diff options
author | Mitch Phillips <mitchp@google.com> | 2023-07-31 17:07:26 +0200 |
---|---|---|
committer | Mitch Phillips <mitchp@google.com> | 2023-07-31 17:07:42 +0200 |
commit | ca35a19acab1cf6788c42037bbedeca86e34a455 (patch) | |
tree | b16e7d48f6acafd5d60ea8157047d6e8ff77b7ad /lld/ELF/Relocations.cpp | |
parent | 8a677a7ff0c6f59b392a03108f2dba86d1606183 (diff) | |
download | llvm-ca35a19acab1cf6788c42037bbedeca86e34a455.zip llvm-ca35a19acab1cf6788c42037bbedeca86e34a455.tar.gz llvm-ca35a19acab1cf6788c42037bbedeca86e34a455.tar.bz2 |
[lld] Synthesize metadata for MTE globals
As per the ABI at
https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst,
this patch interprets the SHT_AARCH64_MEMTAG_GLOBALS_STATIC section,
which contains R_NONE relocations to tagged globals, and emits a
SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section, with the correct
DT_AARCH64_MEMTAG_GLOBALS and DT_AARCH64_MEMTAG_GLOBALSSZ dynamic
entries. This section describes, in a uleb-encoded stream, global memory
ranges that should be tagged with MTE.
We are also out of bits to spare in the LLD Symbol class. As a result,
I've reused the 'needsTocRestore' bit, which is a PPC64 only feature.
Now, it's also used for 'isTagged' on AArch64.
An entry in SHT_AARCH64_MEMTAG_GLOBALS_STATIC is practically a guarantee
from an objfile that all references to the linked symbol are through the
GOT, and meet correct alignment requirements. As a result, we go through
all symbols and make sure that, for all symbols $SYM, all object files
that reference $SYM also have a SHT_AARCH64_MEMTAG_GLOBALS_STATIC entry
for $SYM. If this isn't the case, we demote the symbol to being
untagged. Symbols that are imported from other DSOs should always be
fine, as they're GOT-referenced (and thus the GOT entry either has the
correct tag or not, depending on whether it's tagged in the defining DSO
or not).
Additionally hand-tested by building {libc, libm, libc++, libm, and libnetd}
on Android with some experimental MTE globals support in the
linker/libc.
Reviewed By: MaskRay, peter.smith
Differential Revision: https://reviews.llvm.org/D152921
Diffstat (limited to 'lld/ELF/Relocations.cpp')
-rw-r--r-- | lld/ELF/Relocations.cpp | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index af15f5a..9305c95 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -53,6 +53,7 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Demangle/Demangle.h" #include "llvm/Support/Endian.h" #include <algorithm> @@ -199,10 +200,7 @@ static bool needsPlt(RelExpr expr) { R_PPC32_PLTREL, R_PPC64_CALL_PLT>(expr); } -// Returns true if Expr refers a GOT entry. Note that this function -// returns false for TLS variables even though they need GOT, because -// TLS variables uses GOT differently than the regular variables. -static bool needsGot(RelExpr expr) { +bool lld::elf::needsGot(RelExpr expr) { return oneof<R_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTPLT, R_AARCH64_GOT_PAGE, R_LOONGARCH_GOT, R_LOONGARCH_GOT_PAGE_PC>( @@ -859,6 +857,23 @@ static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec, RelType type) { Partition &part = isec.getPartition(); + if (sym.isTagged()) { + std::lock_guard<std::mutex> lock(relocMutex); + part.relaDyn->addRelativeReloc(target->relativeRel, isec, offsetInSec, sym, + addend, type, expr); + // With MTE globals, we always want to derive the address tag by `ldg`-ing + // the symbol. When we have a RELATIVE relocation though, we no longer have + // a reference to the symbol. Because of this, when we have an addend that + // puts the result of the RELATIVE relocation out-of-bounds of the symbol + // (e.g. the addend is outside of [0, sym.getSize()]), the AArch64 MemtagABI + // says we should store the offset to the start of the symbol in the target + // field. This is described in further detail in: + // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#841extended-semantics-of-r_aarch64_relative + if (addend < 0 || static_cast<uint64_t>(addend) >= sym.getSize()) + isec.relocations.push_back({expr, type, offsetInSec, addend, &sym}); + return; + } + // Add a relative relocation. If relrDyn section is enabled, and the // relocation offset is guaranteed to be even, add the relocation to // the relrDyn section, otherwise add it to the relaDyn section. @@ -1645,6 +1660,10 @@ void elf::postScanRelocations() { auto flags = sym.flags.load(std::memory_order_relaxed); if (handleNonPreemptibleIfunc(sym, flags)) return; + + if (sym.isTagged() && sym.isDefined()) + mainPart->memtagDescriptors->addSymbol(sym); + if (!sym.needsDynReloc()) return; sym.allocateAux(); |