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.