Re: [PATCH 3/9] Handle TLS variable lookups when using separate debug object files.

Simon Marchi
2019-02-05T20:06:49Z

[-- Attachment #1: Type: text/plain, Size: 3797 bytes --]

On 2019-02-04 15:02, John Baldwin wrote:
> On 2/2/19 7:52 AM, Simon Marchi wrote:
>> On 2019-01-22 13:42, John Baldwin wrote:
>>> The object files stored in the shared object list are the original
>>> object files, not the separate debug object files. However, when
>>> resolving a TLS variable, the variable is resolved against a separate
>>> debug object file if it exists. In this case,
>>> svr4_fetch_objfile_link_map was failing to find the link map entry
>>> since the debug object file is not in its internal list, only the
>>> original object file.
>>
>> Does this solve an existing issue, or an issue that would come up with
>> the following patches?
>
> I only noticed while working on these patches, but I believe it is a
> generic issue. I tried to reproduce on a Linux box by compiling a
> small
> library with separate debug symbols and a program that linked against
> it
> and running it under gdb, but TLS variables didn't work for me even
> without
> separate debug symbols in my testing. :(
>
> $ cat foo.c
> #include "foo.h"
>
> static __thread int foo_id;
>
> void
> set_foo_id(int id)
> {
> foo_id = id;
> }
>
> int
> get_foo_id(void)
> {
> return foo_id;
> }
> $ cat foo.h
> void set_foo_id(int id);
> int get_foo_id(void);
> $ cat main.c
> #include <stdio.h>
>
> #include "foo.h"
>
> int
> main(void)
> {
>
> set_foo_id(47);
> printf("foo id = %d\n", get_foo_id());
> return (0);
> }
> $ cc -g -fPIC -shared foo.c -o libfoo.so.full
> $ objcopy --only-keep-debug libfoo.so.full libfoo.so.debug
> $ objcopy --strip-debug --add-gnu-debuglink=libfoo.so.debug
> libfoo.so.full libfoo.so
> $ cc -g main.c -o foo -lfoo -L.
> $ gdb foo
> GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
> ...
> (gdb) start
> Temporary breakpoint 1 at 0x7ae: file main.c, line 9.
> Starting program: /home/john/tls_lib/foo
>
> Temporary breakpoint 1, main () at main.c:9
> 9 set_foo_id(47);
> (gdb) p foo_id
> Cannot find thread-local storage for process 3970, shared library
> libfoo.so:
> Cannot find thread-local variables on this target
>
> Then tried it without separate debug file, but that didn't work either:
>
> $ cc -g -fPIC -shared foo.c -o libfoo.so
> $ gdb foo
> GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
> ...
> (gdb) start
> Temporary breakpoint 1 at 0x7ae: file main.c, line 9.
> Starting program: /home/john/tls_lib/foo
>
> Temporary breakpoint 1, main () at main.c:9
> 9 set_foo_id(47);
> (gdb) p foo_id
> Cannot find thread-local storage for process 3982, shared library
> libfoo.so:
> Cannot find thread-local variables on this target
> (gdb) n
> 10 printf("foo id = %d\n", get_foo_id());
> (gdb)
> foo id = 47
> 11 return (0);
> (gdb) p foo_id
> Cannot find thread-local storage for process 3982, shared library
> libfoo.so:
> Cannot find thread-local variables on this target
>
> I would have expected the second case to work and the first to fail and
> for
> the patch to fix the first case.

I did a similar test and hit the same message. I figured it's because
you need to build with -pthread. With -pthread, GDB manages to print
the value in both cases (with and without separate debug info). That's
why I ended up asking you this question, I thought that maybe I just
hadn't reproduced the issue correctly.

I have attached my test case (so we don't have to rewrite the same test
over and over), which you can easily build with and without debug info
(see the Makefile). Does it trigger the problem on FreeBSD? Does it
work for you in both cases on Linux, like it does for me?

Now that I take a look, there might be the gdb.threads/tls-shared.exp
test that does the exact same thing. But there doesn't seem to be a
board file to test with separate debug files out of the box...

Simon

[-- Attachment #2: shared-lib-tls-test.tgz --]
[-- Type: application/x-gzip, Size: 690 bytes --]