This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
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