This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: time to workaround libc/13097 in fsf gdb?


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]