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: [patch+7.5.1] Work around PR libc/13097 "linux-vdso.so.1" #3


On 11/23/2012 12:39 PM, Jan Kratochvil wrote:
> On Fri, 23 Nov 2012 13:02:41 +0100, Pedro Alves wrote:
>> Won't real file based DSOs in the loader list _always_ be full paths,
>> never relative paths?  I'd think we could always ignore DSOs whose
>> path doesn't start with '/', everywhere.
> 
> :|gcc -shared -fPIC -o x.so -x c -;echo 'main(){}'|gcc -o x ./x.so -x c -;gdb ./x -ex start -ex 'p *_r_debug.r_map' -ex 'p *_r_debug.r_map.l_next' -ex 'p *_r_debug.r_map.l_next.l_next' -ex 'p *_r_debug.r_map.l_next.l_next.l_next' -ex 'p *_r_debug.r_map.l_next.l_next.l_next.l_next' -ex 'p *_r_debug.r_map.l_next.l_next.l_next.l_next.l_next'
> 
> $1 = {l_addr = 0, l_name = 0x37e3a1bd69 "", l_ld = 0x600778, l_next = 0x37e3c23818, l_prev = 0x0}
> $2 = {l_addr = 140737363566592, l_name = 0x37e3a1bd69 "", l_ld = 0x7ffff7ffe488, l_next = 0x7ffff7ffd648, l_prev = 0x37e3c23288}
> $3 = {l_addr = 140737352024064, l_name = 0x7ffff7ffd640 "./x.so", l_ld = 0x7ffff7ffc5e8, l_next = 0x7ffff7dd5000, l_prev = 0x37e3c23818}
>                                                         ^^^^^^^^
> $4 = {l_addr = 0, l_name = 0x7ffff7ffdb60 "/lib64/libc.so.6", l_ld = 0x37e45b0b40, l_next = 0x37e3c22998, l_prev = 0x7ffff7ffd648}
> $5 = {l_addr = 0, l_name = 0x400200 "/lib64/ld-linux-x86-64.so.2", l_ld = 0x37e3c21de8, l_next = 0x0, l_prev = 0x7ffff7dd5000}
> 
> So file based solibs do not have to start with '/'.

Interesting.

This means that looking for relative path DSOs in the file system is currently
depending on GDB's current directory.  E.g., take your example, stick a "sleep(1000);" in
main, compile, and start x outside gdb.  Then, attach to it, and make sure gdb's cwd is not
the same as the directory holding the 'x' binary:

(gdb) info sharedlibrary
>From                To                  Syms Read   Shared Object Library
                                        No          ./x.so
0x0000003d25e1ef60  0x0000003d25f5f7a0  Yes         /lib64/libc.so.6
0x0000003d25a00b20  0x0000003d25a1a2e9  Yes         /lib64/ld-linux-x86-64.so.2
(gdb) info sharedlibrary
>From                To                  Syms Read   Shared Object Library
                                        No          ./x.so
0x0000003d25e1ef60  0x0000003d25f5f7a0  Yes         /lib64/libc.so.6
0x0000003d

GDB should be able to know where "./x.so" is...  But even just looking for the file
relative to the inferior's PWD isn't fully correct, as the inferior might have changed
current directory before GDB attaches.

> Besides that there is no standard for any such rule and I consider this patch
> only as a workaround of a WONTFIXed glibc PR.  

Given the new order of glibc maintenance, if we believe glibc's WONTFIX was
wrong, then we should reopen the PR, and retry discussing the issue.

> In such case I believe the impact should be minimal.
> 
> Maybe there is even a way how to make l_name really "x.so" above, not sure.

Yeah.  I haven't looked at relevant glibc's code, but the ELF spec says (thanks to Matt
Rice for pointing at it):

 "If a shared object name has one or more slash (/) characters anywhere in the name, such as
 /usr/lib/lib2 above or directory/file, the dynamic linker uses that string directly as the path
 name. If the name has no slashes, such as lib1 above, three facilities specify shared
 object path search-ing, with the following precedence."

So your example had a slash.  If there'd be no slash, the below applies:

 "First, the dynamic array tag DT_RPATH may give a string that holds a list of directories,
  separated by colons (:). For example, the string /home/dir/lib:/home/dir2/lib: tells the
  dynamic linker to search first the directory /home/dir/lib, then /home/dir2/lib, and then
  the current directory to find dependencies.
  Second, a variable called LD_LIBRARY_PATH in the process environment [see exec(BA_OS)] may
  hold a list of directories as above, optionally followed by a semicolon (;) and another
  directory list."

  The following values would be equivalent to the previous example:
  LD_LIBRARY_PATH=/home/dir/lib:/home/dir2/lib:
  LD_LIBRARY_PATH=/home/dir/lib;/home/dir2/lib:
  LD_LIBRARY_PATH=/home/dir/lib:/home/dir2/lib:;
  All LD_LIBRARY_PATH directories are searched after those from DT_RPATH. Although some
  programs (such as the link editor) treat the lists before and after the semicolon differently,
  the dynamic linker does not. Nevertheless, the dynamic linker accepts the semicolon
  notation, with the semantics described above.
  Finally, if the other two groups of directories fail to locate the desired library, the dynamic
  linker searches /usr/lib."

GDB does look at LD_LIBRARY_PATH, but doesn't at DT_RPATH.  And gdb also looks at PATH.
But this is all best-effort.  It reminds me of the the libraries-changed-on-disk-already
problem.  Similar kind of problem - we miss a reliable way to find the exact same file
the inferior loaded, and that'd need better help from the kernel or the loader. My favorite
is opening a DSO symlink like we /proc/PID/exe.  Maybe the checkpoint/restore work going on
the kernel has given us the interfaces already.

-- 
Pedro Alves


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