This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: time to workaround libc/13097 in fsf gdb?
- From: Pedro Alves <palves at redhat dot com>
- To: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- Cc: Doug Evans <xdje42 at gmail dot com>, "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Date: Sun, 21 Sep 2014 20:12:17 +0100
- Subject: Re: time to workaround libc/13097 in fsf gdb?
- Authentication-results: sourceware.org; auth=none
- References: <CAP9bCMRko50FiANwa+h2FadG-k6Me69N04F+Le-bUnTVLQYKuQ at mail dot gmail dot com> <5411CFAE dot 7040805 at redhat dot com> <20140912115452 dot GA5626 at host2 dot jankratochvil dot net> <5412E3AC dot 80203 at redhat dot com> <20140912123320 dot GA8704 at host2 dot jankratochvil dot net> <5412EB1F dot 40309 at redhat dot com> <20140917201049 dot GA22880 at host2 dot jankratochvil dot net> <541C3FCF dot 4000400 at redhat dot com> <541C409E dot 6010408 at redhat dot com> <20140920213033 dot GA6255 at host2 dot jankratochvil dot net>
On 09/20/2014 10:30 PM, Jan Kratochvil wrote:
> On Fri, 19 Sep 2014 16:41:34 +0200, Pedro Alves wrote:
>> Here it is. WDYT?
> [...]
>> --- a/gdb/solib-svr4.c
>> +++ b/gdb/solib-svr4.c
> [...]
>> @@ -1478,6 +1479,42 @@ 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 objfile *objfile;
>> + struct obj_section *osect;
>> + CORE_ADDR vsyscall_addr = gdbarch_vsyscall_address (target_gdbarch ());
>> +
>> + /* 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 (vsyscall_addr != 0)
>> + {
>> + struct so_list **sop;
>> +
>> + sop = &so_head;
>> + while (*sop != NULL)
>> + {
>> + struct so_list *so = *sop;
>> +
>> + if (so->lm_info->l_addr_inferior == vsyscall_addr)
>
> This won't work as l_addr_inferior (and also l_addr) do not necessarily
> represent the real starting address of the ELF if the ELF itself is
> "prelinked". For some reason vDSOs on some kernels look like prelinked.
>
> kernel-3.16.2-200.fc20.x86_64 appears sane, vDSO is 0-based.
>
> But for example kernel-2.6.32-220.el6.x86_64 is "prelinked", see below.
Ah, didn't know that. That's the sort of thing we should have in
comments in the code, or at least in the commit log.
> That's the pain of solib-svr4.c which is OS-agnostic and so it cannot find out
> start of the ELF file just from link map. gdbserver can find it as it can
> depend on /proc/PID/{s,}maps as its linux-low.c is Linux-specific.
Is it really a pain though? We can just put things behind gdbarch hooks,
like my patch was doing. In fact, symfile-mem.c is already looking
at /proc/PID/maps to find the vdso mapping size. That's exactly done
behind a gdbarch hook:
args.size = 0;
if (gdbarch_find_memory_regions_p (target_gdbarch ()))
(void) gdbarch_find_memory_regions (target_gdbarch (),
find_vdso_size, &args);
>
> kernel-2.6.32-220.el6.x86_64
> (gdb) p *_r_debug.r_map.l_next
> $4 = {l_addr = 140737363566592, l_name = 0x3deba1ade4 "", l_ld = 0x7ffff7ffe580, l_next = 0x7ffff7ffd658, l_prev = 0x3debc21188}
> (gdb) p/x *_r_debug.r_map.l_next
> $5 = {l_addr = 0x7ffff88fe000, l_name = 0x3deba1ade4, l_ld = 0x7ffff7ffe580, l_next = 0x7ffff7ffd658, l_prev = 0x3debc21188}
> # (gdb) p/x *new.lm_info
> # $5 = {l_addr = 0x0, l_addr_inferior = 0x7ffff88fe000, l_addr_p = 0x0, lm_addr = 0x3debc21718, l_ld = 0x7ffff7ffe580, l_next = 0x7ffff7ffd658, l_prev = 0x3debc21188, l_name = 0x3deba1ade4}
> (gdb) info auxv
> 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffe000
> (gdb) info proc mappings
> 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0 [vdso]
Sounds like a predicate like this would work then?
if (vsyscall_start <= so->lm_info->l_ld && so->lm_info->l_ld < vsyscall_end)
We would move the bit that finds the vdso size to the gdbarch_vsyscall_address hook,
and make that new hook return the vsyscall's size too in addition to
the starting address. We can also cache the result somewhere instead
of constantly reopening /proc/PID/maps if necessary.
We can also add a custom linux-specific target_so_ops implementation that
extends svr4's if we want. The target_so_ops to use is also registered
in the gdbarch.
CORE_ADDR vsyscall_start;
CORE_ADDR vsyscall_end;
vsyscall_start = gdbarch_vsyscall_address (target_gdbarch (), &vsyscall_end);
/* 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 (vsyscall_start != 0)
{
struct so_list **sop;
sop = &so_head;
while (*sop != NULL)
{
struct so_list *so = *sop;
if (vsyscall_start <= so->lm_info->l_ld
&& so->lm_info->l_ld < vsyscall_end)
{
... found vdso ...
> (gdb) dump memory vdso.bin 0x7ffff7ffe000 0x7ffff7fff000
> # readelf -Wa vdso.bin
> [...]
> Entry point address: 0xffffffffff700700
> [...]
> Section Headers:
> [Nr] Name Type Address Off Size ES Flg Lk Inf Al
> [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
> [ 1] .hash HASH ffffffffff700120 000120 000038 04 A 2 0 8
> [ 2] .dynsym DYNSYM ffffffffff700158 000158 0000d8 18 A 3 2 8
> [...]
> [ 9] .dynamic DYNAMIC ffffffffff700580 000580 0000f0 10 WA 3 0 8
Thanks,
Pedro Alves