Fix TLS access for -static -pthread

Message ID 539018F9.5060307@codesourcery.com
State Superseded
Headers

Commit Message

Yao Qi June 5, 2014, 7:15 a.m. UTC
  On 04/10/2014 07:52 PM, Jan Kratochvil wrote:
> +if { "$have_tls" != "" } {
> +    if ![runto_main] {
> +	return -1
> +    }
> +    gdb_breakpoint [gdb_get_line_number "tlsvar-is-set"]
> +    gdb_continue_to_breakpoint "tlsvar-is-set" ".* tlsvar-is-set .*"
> +    gdb_test "p tlsvar" " = 2" "tlsvar in thread"
> +    gdb_test "thread 1" ".*"
> +    # Unwind from pthread_join.
> +    gdb_test "up 10" " in main .*"

This is racy.  When child thread hits breakpoint, the main thread may
not go into pthread_join yet and may not be unwind to main.
On target arm-none-linux-gnueabi, I see

thread 1^M
[Switching to thread 1 (Thread 5784)]^M
#0  clone () at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:62^M
62              cmp     r0, #0^M
(gdb) PASS: gdb.threads/staticthreads.exp: thread 1
up 10^M
#2  0xbe8ea7e4 in ?? ()^M
(gdb) FAIL: gdb.threads/staticthreads.exp: up 10
p tlsvar^M
$2 = 1^M
(gdb) PASS: gdb.threads/staticthreads.exp: tlsvar in main

This patch is to set another breakpoint at the end of main, so that
main thread will hit it, and we can check the value of tlsvar then.
It is safe and we don't have to worry about whether gdb is able to
unwind from pthread library to main function or not.

Is it good to you? b.t.w, this case is UNSUPPORTED on FC 20, because
staticthreads.c can't be compiled.  I guess this case requires
some recent version of glibc.
  

Comments

Jan Kratochvil June 5, 2014, 8:06 a.m. UTC | #1
On Thu, 05 Jun 2014 09:15:05 +0200, Yao Qi wrote:
[...]
> thread 1^M
> [Switching to thread 1 (Thread 5784)]^M
> #0  clone () at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:62^M
> 62              cmp     r0, #0^M
> (gdb) PASS: gdb.threads/staticthreads.exp: thread 1
> up 10^M
> #2  0xbe8ea7e4 in ?? ()^M
> (gdb) FAIL: gdb.threads/staticthreads.exp: up 10

This is a bug of unwinding clone() at this PC.  IIRC even x86_64 has this or
similar CFI bug, though.


> This patch is to set another breakpoint at the end of main, so that
> main thread will hit it, and we can check the value of tlsvar then.
> It is safe and we don't have to worry about whether gdb is able to
> unwind from pthread library to main function or not.

I have to warn that it may be a bit weaker test, it never tests both threads
TLS access during the same stop, it tests only the current thread.

But it still tests the patch works so I am fine with it (not an approval).


> Is it good to you? b.t.w, this case is UNSUPPORTED on FC 20, because
> staticthreads.c can't be compiled.  I guess this case requires
> some recent version of glibc.

I do not see any unsupported case on
 * Fedora 20 x86_64 updates-testing disabled with debuginfos
 * Fedora 20 x86_64 updates-testing enabled with debuginfos
 * Fedora 20 x86_64 updates-testing enabled without debuginfos
 * Fedora Rawhide x86_64 with debuginfos
for both nat and gdbserver runs.

Sergio said he saw some problem with mktemp symbol on some Fedora but I do not
have that reproducible so I cannot fix it.


Thanks,
Jan
  
Pedro Alves June 5, 2014, 3:17 p.m. UTC | #2
On 06/05/2014 09:06 AM, Jan Kratochvil wrote:
> On Thu, 05 Jun 2014 09:15:05 +0200, Yao Qi wrote:
> [...]
>> thread 1^M
>> [Switching to thread 1 (Thread 5784)]^M
>> #0  clone () at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:62^M
>> 62              cmp     r0, #0^M
>> (gdb) PASS: gdb.threads/staticthreads.exp: thread 1
>> up 10^M
>> #2  0xbe8ea7e4 in ?? ()^M
>> (gdb) FAIL: gdb.threads/staticthreads.exp: up 10

It'd be nice if this was reported to glibc upstream.

> This is a bug of unwinding clone() at this PC.  IIRC even x86_64 has this or
> similar CFI bug, though.

I think it's fixed.  It works here on f20:

(gdb) bt
#0  thread_function0 (arg=0x0) at threads.c:63
#1  0x000000373c807f33 in start_thread (arg=0x7ffff7fc6700) at pthread_create.c:309
#2  0x000000373bcf4ded in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb)

It seems this bug ends up easily happening on new ports:

 https://sourceware.org/ml/libc-ports/2012-05/msg00068.html
 https://sourceware.org/ml/libc-alpha/2014-01/msg00337.html

Sounds like nobody has a test to catch this.  Assuming glibc's
backtrace() makes use of CFI, glibc itself could have one.
But maybe we should be have it too - a GNU/Linux specific,
but arch-independent test that makes sure a backtrace in a thread
always stops at clone.  Likewise for catching bogus frames beyond
'_start' in the main thread (with "set backtrace past-main on").
  
Yao Qi June 6, 2014, 2:34 a.m. UTC | #3
On 06/05/2014 04:06 PM, Jan Kratochvil wrote:
> I do not see any unsupported case on
>  * Fedora 20 x86_64 updates-testing disabled with debuginfos
>  * Fedora 20 x86_64 updates-testing enabled with debuginfos
>  * Fedora 20 x86_64 updates-testing enabled without debuginfos
>  * Fedora Rawhide x86_64 with debuginfos
> for both nat and gdbserver runs.

My machine is Fedora 20 x86, and staticthreads.c can't be compiled
like this:

Executing on host: gcc
../../../../git/gdb/testsuite/gdb.threads/staticthreads.c  -static
-DHAVE_TLS -g  -lpthread -lm   -o
/home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads
   (timeout = 300)
spawn -ignore SIGHUP gcc
../../../../git/gdb/testsuite/gdb.threads/staticthreads.c -static
-DHAVE_TLS -g -lpthread -lm -o
/home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads^M
/usr/bin/ld: cannot find -lpthread^M
/usr/bin/ld: cannot find -lm^M
/usr/bin/ld: cannot find -lc^M
collect2: error: ld returned 1 exit status^M
compiler exited with status 1
output is:
/usr/bin/ld: cannot find -lpthread^M
/usr/bin/ld: cannot find -lm^M
/usr/bin/ld: cannot find -lc^M
collect2: error: ld returned 1 exit status^M

Executing on host: gcc
../../../../git/gdb/testsuite/gdb.threads/staticthreads.c  -static
-DHAVE_TLS -g  -lm   -o
/home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads
   (timeout = 300)
spawn -ignore SIGHUP gcc
../../../../git/gdb/testsuite/gdb.threads/staticthreads.c -static
-DHAVE_TLS -g -lm -o
/home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads^M
/usr/bin/ld: cannot find -lm^M
/usr/bin/ld: cannot find -lc^M
collect2: error: ld returned 1 exit status^M
compiler exited with status 1
output is:
/usr/bin/ld: cannot find -lm^M
/usr/bin/ld: cannot find -lc^M
collect2: error: ld returned 1 exit status

My glibc version is 2.18 12.fc20 and gcc version is 4.8.2 7.fc20.
  
Sergio Durigan Junior June 6, 2014, 5:34 a.m. UTC | #4
On Thursday, June 05 2014, Jan Kratochvil wrote:

>> Is it good to you? b.t.w, this case is UNSUPPORTED on FC 20, because
>> staticthreads.c can't be compiled.  I guess this case requires
>> some recent version of glibc.
>
> I do not see any unsupported case on
>  * Fedora 20 x86_64 updates-testing disabled with debuginfos
>  * Fedora 20 x86_64 updates-testing enabled with debuginfos
>  * Fedora 20 x86_64 updates-testing enabled without debuginfos
>  * Fedora Rawhide x86_64 with debuginfos
> for both nat and gdbserver runs.
>
> Sergio said he saw some problem with mktemp symbol on some Fedora but I do not
> have that reproducible so I cannot fix it.

I saw this:

  Executing on host: gcc ../../../gdb/testsuite/gdb.threads/staticthreads.c  -static -DHAVE_TLS -g  -lpthread -lm   -o /patch/to/gdb/testsuite/gdb.threads/staticthreads    (timeout = 300)
  spawn -ignore SIGHUP gcc ../../../gdb/testsuite/gdb.threads/staticthreads.c -static -DHAVE_TLS -g -lpthread -lm -o /patch/to/gdb/testsuite/gdb.threads/staticthreads^M
  /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libpthread.a(libpthread.o): In function `sem_open':^M
  (.text+0x774d): warning: the use of `mktemp' is dangerous, better use `mkstemp'^M
  output is:
  /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libpthread.a(libpthread.o): In function `sem_open':^M
  (.text+0x774d): warning: the use of `mktemp' is dangerous, better use `mkstemp'^M

This is on RHEL-6.5, with gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4).

I had to do a small workaround in gdb_compile_pthreads (from
testsuite/lib/gdb.exp) in order to make the compilation succeed.
  
Yao Qi June 6, 2014, 6:14 a.m. UTC | #5
On 06/06/2014 10:34 AM, Yao Qi wrote:
> My machine is Fedora 20 x86, and staticthreads.c can't be compiled
> like this:
> 
> Executing on host: gcc
> ../../../../git/gdb/testsuite/gdb.threads/staticthreads.c  -static
> -DHAVE_TLS -g  -lpthread -lm   -o
> /home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads
>    (timeout = 300)
> spawn -ignore SIGHUP gcc
> ../../../../git/gdb/testsuite/gdb.threads/staticthreads.c -static
> -DHAVE_TLS -g -lpthread -lm -o
> /home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads^M
> /usr/bin/ld: cannot find -lpthread^M
> /usr/bin/ld: cannot find -lm^M
> /usr/bin/ld: cannot find -lc^M
> collect2: error: ld returned 1 exit status^M
> compiler exited with status 1
> output is:
> /usr/bin/ld: cannot find -lpthread^M
> /usr/bin/ld: cannot find -lm^M
> /usr/bin/ld: cannot find -lc^M
> collect2: error: ld returned 1 exit status^M

Installed glibc-static on my machine, then it is compiled successfully.
  
Jan Kratochvil June 6, 2014, 2:20 p.m. UTC | #6
On Fri, 06 Jun 2014 08:14:28 +0200, Yao Qi wrote:
> On 06/06/2014 10:34 AM, Yao Qi wrote:
> > My machine is Fedora 20 x86, and staticthreads.c can't be compiled
> > like this:
> > 
> > Executing on host: gcc
> > ../../../../git/gdb/testsuite/gdb.threads/staticthreads.c  -static
> > -DHAVE_TLS -g  -lpthread -lm   -o
> > /home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads
> >    (timeout = 300)
> > spawn -ignore SIGHUP gcc
> > ../../../../git/gdb/testsuite/gdb.threads/staticthreads.c -static
> > -DHAVE_TLS -g -lpthread -lm -o
> > /home/yao/Source/gnu/gdb/build-git/x86/gdb/testsuite/gdb.threads/staticthreads^M
> > /usr/bin/ld: cannot find -lpthread^M
> > /usr/bin/ld: cannot find -lm^M
> > /usr/bin/ld: cannot find -lc^M
> > collect2: error: ld returned 1 exit status^M
> > compiler exited with status 1
> > output is:
> > /usr/bin/ld: cannot find -lpthread^M
> > /usr/bin/ld: cannot find -lm^M
> > /usr/bin/ld: cannot find -lc^M
> > collect2: error: ld returned 1 exit status^M
> 
> Installed glibc-static on my machine, then it is compiled successfully.

Therefore considering the current FSF GDB state as correct.


Jan
  
Jan Kratochvil June 6, 2014, 2:21 p.m. UTC | #7
On Fri, 06 Jun 2014 07:34:17 +0200, Sergio Durigan Junior wrote:
> On Thursday, June 05 2014, Jan Kratochvil wrote:
> > Sergio said he saw some problem with mktemp symbol on some Fedora but I do not
> > have that reproducible so I cannot fix it.
> 
> I saw this:
> 
>   Executing on host: gcc ../../../gdb/testsuite/gdb.threads/staticthreads.c  -static -DHAVE_TLS -g  -lpthread -lm   -o /patch/to/gdb/testsuite/gdb.threads/staticthreads    (timeout = 300)
>   spawn -ignore SIGHUP gcc ../../../gdb/testsuite/gdb.threads/staticthreads.c -static -DHAVE_TLS -g -lpthread -lm -o /patch/to/gdb/testsuite/gdb.threads/staticthreads^M
>   /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libpthread.a(libpthread.o): In function `sem_open':^M
>   (.text+0x774d): warning: the use of `mktemp' is dangerous, better use `mkstemp'^M
>   output is:
>   /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libpthread.a(libpthread.o): In function `sem_open':^M
>   (.text+0x774d): warning: the use of `mktemp' is dangerous, better use `mkstemp'^M
> 
> This is on RHEL-6.5, with gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4).
> 
> I had to do a small workaround in gdb_compile_pthreads (from
> testsuite/lib/gdb.exp) in order to make the compilation succeed.

OK, that may be nice to also submit upstream - but according to the Yao's mail
	Message-ID: <53915C44.3010904@codesourcery.com>
it is unrelated to the problem being discussed in this thread.  Sorry for my
wrong expectation.


Jan
  
Jan Kratochvil June 6, 2014, 3:03 p.m. UTC | #8
On Thu, 05 Jun 2014 17:17:41 +0200, Pedro Alves wrote:
> On 06/05/2014 09:06 AM, Jan Kratochvil wrote:
> > On Thu, 05 Jun 2014 09:15:05 +0200, Yao Qi wrote:
> > [...]
> >> thread 1^M
> >> [Switching to thread 1 (Thread 5784)]^M
> >> #0  clone () at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:62^M
> >> 62              cmp     r0, #0^M
> >> (gdb) PASS: gdb.threads/staticthreads.exp: thread 1
> >> up 10^M
> >> #2  0xbe8ea7e4 in ?? ()^M
> >> (gdb) FAIL: gdb.threads/staticthreads.exp: up 10
> 
> It'd be nice if this was reported to glibc upstream.

I agree and it is unrelated to the unspecific x86_64 issue I mentioned.


> > This is a bug of unwinding clone() at this PC.  IIRC even x86_64 has this or
> > similar CFI bug, though.
> 
> I think it's fixed.  It works here on f20:

I agree the issue I could not remember much is a different one, I have filed
it now as:
	[x86_64] conditional cfi_undefined missing right after clone()
	https://sourceware.org/bugzilla/show_bug.cgi?id=17033
But it is really unrelated to this mail thread.


Jan
  

Patch

diff --git a/gdb/testsuite/gdb.threads/staticthreads.c b/gdb/testsuite/gdb.threads/staticthreads.c
index 5c8eabe..a11359c 100644
--- a/gdb/testsuite/gdb.threads/staticthreads.c
+++ b/gdb/testsuite/gdb.threads/staticthreads.c
@@ -76,6 +76,6 @@  main (int argc, char **argv)
     pthread_join (thread, NULL);
   }
 
-  pthread_attr_destroy (&attr);
+  pthread_attr_destroy (&attr); /* tlsvar-is-read */
   return 0;
 }
diff --git a/gdb/testsuite/gdb.threads/staticthreads.exp b/gdb/testsuite/gdb.threads/staticthreads.exp
index 9fa625a..3e23b5b 100644
--- a/gdb/testsuite/gdb.threads/staticthreads.exp
+++ b/gdb/testsuite/gdb.threads/staticthreads.exp
@@ -104,8 +104,9 @@  if { "$have_tls" != "" } {
     gdb_breakpoint [gdb_get_line_number "tlsvar-is-set"]
     gdb_continue_to_breakpoint "tlsvar-is-set" ".* tlsvar-is-set .*"
     gdb_test "p tlsvar" " = 2" "tlsvar in thread"
+
     gdb_test "thread 1" ".*"
-    # Unwind from pthread_join.
-    gdb_test "up 10" " in main .*"
+    gdb_breakpoint ${srcfile}:[gdb_get_line_number "tlsvar-is-read"]
+    gdb_continue_to_breakpoint "tlsvar-is-read" ".* tlsvar-is-read .*"
     gdb_test "p tlsvar" " = 1" "tlsvar in main"
 }