[PATCH] D64930: [ELF][AArch64] Allow PT_LOAD to have overlapping p_offset ranges
Konstantin Belousov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 4 15:37:27 PDT 2019
kib added a comment.
In D64930#1607709 <https://reviews.llvm.org/D64930#1607709>, @MaskRay wrote:
> > I'm not sure about breaking the (p_vaddr % p_align == 0) invariant. ld.bfd, gold, and (for the most part) lld currently provide this invariant for TLS segments in output files.
>
> I think p_vaddr%p_align = p_offset%p_align is the invariant we must satisfy. p_vaddr%p_align=0 is not. However, p_vaddr%p_align!=0 will expose bugs (runtime address not congruent to p_vaddr modulo p_align) in existing ld.so implementations so **I added a workaround to D64906 <https://reviews.llvm.org/D64906>.**
>
> //Below are discussions about bugs in various ld.so implementations. They should not be affected by these patches but ideally they should be fixed.//
>
> > Supporting n-mod-m alignment isn't free for dynamic TLS -- allocators typically have [posix_]memalign and free APIs, but I'm not aware of APIs that provide n-mod-m alignment.
>
> When allocating TCB+static TLS blocks, ld.so should properly pad the allocated space. See my comment added to InputSection.cpp in D64906 <https://reviews.llvm.org/D64906>:
>
> // Variant 1. TP will be followed by an optional gap (which is the size of 2
> // pointers on ARM/AArch64, 0 on other targets), followed by alignment
> // padding, then the static TLS blocks. The alignment padding is added so that
> // (TP + gap + padding) is congruent to p_vaddr modulo p_align.
> //
> // Variant 2. Static TLS blocks, followed by alignment padding are placed
> // before TP. The alignment padding is added so that (TP - padding -
> // p_memsz) is congruent to p_vaddr modulo p_align.
>
>
>
>
> > [1] https://sourceware.org/bugzilla/show_bug.cgi?id=24606
>
> This is a great test case! CC @kib who reviewed https://reviews.freebsd.org/D13378 @luporl for powerpc64. CC @emaste who is already subscribed...
>
> FreeBSD rtld-elf (FreeBSD 13.0-CURRENT #89 r350361M) doesn't make runtime address of PT_TLS congruent to p_vaddr modulo p_align on i386/amd64/arm64/powerpc64:
>
> # amd64 case
> tp = 0x8002278d0
> &tlsvar = 0x8002212c8 # this should be 1-mod-4
> tlsvar[1] = 7 # the value is correct
>
I put (an experimental at this stage) review https://reviews.freebsd.org/D21163 to change the behavior of the FreeBSD dynamic linker.
With the patch applied, and with the test program from the sourceware bugzilla, I see on amd64:
orion% ~/build/bsd/DEV/obj/usr/home/kostik/work/build/bsd/DEV/src/amd64.amd64/libexec/rtld-elf/ld-elf.so.1 ./test1
tp = 0x8010448d0
&tlsvar = 0x80103d4a9
tlsvar[1] = 7
The address is 1 mod 4, as requested.
> glibc (i386 and x86_64) has the same bug. It gets the static TLS block offsets correct.
> Its aarch64 port is correct (https://sourceware.org/bugzilla/show_bug.cgi?id=24606).
>
> musl i386 and x86_64 has been correct for many years:
>
> % ./test1
> tp = 0x7f2697b10cc8
> &tlsvar = 0x7f2697b113b9 # 1-mod-4
> tlsvar[1] = 7
>
>
> musl aarch64 (and likely arm/powerpc/powerpc64) was incorrect before 1.1.23 .
> (Fixed by nsz's "fix tls offsets when p_vaddr%p_align != 0 on TLS_ABOVE_TP targets")
>
>> I think there's an interoperability/compatibility issue. Like current Bionic, I don't think the BSDs pay attention to the (p_vaddr % p_align) value, for static or dynamic TLS. glibc uses that value for static TLS segments, but not for dynamic TLS[1]. (i.e. With this change, I believe lld can generate DSOs where some .tbss variables are misaligned when dlopen'ed with glibc.)
>
> It'd be nice if Bionic can fix the problem :) Though it may hardly happen on Bionic arm/aarch64 because .tdata is overaligned to 64.
>
> `p_vaddr(PT_TLS) % p_align(PT_TLS) != 0` can only happen if `sh_addralign(.tdata) < sh_addralign(.tbss)`.
> So you may have to align .tbss to >=128 to verify.
>
> FreeBSD definitely paid attention to the alignment of PT_TLS:
>
> // lib/libc/gen/tls.c
> * +----------+--------------+--------------+-----------+------------------+
> * | pre gap | extended TCB | TCB | post gap | TLS segment |
> * | pre_size | extra_size | TLS_TCB_SIZE | post_size | tls_static_space |
> * +----------+--------------+--------------+-----------+------------------+
> *
> * where:
> * extra_size is tcbsize - TLS_TCB_SIZE
> * post_size is used to adjust TCB to TLS aligment for first version of TLS
> * layout and is always 0 for second version.
> * pre_size is used to adjust TCB aligment for first version and to adjust
> * TLS alignment for second version.
>
>
> Though amd64 is know to have problems as to dynamic TLS blocks. aarch64 may likely have static TLS offset problems (according to the experiments in D62055 <https://reviews.llvm.org/D62055>).
Can you provide the test for static TLS on amd64/i386 ?
Repository:
rLLD LLVM Linker
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D64930/new/
https://reviews.llvm.org/D64930
More information about the llvm-commits
mailing list