[PATCH] D64930: [ELF][AArch64] Allow PT_LOAD to have overlapping p_offset ranges

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 4 18:52:06 PDT 2019


MaskRay added a comment.

In D64930#1614131 <https://reviews.llvm.org/D64930#1614131>, @kib wrote:

> 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 ?


The new test aarch64-tls-vaddr-align.s checks p_vaddr%p_align = 0. Once D64906 <https://reviews.llvm.org/D64906> (PPC64) is accepted, I'll create an i386 patch, which involves ~40 test changes.

If you comment out the following part included in D64906 <https://reviews.llvm.org/D64906>:

  // ELF/Writer.cpp
        else if (Out::tlsPhdr && Out::tlsPhdr->firstSec == p->firstSec)
          cmd->addrExpr = [] {
            return alignTo(script->getDot(), config->maxPageSize) +
                   alignTo(script->getDot() % config->maxPageSize,
                           Out::tlsPhdr->p_align);
          };

aarch64-tls-vaddr-align.s will create a PT_TLS where p_vaddr%p_align!=0.


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