aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lld/ELF/SyntheticSections.cpp')
-rw-r--r--contrib/llvm-project/lld/ELF/SyntheticSections.cpp120
1 files changed, 79 insertions, 41 deletions
diff --git a/contrib/llvm-project/lld/ELF/SyntheticSections.cpp b/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
index 7778ae5f78e6..b8a2ebeefce9 100644
--- a/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
+++ b/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
@@ -15,12 +15,15 @@
#include "SyntheticSections.h"
#include "Config.h"
+#include "DWARF.h"
+#include "EhFrame.h"
#include "InputFiles.h"
#include "LinkerScript.h"
#include "OutputSections.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "Target.h"
+#include "Thunks.h"
#include "Writer.h"
#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/DWARF.h"
@@ -29,16 +32,13 @@
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MD5.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
#include <cstdlib>
-#include <thread>
using namespace llvm;
using namespace llvm::dwarf;
@@ -113,7 +113,7 @@ std::unique_ptr<MipsAbiFlagsSection<ELFT>> MipsAbiFlagsSection<ELFT>::create() {
create = true;
std::string filename = toString(sec->file);
- const size_t size = sec->data().size();
+ const size_t size = sec->rawData.size();
// Older version of BFD (such as the default FreeBSD linker) concatenate
// .MIPS.abiflags instead of merging. To allow for this case (or potential
// zero padding) we ignore everything after the first Elf_Mips_ABIFlags
@@ -122,7 +122,7 @@ std::unique_ptr<MipsAbiFlagsSection<ELFT>> MipsAbiFlagsSection<ELFT>::create() {
Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags)));
return nullptr;
}
- auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data());
+ auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->rawData.data());
if (s->version != 0) {
error(filename + ": unexpected .MIPS.abiflags version " +
Twine(s->version));
@@ -185,7 +185,7 @@ std::unique_ptr<MipsOptionsSection<ELFT>> MipsOptionsSection<ELFT>::create() {
sec->markDead();
std::string filename = toString(sec->file);
- ArrayRef<uint8_t> d = sec->data();
+ ArrayRef<uint8_t> d = sec->rawData;
while (!d.empty()) {
if (d.size() < sizeof(Elf_Mips_Options)) {
@@ -241,12 +241,12 @@ std::unique_ptr<MipsReginfoSection<ELFT>> MipsReginfoSection<ELFT>::create() {
for (InputSectionBase *sec : sections) {
sec->markDead();
- if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) {
+ if (sec->rawData.size() != sizeof(Elf_Mips_RegInfo)) {
error(toString(sec->file) + ": invalid size of .reginfo section");
return nullptr;
}
- auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data());
+ auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->rawData.data());
reginfo.ri_gprmask |= r->ri_gprmask;
sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value;
};
@@ -410,7 +410,8 @@ void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) {
return;
size_t offset = piece.inputOff;
- uint32_t id = read32(piece.data().data() + 4);
+ const uint32_t id =
+ endian::read32<ELFT::TargetEndianness>(piece.data().data() + 4);
if (id == 0) {
offsetToCie[offset] = addCie<ELFT>(piece, rels);
continue;
@@ -1335,7 +1336,7 @@ DynamicSection<ELFT>::computeContents() {
addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH,
part.dynStrTab->addString(config->rpath));
- for (SharedFile *file : sharedFiles)
+ for (SharedFile *file : ctx->sharedFiles)
if (file->isNeeded)
addInt(DT_NEEDED, part.dynStrTab->addString(file->soName));
@@ -1504,7 +1505,7 @@ DynamicSection<ELFT>::computeContents() {
if (part.verNeed && part.verNeed->isNeeded()) {
addInSec(DT_VERNEED, *part.verNeed);
unsigned needNum = 0;
- for (SharedFile *f : sharedFiles)
+ for (SharedFile *f : ctx->sharedFiles)
if (!f->vernauxs.empty())
++needNum;
addInt(DT_VERNEEDNUM, needNum);
@@ -1588,9 +1589,14 @@ int64_t DynamicReloc::computeAddend() const {
}
uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
- if (needsDynSymIndex())
- return symTab->getSymbolIndex(sym);
- return 0;
+ if (!needsDynSymIndex())
+ return 0;
+
+ size_t index = symTab->getSymbolIndex(sym);
+ assert((index != 0 || (type != target->gotRel && type != target->pltRel) ||
+ !mainPart->dynSymTab->getParent()) &&
+ "GOT or PLT relocation must refer to symbol in dynamic symbol table");
+ return index;
}
RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type,
@@ -2158,9 +2164,7 @@ void SymbolTableBaseSection::sortSymTabSymbols() {
void SymbolTableBaseSection::addSymbol(Symbol *b) {
// Adding a local symbol to a .dynsym is a bug.
assert(this->type != SHT_DYNSYM || !b->isLocal());
-
- bool hashIt = b->isLocal() && config->optimize >= 2;
- symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)});
+ symbols.push_back({b, strTabSec.addString(b->getName(), false)});
}
size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) {
@@ -2194,7 +2198,7 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &strTabSec)
}
static BssSection *getCommonSec(Symbol *sym) {
- if (!config->defineCommon)
+ if (config->relocatable)
if (auto *d = dyn_cast<Defined>(sym))
return dyn_cast_or_null<BssSection>(d->section);
return nullptr;
@@ -2236,8 +2240,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
eSym->st_other |= sym->stOther & STO_AARCH64_VARIANT_PCS;
if (BssSection *commonSec = getCommonSec(sym)) {
- // st_value is usually an address of a symbol, but that has a special
- // meaning for uninstantiated common symbols (--no-define-common).
+ // When -r is specified, a COMMON symbol is not allocated. Its st_shndx
+ // holds SHN_COMMON and st_value holds the alignment.
eSym->st_shndx = SHN_COMMON;
eSym->st_value = commonSec->alignment;
eSym->st_size = cast<Defined>(sym)->size;
@@ -2322,7 +2326,7 @@ bool SymtabShndxSection::isNeeded() const {
// a .symtab_shndx section when the amount of output sections is huge.
size_t size = 0;
for (SectionCommand *cmd : script->sectionCommands)
- if (isa<OutputSection>(cmd))
+ if (isa<OutputDesc>(cmd))
++size;
return size >= SHN_LORESERVE;
}
@@ -2837,7 +2841,7 @@ static SmallVector<GdbIndexSection::GdbSymbol, 0> createSymbols(
// Instantiate GdbSymbols while uniqufying them by name.
auto symbols = std::make_unique<SmallVector<GdbSymbol, 0>[]>(numShards);
- parallelForEachN(0, concurrency, [&](size_t threadId) {
+ parallelFor(0, concurrency, [&](size_t threadId) {
uint32_t i = 0;
for (ArrayRef<NameAttrEntry> entries : nameAttrs) {
for (const NameAttrEntry &ent : entries) {
@@ -2917,7 +2921,7 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
SmallVector<GdbChunk, 0> chunks(files.size());
SmallVector<SmallVector<NameAttrEntry, 0>, 0> nameAttrs(files.size());
- parallelForEachN(0, files.size(), [&](size_t i) {
+ parallelFor(0, files.size(), [&](size_t i) {
// To keep memory usage low, we don't want to keep cached DWARFContext, so
// avoid getDwarf() here.
ObjFile<ELFT> *file = cast<ObjFile<ELFT>>(files[i]);
@@ -3175,21 +3179,30 @@ VersionNeedSection<ELFT>::VersionNeedSection()
".gnu.version_r") {}
template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
- for (SharedFile *f : sharedFiles) {
+ for (SharedFile *f : ctx->sharedFiles) {
if (f->vernauxs.empty())
continue;
verneeds.emplace_back();
Verneed &vn = verneeds.back();
vn.nameStrTab = getPartition().dynStrTab->addString(f->soName);
+ bool isLibc = config->relrGlibc && f->soName.startswith("libc.so.");
+ bool isGlibc2 = false;
for (unsigned i = 0; i != f->vernauxs.size(); ++i) {
if (f->vernauxs[i] == 0)
continue;
auto *verdef =
reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]);
- vn.vernauxs.push_back(
- {verdef->vd_hash, f->vernauxs[i],
- getPartition().dynStrTab->addString(f->getStringTable().data() +
- verdef->getAux()->vda_name)});
+ StringRef ver(f->getStringTable().data() + verdef->getAux()->vda_name);
+ if (isLibc && ver.startswith("GLIBC_2."))
+ isGlibc2 = true;
+ vn.vernauxs.push_back({verdef->vd_hash, f->vernauxs[i],
+ getPartition().dynStrTab->addString(ver)});
+ }
+ if (isGlibc2) {
+ const char *ver = "GLIBC_ABI_DT_RELR";
+ vn.vernauxs.push_back({hashSysV(ver),
+ ++SharedFile::vernauxNum + getVerDefNum(),
+ getPartition().dynStrTab->addString(ver)});
}
}
@@ -3274,8 +3287,8 @@ void MergeTailSection::finalizeContents() {
}
void MergeNoTailSection::writeTo(uint8_t *buf) {
- parallelForEachN(0, numShards,
- [&](size_t i) { shards[i].write(buf + shardOffsets[i]); });
+ parallelFor(0, numShards,
+ [&](size_t i) { shards[i].write(buf + shardOffsets[i]); });
}
// This function is very hot (i.e. it can take several seconds to finish)
@@ -3299,7 +3312,7 @@ void MergeNoTailSection::finalizeContents() {
numShards));
// Add section pieces to the builders.
- parallelForEachN(0, concurrency, [&](size_t threadId) {
+ parallelFor(0, concurrency, [&](size_t threadId) {
for (MergeInputSection *sec : sections) {
for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) {
if (!sec->pieces[i].live)
@@ -3336,7 +3349,7 @@ template <class ELFT> void elf::splitSections() {
llvm::TimeTraceScope timeScope("Split sections");
// splitIntoPieces needs to be called on each MergeInputSection
// before calling finalizeContents().
- parallelForEach(objectFiles, [](ELFFileBase *file) {
+ parallelForEach(ctx->objectFiles, [](ELFFileBase *file) {
for (InputSectionBase *sec : file->getSections()) {
if (!sec)
continue;
@@ -3540,7 +3553,7 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
for (InputSection *isec : executableSections) {
assert(isec->getParent() != nullptr);
if (InputSection *d = findExidxSection(isec)) {
- memcpy(buf + offset, d->data().data(), d->data().size());
+ memcpy(buf + offset, d->rawData.data(), d->rawData.size());
d->relocateAlloc(buf + d->outSecOff, buf + d->outSecOff + d->getSize());
offset += d->getSize();
} else {
@@ -3565,10 +3578,6 @@ bool ARMExidxSyntheticSection::isNeeded() const {
[](InputSection *isec) { return isec->isLive(); });
}
-bool ARMExidxSyntheticSection::classof(const SectionBase *d) {
- return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX;
-}
-
ThunkSection::ThunkSection(OutputSection *os, uint64_t off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
config->emachine == EM_PPC64 ? 16 : 4, ".text.thunk") {
@@ -3708,9 +3717,9 @@ static uint8_t getAbiVersion() {
return 0;
}
- if (config->emachine == EM_AMDGPU) {
- uint8_t ver = objectFiles[0]->abiVersion;
- for (InputFile *file : makeArrayRef(objectFiles).slice(1))
+ if (config->emachine == EM_AMDGPU && !ctx->objectFiles.empty()) {
+ uint8_t ver = ctx->objectFiles[0]->abiVersion;
+ for (InputFile *file : makeArrayRef(ctx->objectFiles).slice(1))
if (file->abiVersion != ver)
error("incompatible ABI version: " + toString(file));
return ver;
@@ -3844,6 +3853,35 @@ void InStruct::reset() {
symTabShndx.reset();
}
+constexpr char kMemtagAndroidNoteName[] = "Android";
+void MemtagAndroidNote::writeTo(uint8_t *buf) {
+ assert(sizeof(kMemtagAndroidNoteName) == 8); // ABI check for Android 11 & 12.
+ assert((config->androidMemtagStack || config->androidMemtagHeap) &&
+ "Should only be synthesizing a note if heap || stack is enabled.");
+
+ write32(buf, sizeof(kMemtagAndroidNoteName));
+ write32(buf + 4, sizeof(uint32_t));
+ write32(buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG);
+ memcpy(buf + 12, kMemtagAndroidNoteName, sizeof(kMemtagAndroidNoteName));
+ buf += 12 + sizeof(kMemtagAndroidNoteName);
+
+ uint32_t value = 0;
+ value |= config->androidMemtagMode;
+ if (config->androidMemtagHeap)
+ value |= ELF::NT_MEMTAG_HEAP;
+ // Note, MTE stack is an ABI break. Attempting to run an MTE stack-enabled
+ // binary on Android 11 or 12 will result in a checkfail in the loader.
+ if (config->androidMemtagStack)
+ value |= ELF::NT_MEMTAG_STACK;
+ write32(buf, value); // note value
+}
+
+size_t MemtagAndroidNote::getSize() const {
+ return sizeof(llvm::ELF::Elf64_Nhdr) +
+ /*namesz=*/sizeof(kMemtagAndroidNoteName) +
+ /*descsz=*/sizeof(uint32_t);
+}
+
InStruct elf::in;
std::vector<Partition> elf::partitions;