Bug 959422
| Summary: | TLS variable wrongly relocated on .debug_info | ||
|---|---|---|---|
| Product: | Red Hat Enterprise Linux 6 | Reporter: | Sergio Durigan Junior <sergiodj> |
| Component: | binutils | Assignee: | Patsy Griffin <pfrankli> |
| Status: | CLOSED ERRATA | QA Contact: | Miloš Prchlík <mprchlik> |
| Severity: | unspecified | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | 6.4 | CC: | jan.kratochvil, law, mcermak, mfranc, mprchlik, ohudlick |
| Target Milestone: | rc | ||
| Target Release: | --- | ||
| Hardware: | s390x | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | binutils-2.20.51.0.2-5.41.el6 | Doc Type: | Bug Fix |
| Doc Text: |
Cause: The linker incorrectly handled certain relocations appearing in debugging (dwarf) sections.
Consequence: Debugging information for some variables in TLS sections could be incorrect.
Fix: The linker now correctly handles TLS relocations appearing in debug sections.
Result: Debugging information for variables in TLS sections is correct, allowing those variables to be examined by debuggers and other tools.
|
Story Points: | --- |
| Clone Of: | Environment: | ||
| Last Closed: | 2014-10-14 04:40:42 UTC | Type: | Bug |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. http://rhn.redhat.com/errata/RHBA-2014-1414.html |
Description of problem: Consider the following test file: #include <pthread.h> __thread const char *tls_var = "hello"; int main () { return 0; } When you try to debug this on GDB, and print "tls_var", you get: [root@ibm-z10-05 build-g3]# gcc -lpthread -g3 -O0 ld-fail.c -o ld-fail [root@ibm-z10-05 build-g3]# gdb ./ld-fail -q -ex start -ex 'print tls_var' Reading symbols from /root/sergiodj/src/build-g3/ld-fail...done. Temporary breakpoint 1 at 0x8000057e: file ld-fail.c, line 5. Starting program: /root/sergiodj/src/build-g3/ld-fail [Thread debugging using libthread_db enabled] Temporary breakpoint 1, main () at ld-fail.c:5 5 return 0; $1 = 0x0 However, when you modify the test file to: #include <pthread.h> __thread const char *tls_var = "hello"; int main () { const char *p = tls_var; return 0; } The debugging works: [root@ibm-z10-05 build-g3]# gcc -lpthread -g3 -O0 ld-ok.c -o ld-ok [root@ibm-z10-05 build-g3]# gdb ./ld-ok -q -ex start -ex 'print tls_var' Reading symbols from /root/sergiodj/src/build-g3/ld-ok...done. Temporary breakpoint 1 at 0x8000058a: file ld-ok.c, line 5. Starting program: /root/sergiodj/src/build-g3/ld-ok [Thread debugging using libthread_db enabled] Temporary breakpoint 1, main () at ld-ok.c:5 5 const char *p = tls_var; $1 = 0x800006d8 "hello" Jan Kratochvil and I did some investigation, and here is what has been found: Using below this sample program to see more there the TLS offsets: #include <pthread.h> __thread const char *tls_var = "hello"; __thread const char *tls_var2 = "hello2"; __thread const char *tls_var3 = "hello3"; int main () { const char *p = tls_var; const char *p2 = tls_var2; int i = 10; const char *p3 = tls_var3; return 0; } So some investigations: (1) It works without -g, just with .symtab: (gdb) p *(char **)&tls_var $1 = 0x80000728 "hello" .symtab really looks fine with all the cases I tried: 70: 0000000000000000 8 TLS GLOBAL DEFAULT 18 tls_var 61: 0000000000000008 8 TLS GLOBAL DEFAULT 18 tls_var2 72: 0000000000000010 8 TLS GLOBAL DEFAULT 18 tls_var3 Wrong is only DWARF there: <1><173>: Abbrev Number: 8 (DW_TAG_variable) DW_AT_name : tls_var DW_AT_location : 10 byte block: 3 ff ff ff ff ff ff ff e8 e0 (DW_OP_addr: ffffffffffffffe8; DW_OP_GNU_push_tls_address) <1><18e>: Abbrev Number: 8 (DW_TAG_variable) DW_AT_name : tls_var2 DW_AT_location : 10 byte block: 3 ff ff ff ff ff ff ff f0 e0 (DW_OP_addr: fffffffffffffff0; DW_OP_GNU_push_tls_address) <1><1aa>: Abbrev Number: 8 (DW_TAG_variable) DW_AT_name : tls_var3 DW_AT_location : 10 byte block: 3 ff ff ff ff ff ff ff f8 e0 (DW_OP_addr: fffffffffffffff8; DW_OP_GNU_push_tls_address) (2) Even with DWARF when I adjusted the offset GDB works then fine: linux-thread-db.c: So a 32-bit debugger can not access 64-bit TLS through this. */ offset-=0xffffffffffffffe8; err = info->td_thr_tls_get_addr_p (&thread_info->private->th, The .S file looks somehow fine to me, as you wrote above: > .quad tls_var@DTPOFF In fact .o file also looks fine to me: Relocation section '.rela.debug_info' at offset 0xfb8 contains 12 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000185 0000001200000035 R_390_TLS_LDO64 0000000000000000 tls_var + 0 00000000000001a1 0000001300000035 R_390_TLS_LDO64 0000000000000008 tls_var2 + 0 00000000000001bd 0000001400000035 R_390_TLS_LDO64 0000000000000010 tls_var3 + 0 Symbol table '.symtab' contains 22 entries: Num: Value Size Type Bind Vis Ndx Name 18: 0000000000000000 8 TLS GLOBAL DEFAULT 12 tls_var 19: 0000000000000008 8 TLS GLOBAL DEFAULT 12 tls_var2 20: 0000000000000010 8 TLS GLOBAL DEFAULT 12 tls_var3 But the binary has wrongly relocated .debug_info. Therefore the bug is in ld. Version-Release number of selected component (if applicable): binutils-2.20.51.0.2-5.36.el6.s390x How reproducible: Always. Steps to Reproduce: Described above. Actual results: TLS variable is not printed correctly due to wrongly relocated .debug_info. Expected results: TLS variable should be printed correctly.