aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Relocations.cpp
diff options
context:
space:
mode:
authorMitch Phillips <mitchp@google.com>2023-07-31 17:07:26 +0200
committerMitch Phillips <mitchp@google.com>2023-07-31 17:07:42 +0200
commitca35a19acab1cf6788c42037bbedeca86e34a455 (patch)
treeb16e7d48f6acafd5d60ea8157047d6e8ff77b7ad /lld/ELF/Relocations.cpp
parent8a677a7ff0c6f59b392a03108f2dba86d1606183 (diff)
downloadllvm-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.cpp27
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();