Hi, I am tracking some TLS issues with lld and found that it is generating wrong tbss size for case where multiple modules have non initialized threads variables. For instance: -- t0.c -- __thread int x0; __thread int x1; __thread int x2; extern __thread int e0; extern __thread int e1; extern __thread int e2; extern __thread int e3; int foo0 () { return x0; } int main () { return x0; } -- t1.c -- __thread int e0; __thread int e1; __thread int e2; __thread int e3; --- lld is generating (for aarch64): [14] .tbss NOBITS 0000000000401000 00001000 0000000000000010 0000000000000000 WAT 0 0 4 Where is just taking in consideration the largest tbss segment, not all from all objects. ld generates a correct output: [17] .tbss NOBITS 0000000000410dec 00000dec 000000000000001c 0000000000000000 WAT 0 0 4 My initial idea is that 'lib/ReaderWriter/ELF/SegmentChunks.cpp' / Segment<ELFT>::assignVirtualAddress is setting wrong slice values, however playing with this I could not find a correct logic to handle the TBSS. Any ideas where lld is possible messing the TBSS segments sizes?
Are you saying it generates wrong section size? Tbss is very special and I checked the behavior on X86_64 to model it. It does not account for virtual address increase as libc allocates it.> On Jun 2, 2015, at 17:20, Adhemerval Zanella <adhemerval.zanella at linaro.org> wrote: > > Hi, > > I am tracking some TLS issues with lld and found that it is > generating wrong tbss size for case where multiple modules > have non initialized threads variables. For instance: > > -- t0.c -- > > __thread int x0; > __thread int x1; > __thread int x2; > > extern __thread int e0; > extern __thread int e1; > extern __thread int e2; > extern __thread int e3; > > int foo0 () > { > return x0; > } > > int main () > { > return x0; > } > > -- t1.c -- > > __thread int e0; > __thread int e1; > __thread int e2; > __thread int e3; > > --- > > lld is generating (for aarch64): > > [14] .tbss NOBITS 0000000000401000 00001000 > 0000000000000010 0000000000000000 WAT 0 0 4 > > Where is just taking in consideration the largest tbss segment, not all > from all objects. ld generates a correct output: > > [17] .tbss NOBITS 0000000000410dec 00000dec > 000000000000001c 0000000000000000 WAT 0 0 4 > > My initial idea is that 'lib/ReaderWriter/ELF/SegmentChunks.cpp' / > Segment<ELFT>::assignVirtualAddress is setting wrong slice values, however > playing with this I could not find a correct logic to handle the TBSS. > > Any ideas where lld is possible messing the TBSS segments sizes?
Hi, Yes, ldd is generating wrong tbss size. It is just considering one tbss section and not calculating all sections from all objects. The following example on x86_64 shows the issue: --- t0.c --- #include <stdio.h> extern __thread int t0; extern __thread int t1; extern __thread int t2; extern __thread int t3; __thread int t4; __thread int t5; __thread int t6; __thread int t7; int main () { t4 = 1; t5 = 2; t6 = 3; t7 = 4; printf ("%i %i %i %i\n", t0, t1, t2, t3); printf ("%i %i %i %i\n", t4, t5, t6, t7); return 0; } --- t1.c --- __thread int t0; __thread int t1; __thread int t2; __thread int t3; ------------- If you build with lld you will see: $ ./t-lld 1 1 1 1 1 2 3 4 Because t{4,5,6,7} space is not taking in consideration. In fact if you check the resulting tbss for the test: [15] .tbss NOBITS 0000000000401000 00001000 0000000000000010 0000000000000000 WAT 0 0 4 Its size is just 0x10 (4 int), where it should be 0x20 (8 ints). On 02-06-2015 21:14, Shankar Easwaram wrote:> Are you saying it generates wrong section size? Tbss is very special and I checked the behavior on X86_64 to model it. It does not account for virtual address increase as libc allocates it. > > >> On Jun 2, 2015, at 17:20, Adhemerval Zanella <adhemerval.zanella at linaro.org> wrote: >> >> Hi, >> >> I am tracking some TLS issues with lld and found that it is >> generating wrong tbss size for case where multiple modules >> have non initialized threads variables. For instance: >> >> -- t0.c -- >> >> __thread int x0; >> __thread int x1; >> __thread int x2; >> >> extern __thread int e0; >> extern __thread int e1; >> extern __thread int e2; >> extern __thread int e3; >> >> int foo0 () >> { >> return x0; >> } >> >> int main () >> { >> return x0; >> } >> >> -- t1.c -- >> >> __thread int e0; >> __thread int e1; >> __thread int e2; >> __thread int e3; >> >> --- >> >> lld is generating (for aarch64): >> >> [14] .tbss NOBITS 0000000000401000 00001000 >> 0000000000000010 0000000000000000 WAT 0 0 4 >> >> Where is just taking in consideration the largest tbss segment, not all >> from all objects. ld generates a correct output: >> >> [17] .tbss NOBITS 0000000000410dec 00000dec >> 000000000000001c 0000000000000000 WAT 0 0 4 >> >> My initial idea is that 'lib/ReaderWriter/ELF/SegmentChunks.cpp' / >> Segment<ELFT>::assignVirtualAddress is setting wrong slice values, however >> playing with this I could not find a correct logic to handle the TBSS. >> >> Any ideas where lld is possible messing the TBSS segments sizes?