summaryrefslogtreecommitdiff
path: root/bfd/elfcore.h
diff options
context:
space:
mode:
authorMatthew Malcomson <matthew.malcomson@arm.com>2022-08-05 17:19:34 +0100
committerMatthew Malcomson <matthew.malcomson@arm.com>2022-08-05 17:50:11 +0100
commitece841e87abc8c8967e0b815aee82030620df3ca (patch)
treef37ec3fd95d795ce03c717e74c9181da3cb390c8 /bfd/elfcore.h
parent1408e112feec3de9c402a9477315b0bbde06a456 (diff)
downloadbinutils-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