diff options
author | Matthew Malcomson <matthew.malcomson@arm.com> | 2022-08-05 17:19:34 +0100 |
---|---|---|
committer | Matthew Malcomson <matthew.malcomson@arm.com> | 2022-08-05 17:50:11 +0100 |
commit | ece841e87abc8c8967e0b815aee82030620df3ca (patch) | |
tree | f37ec3fd95d795ce03c717e74c9181da3cb390c8 /bfd/elfcore.h | |
parent | 1408e112feec3de9c402a9477315b0bbde06a456 (diff) | |
download | binutils-gdb-ece841e87abc8c8967e0b815aee82030620df3ca.tar.gz |
Implement Morello TLS relaxations
The majority of the code change here is around TLS data stubs. The new
TLS ABI requires that when relaxing a General Dynamic or Initial Exec
access to a variable to a Local Exec access, the linker emits data stubs
in a read-only section.
We do this with the below approach:
- check_relocs notices that we need TLS data stubs by recognising that
some relocation will need to be relaxed to a local-exec relocation.
- check_relocs then records a hash table entry mapping the symbol that
we are relocating against to a position in some data stub section.
It also ensures that this data stub section has been created, and
increments our data stub section size.
- This section is placed in the resulting binary using the standard
subsection and wildcard matching implemented by the generic linker.
- In elfNN_aarch64_size_dynamic_sections we allocate the actual buffer
for our data stub section.
- When it comes to actually relaxing the TLS sequence,
relocate_section directly populates the data stub using the address
and size of the TLS object that has already been calculated, it then
uses final_link_relocate to handle adjusting the text so that it
points to this data stub.
Notes on implementation:
Mechanism by which we create and populate a TLS data section:
There are currently three different ways by which the AArch64 backend
creates and populates a special section. These are
- The method by which the .got (and related sections) are populated.
- The method by which the interworking stubs are populated.
- The method by which erratum 843419 stub sections are populated.
We have gone with an approach that mostly follows that used to
populate the .got. Here we give an outline of the approaches and
provide the reasoning by which the approach used by the .got was
chosen.
Handling the .got section:
- Create a section on an existing BFD.
- Mark that section as SEC_LINKER_CREATED.
- Record the existing BFD as the `dynobj`.
- bfd_elf_final_link still calls elf_link_input_bfd on the object.
- elf_link_input_bfd avoids emitting the section (because of
SEC_LINKER_CREATED).
- bfd_elf_final_link then emits the special sections on `dynobj` after
all the non-special sections on all objects have been relocated.
- Allows updating the .got input section in relocate_section &
final_link_relocate knowing that its contents will be output once all
relocations on standard input sections have been processed.
Handling interworking stub sections.
- Create a special stub file.
- Create sections on that stub file for each input section we need a
stub for.
- Manually populate the sections in build_stubs (which is called
through `ldemul_finish` *before* `ldwrite` and hence before any
other files are relocated).
Handling erratum 843419 stub sections.
- Create a special stub file.
- Create sections on that stub file for each input section we need a
stub for.
- Ensure that the stub file is marked with class ELFCLASSNONE.
- Ensure that the list of input sections for the relevant output
section statement has the veneered input section *directly before*
the stub section which has the veneer.
- When relocating and outputting sections, having ELFCLASSNONE means
that we output sections on the stub_file only when we see the
corresponding input statement. Without that class marker
bfd_elf_final_link calls elf_link_input_bfd which writes out the
data for all input sections on the relevant BFD.
- Since we have ensured the input statement for our stub section is
directly after the input statement for the section we are emitting
veneers for, we know that the veneered section will be relocated
and output before we output our stub section.
- Hence we can copy relocated data from the veneered section into our
stub section and know that our stub section will be output after
this modification has been made.
In deciding what to do with the read-only TLS data stubs we noticed
the following problems with each approach:
- The ABI requires that the read-only TLS data stubs are emitted into
a read-only section. This will necessarily be a different output
section to .text where the requirement for these stubs is found.
The temporal order in which output sections are written to the
output file is tied to the order in which the in-memory linker
statements are kept, and that is tied to the linker script provided
by the user. Hence we can not rely on ordering and ELFCLASSNONE to
ensure that our data stub section is emitted after the relevant TLS
sequences have been relaxed. (We need to know our data stub section
is written to the output after we have populated it as otherwise the
data would not propagate to the resulting binary).
- I think it is easier and simpler to find the data needed for the TLS
data stubs in relocate_section just as we relax the relevant TLS
sequences. Hence I don't want to use the approach used for
interworking stubs of populating the entire section beforehand.
- Adding a section to `dynobj` would mean that we're adding a section
to a user input BFD, which is not quite as clear as having a
separate BFD for our special stub section. It also means we treat
this particular section as a "dynamic" section. This is a little
confusing nomenclature-wise.
Based on the above trade-offs we chose the .got approach (accepting
the negative that this will be stored on a user BFD). N.b. using the
.got approach and requiring the section get allocated in
`size_dynamic_sections` is not problematic for static executables
despite the nomenclature. This function always gets called.
One difference between how we handle the data stubs and how the .got
is handled is that we do not count the number of data stubs required
in size_dynamic_sections, but rather total it as we see relocations
needing these stubs in check_relocs.
We do this largely to avoid requiring another data member on all
symbols to indicate information about whether this symbol needs a data
stub and where that data stub is. The number of TLS symbols are
expected to be much smaller than the number of symbols with an entry
in the GOT and hence a separate hash table just containing entries for
those symbols which need such information is likely to often be
smaller.
N.b. it is interesting to mention that for all relocations which need
a data stub we would make an input section on `dynobj` in
`check_relocs` if that relaxation were not performed. This is since
if we did not realise they could be relaxed these relocations would
have needed a .got entry.
N.b. we must use make_section_anyway to create our TLS data stubs
section in order to avoid any problems with our linker defined section
having the same name as a section already defined by the user.
We do not use local stub symbols:
The TLS ABI describes data stubs using specially named symbols. These
are not part of the ABI. We could have associated the position of a
data stub with a particular symbol by generating a symbol internally
using some name mangling scheme that matches that in the TLS ABI
examples and points to the data stub for a particular symbol. We take
the current approach on the belief that it is "neater" to avoid
relying on such a name-mangling scheme and the associated sprintf
calls.
final_link_relocate handling the adjusted relocation for data stubs:
final_link_relocate does not actually use the `h` or `sym` arguments
to decide anything for the two relocations we need to handle once we
have relaxed an IE or GD TLS access sequence to a LE one.
The relocations we need are BFD_RELOC_MORELLO_ADR_HI20_PCREL and
BFD_RELOC_AARCH64_ADD_LO12. For both (and in fact for most
relocations) we only use `h` and `sym` for catching and reporting
errors.
This means we don't actually have to update the `h` and/or `sym`
variables before calling elfNN_aarch64_final_link_relocate.
Allocate TLS data stubs on dynobj
This uses the same approach that the linker uses to ensure that the
.got sections are emitted after all relocations have been processed.
elf_link_input_bfd avoids sections with SEC_LINKER_CREATED, and
bfd_elf_final_link emits all SEC_LINKER_CREATED sections on the dynobj
*after* standard sections have been relocated.
This means that we can populate the contents of the TLS data stub
section while performing relocations on all our other sections (i.e.
in the same place as we perform the relaxations on the TLS sequences
that we recognise need these data stubs).
Assert that copy_indirect_symbol is not a problem
copy_indirect_symbol takes information from one symbol and puts it
onto another. The point is to ensure that any symbol which simply
refers to another has all its cached information on that symbol to
which it refers rather than itself. If we could ever call this
function on a symbol which we have found needs an associated data stub
created, then we could have to handle adjusting the hash table
associating a symbol with a data stub. We do not believe this is
needed, and add an assert instead.
The proof that this is not a problem is a little tricky. However it
*shouldn't* be a problem given what it's handling. This is handling
moving cached information from an indirected symbol to the symbol it
represents. That is needed when the information was originally put on
the indirected symbol, and that happens when the indirection was
originally the other way around. The two ways that this reversal of
indirection can happen is through resolving dynamic weak symbols and
versioned symbols. Both of these are not something we can see with
SYMBOL_REFERENCES_LOCAL TLS symbols (see below).
We only need to worry about copy_indirect_symbol transferring
information *from* a symbol which we have generated a TLS relaxation
against to LE.
In order to satisfy the criteria that we have generated a TLS
relaxation hash entry against a symbol, we must have already have run
check_relocs. This means that of the ways in which
copy_indirect_symbol can be called we have eliminated all but
_bfd_elf_fix_symbol_flags and bfd_elf_record_link_assignment.
bfd_elf_record_link_assignment handles symbol assignments in a linker
script. Such assignments can not be made on TLS symbols (we end up
generating a non-TLS symbol).
_bfd_elf_fix_symbol_flags only calls copy_indirect_symbol on symbols
which have is_weakalias set. These are symbols "from a dynamic
object", and we only ever call the hook when the real definition is in
a non-shared object. Hence we would not have performed this
relaxation on the symbol (because it is not SYMBOL_REFERENCES_LOCAL).
Hence I don't believe this is something that we can trigger and we add
an assertion here rather than add code to handle the case.
Diffstat (limited to 'bfd/elfcore.h')
0 files changed, 0 insertions, 0 deletions