about summary refs log tree commit diff
path: root/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-06-27 15:32:09 -0400
committerRich Felker <dalias@aerifal.cx>2018-06-27 15:57:57 -0400
commit8b8fb7f03721c42445f982582f462144ab60a1a0 (patch)
tree19bf337a9afdb1f2b6199c908a9b214ea54caf70 /ldso
parente829695fcc880f8578c2b964ea2d090f0016c9d7 (diff)
downloadmusl-8b8fb7f03721c42445f982582f462144ab60a1a0.tar.gz
musl-8b8fb7f03721c42445f982582f462144ab60a1a0.tar.xz
musl-8b8fb7f03721c42445f982582f462144ab60a1a0.zip
correctly handle non-matching symbols in dladdr
based on patch by Axel Siebenborn, with fixes discussed on the mailing
list after submission and and rebased around the UB fix in commit
e829695fcc880f8578c2b964ea2d090f0016c9d7.

avoid spurious symbol matches by dladdr beyond symbol size. for
symbols with a size recorded, only match if the queried address lies
within the address range determined by the symbol address and size.
for symbols with no size recorded, the old closest-match behavior is
kept, as long as there is no intervening symbol with a recorded size.

the case where no symbol is matched, but the address does lie within
the memory range of a shared object, is specified as success. fix the
return value and produce a valid (with null dli_sname and dli_saddr)
Dl_info structure.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/dynlink.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 6b05b5e0..31c50609 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1978,6 +1978,11 @@ int dladdr(const void *addr_arg, Dl_info *info)
 			size_t symaddr = (size_t)laddr(p, sym->st_value);
 			if (symaddr > addr || symaddr < best)
 				continue;
+			if (sym->st_size && symaddr+sym->st_size <= addr) {
+				best = 0;
+				bestsym = 0;
+				continue;
+			}
 			best = symaddr;
 			bestsym = sym;
 			if (addr == symaddr)
@@ -1985,13 +1990,17 @@ int dladdr(const void *addr_arg, Dl_info *info)
 		}
 	}
 
-	if (!best) return 0;
+	info->dli_fname = p->name;
+	info->dli_fbase = p->map;
+
+	if (!best) {
+		info->dli_sname = 0;
+		info->dli_saddr = 0;
+		return 1;
+	}
 
 	if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC)
 		best = (size_t)(p->funcdescs + (bestsym - p->syms));
-
-	info->dli_fname = p->name;
-	info->dli_fbase = p->map;
 	info->dli_sname = strings + bestsym->st_name;
 	info->dli_saddr = (void *)best;