[PATCH] D53906: [ELF] Allow configuring the TLS layout for an Android executable

Ryan Prichard via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 1 14:39:16 PDT 2018


rprichard added a comment.

In https://reviews.llvm.org/D53906#1283665, @peter.smith wrote:

> Increasing the alignment of the TLS segment is an interesting idea as it allows the possibility of a larger TCB and in theory could also be used by the loader to detect compatible ELF files (reject those without the alignment).
>
> One possible way to achieve this without linker changes would be for the Android startup equivalent crt0.s to have a zero sized TLS .data section with 16 byte alignment. This would have the problem that all executables and shared libraries that didn't use TLS would get a 0 sized TLS segment.


Yeah, when I was prototyping ELF TLS on Android, that was my first approach: https://android-review.googlesource.com/c/platform/bionic/+/723698/1/libc/arch-common/bionic/crtbegin.c. (I used a non-zero variable, but a 0-sized variable would be better.)

Putting a TLS segment in every executable seems like something we'd like to avoid. Another problem is that the compiler and/or linker tries to optimize out the dummy section. e.g. with `--gc-sections`

> If changes were made to the linker I think it probably would be best to search for the TLS segment and increase its alignment to 16 if it exists. That would work with both arbitrary linker scripts where the author may forget to increase the alignment; and the "internal" linker script which in theory we could just up the alignment to 16.

I think this would be OK. If we go this route, it might be nice to modify this behavior, which tends to wastes space after the executable TLS segment on non-variant-2 targets:

  // The TLS pointer goes after PT_TLS for variant 2 targets. At least glibc
  // will align it, so round up the size to make sure the offsets are
  // correct.
  if (P->p_type == PT_TLS && P->p_memsz)
    P->p_memsz = alignTo(P->p_memsz, P->p_align);

On variant 2 targets, it's necessary for `getTlsTpOffset()` to use a `p_memsz` aligned up to `p_align`, but it's (presumably) not necessary for the `PT_TLS` segment's size to actually be rounded up in the ELF output. (ld.bfd doesn't round up the size. ld.gold/lld do round it up, but running binutils strip recomputes the `PT_TLS` size without the rounding.)

On other architectures, the extra rounding prevents the loader/libc from allocating anything in the area immediately after the executable's TLS segment. Normally it could put another solib's TLS there, or perhaps some per-thread data. Maybe this is OK if Android only needs 16 reserved words, though, which is my current goal?

If we decided to change this code, we could:

- restrict it to variant 2 only, or
- move the `alignTo()` call to `getTlsTpOffset()` and apply it to variant 2 only


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D53906





More information about the llvm-commits mailing list