diff options
Diffstat (limited to 'gdb/solib-svr4.c')
-rw-r--r-- | gdb/solib-svr4.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 5c87019..5313bf0 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -1461,10 +1461,11 @@ svr4_current_sos_direct (struct svr4_info *info) return head; } -/* Implement the "current_sos" target_so_ops method. */ +/* Implement the main part of the "current_sos" target_so_ops + method. */ static struct so_list * -svr4_current_sos (void) +svr4_current_sos_1 (void) { struct svr4_info *info = get_svr4_info (); @@ -1477,6 +1478,82 @@ svr4_current_sos (void) return svr4_current_sos_direct (info); } +/* Implement the "current_sos" target_so_ops method. */ + +static struct so_list * +svr4_current_sos (void) +{ + struct so_list *so_head = svr4_current_sos_1 (); + struct mem_range vsyscall_range; + + /* Filter out the vDSO module, if present. Its symbol file would + not be found on disk. The vDSO/vsyscall's OBJFILE is instead + managed by symfile-mem.c:add_vsyscall_page. */ + if (gdbarch_vsyscall_range (target_gdbarch (), &vsyscall_range) + && vsyscall_range.length != 0) + { + struct so_list **sop; + + sop = &so_head; + while (*sop != NULL) + { + struct so_list *so = *sop; + + /* We can't simply match the vDSO by starting address alone, + because lm_info->l_addr_inferior (and also l_addr) do not + necessarily represent the real starting address of the + ELF if the vDSO's ELF itself is "prelinked". The l_ld + field (the ".dynamic" section of the shared object) + always points at the absolute/resolved address though. + So check whether that address is inside the vDSO's + mapping instead. + + E.g., on Linux 3.16 (x86_64) the vDSO is a regular + 0-based ELF, and we see: + + (gdb) info auxv + 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffb000 + (gdb) p/x *_r_debug.r_map.l_next + $1 = {l_addr = 0x7ffff7ffb000, ..., l_ld = 0x7ffff7ffb318, ...} + + And on Linux 2.6.32 (x86_64) we see: + + (gdb) info auxv + 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffe000 + (gdb) p/x *_r_debug.r_map.l_next + $5 = {l_addr = 0x7ffff88fe000, ..., l_ld = 0x7ffff7ffe580, ... } + + Dumping that vDSO shows: + + (gdb) info proc mappings + 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0 [vdso] + (gdb) dump memory vdso.bin 0x7ffff7ffe000 0x7ffff7fff000 + # readelf -Wa vdso.bin + [...] + Entry point address: 0xffffffffff700700 + [...] + Section Headers: + [Nr] Name Type Address Off Size + [ 0] NULL 0000000000000000 000000 000000 + [ 1] .hash HASH ffffffffff700120 000120 000038 + [ 2] .dynsym DYNSYM ffffffffff700158 000158 0000d8 + [...] + [ 9] .dynamic DYNAMIC ffffffffff700580 000580 0000f0 + */ + if (address_in_mem_range (so->lm_info->l_ld, &vsyscall_range)) + { + *sop = so->next; + free_so (so); + break; + } + + sop = &so->next; + } + } + + return so_head; +} + /* Get the address of the link_map for a given OBJFILE. */ CORE_ADDR |