Hi, On Mon, 18 Dec 2017, Nancy wrote:
> tls.c: > __thread int i=10; > > $gcc -g -c -save-temps tls.c > $readelf -r tls.o > Relocation section '.rela.debug_info' at offset 0x2d0 contains 6 entries: > Offset Info Type Sym. Value Sym. Name + > Addend > 000000000006 00070000000a R_X86_64_32 0000000000000000 .debug_abbrev + > 0 > 00000000000c 000a0000000a R_X86_64_32 0000000000000000 .debug_str + 11 > 000000000011 000a0000000a R_X86_64_32 0000000000000000 .debug_str + 3f > 000000000015 000a0000000a R_X86_64_32 0000000000000000 .debug_str + 0 > 000000000019 00090000000a R_X86_64_32 0000000000000000 .debug_line + 0 > 000000000028 000d00000015 R_X86_64_DTPOFF32 0000000000000000 i + 0 > > Relocation section '.rela.debug_aranges' at offset 0x360 contains 1 entries: > Offset Info Type Sym. Value Sym. Name + > Addend > 000000000006 00060000000a R_X86_64_32 0000000000000000 .debug_info + 0 > > I can't find any code in cc1 or as that generate R_X86_64_DTPOFF32 in > .rela.debug_info section. Did I miss something? To expand on what Nathan said: the debug info needs to refer to the location of the variable 'i' somehow, and as it's a TLS variable that location is thread specific as well, and so the normal data relocations can't be used. So the dwarf info contains a location expression that uses this relocation and a GNU extension to push the tls address into the expression stack. See e.g. the verbose asm output for the above file, the DIE for 'i' will contain something like this: .uleb128 0x2 # (DIE (0x1d) DW_TAG_variable) .ascii "i\0" # DW_AT_name .byte 0x1 # DW_AT_decl_file (x.c) .byte 0x1 # DW_AT_decl_line .long 0x31 # DW_AT_type # DW_AT_external .uleb128 0xa # DW_AT_location .byte 0xe # DW_OP_const8u .long i@dtpoff, 0 .byte 0xe0 # DW_OP_GNU_push_tls_address The 'i@dtpoff' is the field that causes the DTPOFF32 relocation to be created by the assembler. Ciao, Michael.