Skip to content

arc binutils generates incorrect thread local storage (TLS) offsets #688

Open
@keith-packard

Description

@keith-packard

I'm working on standalone arc testing for picolibc. One of the tests checks to make sure TLS offsets and relocations work correctly for values that require larger alignment. I discovered that the relocations generated in the output file don't match the positions of the values within the TLS segment. With this bug present, TLS cannot be used on arc.

I've managed to reproduce this in a stand-alone test case.

Source code:

__thread int data_var = 12;
__attribute__((__aligned__(128))) __thread int data_var_128 = 128;
__thread int bss_var;
__attribute__((__aligned__(256))) __thread int bss_var_256;

int __start(void)
{
	return data_var + data_var_128 + bss_var + bss_var_256;
}

Compile command:

$ arc-zephyr-elf-gcc -ffreestanding -nostdlib foo.c -mtp-regno=26
$ arc-zephyr-elf-objdump -St a.out

objdump output:


a.out:     file format elf32-littlearc

SYMBOL TABLE:
00000100 l    d  .text	00000000 .text
00002200 l    d  .tdata	00000000 .tdata
00002300 l    d  .tbss	00000000 .tbss
00002300 l    d  .got	00000000 .got
0000230c l    d  .bss	00000000 .bss
0000230c l    d  .noinit	00000000 .noinit
00000000 l    d  .comment	00000000 .comment
00000000 l    d  .ARC.attributes	00000000 .ARC.attributes
00000000 l    df *ABS*	00000000 foo.c
00000000 l    df *ABS*	00000000 
00002300 l     O .got	00000000 _GLOBAL_OFFSET_TABLE_
00000100 g       .text	00000000 __JLI_TABLE__
0000240c g       .got	00000000 __SDATA_BEGIN__
00000000 g       .tdata	00000004 data_var
00000100 g     F .text	0000003c __start
00000200 g       .tbss	00000004 bss_var_256
00000100 g       .tbss	00000004 bss_var
0000230c g       .got	00000000 __bss_start
00000080 g       .tdata	00000004 data_var_128
0000230c g       .got	00000000 _edata
0000230c g       .bss	00000000 _end



Disassembly of section .text:

00000100 <__start>:
 100:	1cfc b6c8           	st.aw	fp,[sp,-4]
 104:	439b                	mov_s	fp,sp
 106:	2200 3f82 0000 0080 	add	r2,gp,0x80
 10e:	4344                	ld_s	r3,[r2,0]
 110:	2200 3f82 0000 0100 	add	r2,gp,0x100
 118:	4244                	ld_s	r2,[r2,0]
 11a:	635b                	add_s	r3,r3,r2
 11c:	2200 3f82 0000 0200 	add	r2,gp,0x200
 124:	4244                	ld_s	r2,[r2,0]
 126:	635b                	add_s	r3,r3,r2
 128:	2200 3f82 0000 0300 	add	r2,gp,0x300
 130:	4244                	ld_s	r2,[r2,0]
 132:	635a                	add_s	r2,r3,r2
 134:	4040                	mov_s	r0,r2
 136:	1404 341b           	ld.ab	fp,[sp,4]
 13a:	7ee0                	j_s	[blink]

You can see that all of the TLS variables are referenced with incorrect offsets:

                Actual offset    Value in code	Difference

data_var	00000000           0x80		0x80
data_var_128    00000080           0x100	0x80
bss_var         00000100           0x200	0x100
bss_var_256     00000200           0x300	0x100

If this required a computable offset to the TLS base address based on the TLS block alignment (as on ARM), that would be fixable in the linker script and/or TLS register setting code. However, the offsets of data_var and data_var_128 are 0x80 while the offsets of bss_var and bss_var_256 are 0x100.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: ToolchainIssues related to Toolchain (Binutils+GCC+GDB+libs)

    Type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions