git: dfd00261c95a - main - librtld_db: Handle shlibs with discontiguous mappings.

From: Chuck Silvers <chs_at_FreeBSD.org>
Date: Fri, 03 Dec 2021 19:09:08 UTC
The branch main has been updated by chs:

URL: https://cgit.FreeBSD.org/src/commit/?id=dfd00261c95a9839ba528f7e052d9bcac19f2b14

commit dfd00261c95a9839ba528f7e052d9bcac19f2b14
Author:     Chuck Silvers <chs@FreeBSD.org>
AuthorDate: 2021-12-03 19:03:32 +0000
Commit:     Chuck Silvers <chs@FreeBSD.org>
CommitDate: 2021-12-03 19:07:30 +0000

    librtld_db: Handle shlibs with discontiguous mappings.
    
    Some shared libraries specify mappings that leave a gap (actually a
    MAP_GUARD mapping) in between the file mappings (libcrypto.so was
    the one I found), and this would cause rd_loadobj_iter() to report
    the mapping info incorrectly, leaving out rdl_path and misreporting
    rdl_offset for file mappings after the gap.  Fix rd_loadobj_iter()
    to handle this situation.
    
    Reviewed by:    markj
    Sponsored by:   Netflix
    Differential Revision:  https://reviews.freebsd.org/D32950
---
 lib/librtld_db/rtld_db.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/librtld_db/rtld_db.c b/lib/librtld_db/rtld_db.c
index 9edeecfb95c5..18e16f36e62c 100644
--- a/lib/librtld_db/rtld_db.c
+++ b/lib/librtld_db/rtld_db.c
@@ -165,6 +165,7 @@ rd_loadobj_iter(rd_agent_t *rdap, rl_iter_f *cb, void *clnt_data)
 	rd_loadobj_t rdl;
 	rd_err_e ret;
 	uintptr_t base;
+	uint32_t offset;
 	int cnt, i;
 
 	DPRINTF("%s\n", __func__);
@@ -190,11 +191,12 @@ rd_loadobj_iter(rd_agent_t *rdap, rl_iter_f *cb, void *clnt_data)
 			if (kve->kve_vn_fileid != fileid) {
 				base = kve->kve_start;
 				fileid = kve->kve_vn_fileid;
-				path = kve->kve_path;
 			}
+			path = kve->kve_path;
+			offset = kve->kve_start - base;
 		} else {
-			base = 0;
 			path = NULL;
+			offset = 0;
 		}
 		memset(&rdl, 0, sizeof(rdl));
 		/*
@@ -202,7 +204,7 @@ rd_loadobj_iter(rd_agent_t *rdap, rl_iter_f *cb, void *clnt_data)
 		 */
 		rdl.rdl_saddr = kve->kve_start;
 		rdl.rdl_eaddr = kve->kve_end;
-		rdl.rdl_offset = kve->kve_start - base;
+		rdl.rdl_offset = offset;
 		if (kve->kve_protection & KVME_PROT_READ)
 			rdl.rdl_prot |= RD_RDL_R;
 		if (kve->kve_protection & KVME_PROT_WRITE)