diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 4c3e5aff9ef2656b2e5380a08fce64d656ac40df..5a0c9963d5a654c9cc43f9a22db2c4c636dc1c80 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -81,6 +81,16 @@ AArch64::AArch64() { RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { + if (config->adlt) + switch (type) { + case R_AARCH64_GLOB_DAT: + case R_AARCH64_JUMP_SLOT: + case R_AARCH64_RELATIVE: + return R_ABS; + default: + break; + } + switch (type) { case R_AARCH64_ABS16: case R_AARCH64_ABS32: diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index f4f8b81b018f12f302c71c7260a7de526d0c4e01..24224c8cce54d2138e519ca1f484e853eee585a3 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1631,7 +1631,15 @@ SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, template void SharedFileExtended::parseForAdlt() { this->parse(); parseDynamics(); + parseElfSymTab(); + // add additional section symbols + for (InputSectionBase *sec : this->sections) + for (StringRef prefix : {".got", ".got.plt"}) + if (sec && sec->name.startswith(prefix)) { + auto *d = make(this, "", ELF::STB_LOCAL, 0, ELF::STT_SECTION, 0, 0, sec); + this->allSymbols.push_back(cast(d)); + } bool isDebug = false; if (!isDebug) @@ -1694,15 +1702,33 @@ bool SharedFileExtended::addAdltPostfix(Symbol *s) { return true; } +// TODO: optimize 2 lookups +template +bool SharedFileExtended::saveSymbol(const Defined& d) const { + auto found = elf::symtab->find(d.getName()); + if (found) + return false; + in.symTab->addSymbol(elf::symtab->addSymbol(d)); + return true; +} + template Defined *SharedFileExtended::findSectionSymbol(uint64_t offset) const { bool isDebug = false; + // if (offset == 0x43e0) // debug hint + // isDebug = true; auto predRange = [=](Symbol *sym) { if (!sym || sym->isUndefined() || !sym->isSection()) return false; const Defined *d = cast(sym); uint64_t low = d->section->address; uint64_t high = low + d->section->size; + + if (isDebug) + lld::outs() << "offset: 0x" + Twine::utohexstr(offset) + + "sect name: " + d->section->name + "low 0x" + + Twine::utohexstr(low) + " high: 0x" + + Twine::utohexstr(offset) + "\n"; return (offset >= low) && (offset < high); }; @@ -1719,33 +1745,56 @@ Defined *SharedFileExtended::findSectionSymbol(uint64_t offset) const { return d; } +template +InputSectionBase * +SharedFileExtended::findInputSection(StringRef name) const { + for (InputSectionBase *sec : this->sections) + if (sec && sec->name == name) + return sec; + return nullptr; +} + +template +InputSectionBase * +SharedFileExtended::findInputSection(uint64_t offset) const { + for (InputSectionBase *sec : this->sections) + if (sec && sec->address == offset) + return sec; + return nullptr; +} + template Defined *SharedFileExtended::findDefinedSymbol( - uint64_t offset, llvm::function_ref extraCond) const { + uint64_t offset, StringRef fatalTitle, + llvm::function_ref extraCond) const { bool isDebug = false; - SmallVector matches; - for (Symbol *sym : this->allSymbols) { + auto predRange = [=](Symbol *sym) { if (!sym || sym->isUndefined()) - continue; + return false; Defined *d = cast(sym); if (d->file != this) - continue; + return false; bool goodVal = d->section->address + d->value == offset; bool goodType = d->type == STT_FUNC || d->type == STT_OBJECT; - if (!(goodVal && goodType && extraCond(d))) - continue; + return goodVal && goodType && extraCond(d); + }; + auto i = this->allSymbols.begin(); + auto e = this->allSymbols.end(); + auto ret = std::find_if(i, e, predRange); + if (ret != e) { // item was found + Defined* d = cast(*ret); if (isDebug) - traceSymbol(*sym, "found sym: "); - matches.push_back(d); + traceSymbol(*d, "found defined sym: "); + return d; } - if (!matches.empty()) - return matches[0]; // TODO: resolve multiple variants - - return findSectionSymbol(offset); + auto* sectionSym = findSectionSymbol(offset); + if (!sectionSym) + fatal(fatalTitle + " 0x" + Twine::utohexstr(offset) + "\n"); + return sectionSym; } template @@ -1779,35 +1828,60 @@ void SharedFileExtended::traceElfSection(const Elf_Shdr &sec) const { } template -void SharedFileExtended::traceSymbol(const Symbol& sym, StringRef title) const { - lld::outs() << "File: " << soName << ": " + title << " symName: " << sym.getName(); +void SharedFileExtended::traceSymbol(const Symbol &sym, + StringRef title) const { + lld::outs() << "File: " << soName << ": " + title + << " symName: " << sym.getName(); if (!sym.isDefined()) { lld::outs() << '\n'; return; } auto &d = cast(sym); - lld::outs() << " val: 0x" << Twine::utohexstr(d.value) << " sec of sym: " - << (d.section ? d.section->name : "unknown!") + lld::outs() << " val: 0x" << Twine::utohexstr(d.value) + << " sec of sym: " << (d.section ? d.section->name : "unknown!") << " sym type: 0x" << Twine::utohexstr(d.type) - << " sym binding: 0x" << Twine::utohexstr(d.binding) - << '\n'; + << " sym binding: 0x" << Twine::utohexstr(d.binding) << '\n'; } template -void SharedFileExtended::traceSection(const SectionBase& sec) const { - lld::outs() << "File: " << soName << " sec: " << sec.name << " sec addr: 0x" - << Twine::utohexstr(sec.address) << " sec offs: 0x" - << Twine::utohexstr(sec.getOffset(0)) << " sec ent size: 0x" - << Twine::utohexstr(sec.entsize) << '\n'; +void SharedFileExtended::traceSection(const SectionBase &sec, + StringRef title) const { + lld::outs() << "File: " << soName << ": " + title << " sec: " << sec.name + << " sec addr: 0x" << Twine::utohexstr(sec.address) + << " sec offs: 0x" << Twine::utohexstr(sec.getOffset(0)) + << " sec ent size: 0x" << Twine::utohexstr(sec.entsize) << '\n'; } template -Symbol& SharedFileExtended::getSymbol(uint32_t symbolIndex) const { - if (symbolIndex >= this->symbols.size()) - return getSymbolFromElfSymTab(symbolIndex); +Symbol &SharedFileExtended::getDynamicSymbol(uint32_t symbolIndex) const { return *this->symbols[symbolIndex]; } +template +Symbol &SharedFileExtended::getSymbolADLT(uint32_t symbolIndex, + bool fromDynamic) const { + Symbol &sym = fromDynamic ? getDynamicSymbol(symbolIndex) + : getSymbolFromElfSymTab(symbolIndex); + + StringRef name = sym.getName(); + if (name.empty()) + return sym; + + // check SymbolTable + auto res = elf::symtab->find(name); + if (res && res->exportDynamic) + return *res; + + // check SymbolTableBaseSection + auto found = llvm::find_if( + in.symTab->getSymbols(), [&](const SymbolTableEntry &entry) { + return entry.sym->getName() == name; + }); + // add a local sym if it was not previously added + if (found == in.symTab->getSymbols().end()) + in.symTab->addSymbol(&sym); + return sym; +} template void SharedFileExtended::parseDynamics() { const ELFFile obj = this->getObj(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 821e5f369db30c0e0230e19473a952cdc301e56c..bc3d594189ee8a6b224dd854db638005b1f06191 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -402,10 +402,18 @@ public: StringRef addAdltPostfix(StringRef input); bool addAdltPostfix(Symbol *s); + bool saveSymbol(const Defined& d) const; + Defined *findSectionSymbol(uint64_t offset) const; Defined *findDefinedSymbol( - uint64_t offset, llvm::function_ref extraCond = - [](Defined *) { return true; }) const; + uint64_t offset, + StringRef fatalTitle = "defined symbol not found! offset:", + llvm::function_ref extraCond = [](Defined *) { + return true; + }) const; + + InputSectionBase *findInputSection(StringRef name) const; + InputSectionBase *findInputSection(uint64_t offset) const; ArrayRef getLocalSymbols() override { if (this->allSymbols.empty()) @@ -413,7 +421,8 @@ public: return llvm::makeArrayRef(this->allSymbols).slice(1, eFirstGlobal - 1); } - Symbol &getSymbol(uint32_t symbolIndex) const override; + Symbol &getDynamicSymbol(uint32_t symbolIndex) const; + Symbol &getSymbolADLT(uint32_t symbolIndex, bool fromDynamic) const; Symbol &getSymbolFromElfSymTab(uint32_t symbolIndex) const { if (symbolIndex >= this->allSymbols.size()) @@ -424,8 +433,8 @@ public: void traceElfSymbol(const Elf_Sym &sym, StringRef strTable) const; void traceElfSection(const Elf_Shdr &sec) const; - void traceSymbol(const Symbol& sym, StringRef title = "") const; - void traceSection(const SectionBase& sec) const; + void traceSymbol(const Symbol &sym, StringRef title = "") const; + void traceSection(const SectionBase &sec, StringRef title = "") const; int dynSymSecIdx = 0; int symTabSecIdx = 0; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 8e772a6a683e8660460ebd1ba4599a19c7b3e4b7..a025cb2bc0fcb7716a608737bf170d8023b560ee 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -845,7 +845,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend += target.getImplicitAddend(bufLoc, type); - Symbol &sym = config->adlt ? getSharedFile()->getSymbol( + Symbol &sym = config->adlt ? getSharedFile()->getSymbolFromElfSymTab( rel.getSymbol(config->isMips64EL)) : getFile()->getRelocTargetSym(rel); if (config->adlt) { // TODO improve diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index de31d8cc2af4ad6cf9b6c5f3d89ca2df2797f511..1adda8cd4c25560611208d37b47af0973c919da6 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -456,8 +456,17 @@ private: int64_t addend) const; template void scanOne(RelTy *&i); + // ADLT template - void handleRelativeReloc(const RelTy &rel, const Symbol& sym, uint64_t offset); + void processForADLT(const RelTy &rel, Relocation *r); + + template + void addRelativeRelocForAdlt(const RelTy &rel, Defined &symWhere, + Defined &inputSym) const; + void pushRelocAdlt(Relocation *r) const; + + template + void tracePushRelocADLT(Defined &symWhere, Relocation &r) const; }; } // namespace @@ -1294,11 +1303,153 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return 0; } +// ADLT BEGIN +template +void RelocationScanner::addRelativeRelocForAdlt(const RelTy &rel, + Defined &symWhere, + Defined &inputSym) const { + // auto file = sec.getSharedFile(); + std::string title = "addRelativeRelocForAdlt: "; + std::string failTitle = ""; + + RelType type = R_AARCH64_ABS64; + RelExpr expr = R_ABS; + int64_t addend = computeAddend(rel, expr, false); + + // todo: rewrite + addend = inputSym.isSection() ? (addend - inputSym.section->address) : 0; + /* + { + failTitle = "addend: 0x" + utohexstr(addend) + " was not decreased!"; + auto *ISec = inputSym.section; + if (static_cast(addend - ISec->address) >= 0) + addend -= ISec->address; + else + file->traceSection(*ISec, failTitle); + }*/ + // finally + addRelativeReloc(*cast(symWhere.section), symWhere.value, + inputSym, addend, expr, type); +} + +void RelocationScanner::pushRelocAdlt(Relocation *r) const { + sec.relocations.push_back(*r); +} + +template +void RelocationScanner::tracePushRelocADLT(Defined &symWhere, + Relocation &r) const { + auto file = sec.getSharedFile(); + lld::outs() << "[ADLT] Before push: type: " + toString(r.type) + + " expr: " + toString(r.expr) + " offset: 0x" + + utohexstr(r.offset) + " addend: 0x" + utohexstr(r.addend) + + ".\n"; + lld::outs() << "symWhere: "; + file->traceSymbol(symWhere); + + lld::outs() << "r->sym: "; + file->traceSymbol(*r.sym); + lld::outs() << "\n"; +} + +template +void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r) { + auto file = sec.getSharedFile(); + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + std::string title = "processForADLT: symIndex: " + toString(symIndex) + " "; + bool isDebug = false; + + // parse offset (where) + std::string failTitle = title + "symWhere not found! offset: "; + Defined *symWhere = file->findDefinedSymbol(r->offset, failTitle); + file->saveSymbol(*symWhere); + + /*if (r->offset == 0x23dc) // debug hint + isDebug = true; */ + + // process offset + failTitle = "offset: 0x" + utohexstr(r->offset) + " was not decreased!"; + if (static_cast(r->offset - sec.address) >= 0) + r->offset -= sec.address; + else + file->traceSection(sec, failTitle); + + // prepare to resolve relocs + /*if (r->sym->getName() == "__ubsan_handle_cfi_check_fail") // debug hint + isDebug = true;*/ + + if (isDebug) + tracePushRelocADLT(*symWhere, *r); + + // resolve relocs + switch (r->type) { + // dyn relocs + case R_AARCH64_RELATIVE: + failTitle = + title + " " + toString(r->type) + ": r->sym not found! addend: "; + if (auto *d = file->findDefinedSymbol( + r->addend, failTitle, [](Defined *d) { return !d->isPreemptible; })) + addRelativeRelocForAdlt(rel, *symWhere, *d); + return; + case R_AARCH64_GLOB_DAT: + r->sym->needsGot = 1; + if (r->sym->isUndefined()) + r->sym->needsPlt = 1; + return; + case R_AARCH64_JUMP_SLOT: + if (r->sym->isUndefined()) + r->sym->needsPlt = 1; + return; + // abs relocs + case R_AARCH64_ABS32: + case R_AARCH64_ABS64: + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_PREL32: + case R_AARCH64_PREL64: + pushRelocAdlt(r); + return; + // plt relocs + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + if (r->sym->isDefined()) + r->expr = R_PC; // prev: R_PLT_PC + pushRelocAdlt(r); + return; + // got relocs + case R_AARCH64_ADR_GOT_PAGE: + if (r->sym->isDefined() && !r->sym->needsGot) { + if (isDebug) { + lld::outs() << "[ADLT] R_AARCH64_ADR_GOT_PAGE: sym not in GOT! "; + file->traceSymbol(*r->sym); + } + r->expr = R_PC; // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || + // R_GOT || R_GOT_PC + } + LLVM_FALLTHROUGH; + case R_AARCH64_LD64_GOT_LO12_NC: + pushRelocAdlt(r); + return; + default: + fatal("Unhandled reloc: " + toString(r->type)); + break; + } +} +// ADLT END + template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; uint32_t symIndex = rel.getSymbol(config->isMips64EL); - auto file = config->adlt ? sec.getSharedFile() : sec.getFile(); - Symbol &sym = file->getSymbol(symIndex); + bool fromDynamic = sec.type == SHT_NULL || sec.name.startswith(".got.plt"); + Symbol &sym = + config->adlt + ? sec.getSharedFile()->getSymbolADLT(symIndex, fromDynamic) + : sec.getFile()->getSymbol(symIndex); RelType type; // Deal with MIPS oddity. @@ -1321,74 +1472,6 @@ template void RelocationScanner::scanOne(RelTy *&i) { return; const uint8_t *relocatedAddr = sec.rawData.begin() + offset; - if (config->adlt) { - auto file = sec.getSharedFile(); - bool isDebug = false; - - auto saveSymIfNeeded = [&](const Defined& d) { - auto found = elf::symtab->find(d.getName()); - if (!found) - in.symTab->addSymbol(elf::symtab->addSymbol(d)); - }; - - auto handleRelativeReloc = [&]() { - RelType type = R_AARCH64_ABS64; - RelExpr expr = target.getRelExpr(type, sym, relocatedAddr); - uint64_t addend = computeAddend(rel, expr, sym.isLocal()); - StringRef title = "handle relative reloc: "; - if (isDebug) - lld::outs() << title << "offset: 0x" + Twine::utohexstr(offset) - << " addend: 0x" + Twine::utohexstr(addend) + "\n"; - - // parse offset (where) - const Defined *symWhere = file->findDefinedSymbol(offset); - if (!symWhere) - fatal(title + "symWhere not found! offset: 0x" + - Twine::utohexstr(offset) + "\n"); - auto iSec = cast(symWhere->section); - offset = - symWhere->isSection() ? (offset - symWhere->section->address) : 0; - saveSymIfNeeded(*symWhere); - - // parse addent (replacement) - Defined *inputSym = file->findDefinedSymbol( - addend, [](Defined *d) { return !d->isPreemptible; }); - - if (!inputSym) - fatal(title + "inputSym not found! addend: 0x" + - Twine::utohexstr(addend) + "\n"); - addend = - inputSym->isSection() ? (addend - inputSym->section->address) : 0; - - if (isDebug) - file->traceSymbol(*inputSym, "handle relative reloc: inputSym: "); - saveSymIfNeeded(*inputSym); - - // finally - addRelativeReloc(*iSec, symWhere->value, *inputSym, addend, expr, type); - }; - switch (type) { - case R_AARCH64_RELATIVE: - handleRelativeReloc(); - return; - case R_AARCH64_GLOB_DAT: { - Symbol &s = file->getSymbol(symIndex); - s.needsGot = 1; - if (s.isUndefined()) - s.needsPlt = 1; - return; - } - case R_AARCH64_JUMP_SLOT: { - Symbol &s = file->getSymbol(symIndex); - if (s.isUndefined()) - s.needsPlt = 1; - return; - } - default: - break; - } - } - RelExpr expr = target.getRelExpr(type, sym, relocatedAddr); // Ignore R_*_NONE and other marker relocations. @@ -1399,105 +1482,9 @@ template void RelocationScanner::scanOne(RelTy *&i) { int64_t addend = computeAddend(rel, expr, sym.isLocal()); if (config->adlt) { - auto file = sec.getSharedFile(); - auto traceSym = [&](StringRef debugTitle, Symbol& sym) { - lld::outs() << debugTitle; - lld::outs() << "type: " << lld::toString(type) << " sym: "; - Symbol* p = &sym; - if (!p) { - lld::outs() << "unknown!\n"; - return; - } - file->traceSymbol(sym); - if (!sym.isDefined()) - return; - lld::outs() << "sec: "; - file->traceSection(*(cast(sym).section)); - }; - - bool isDebug = false; - auto strType = lld::toString(type); - auto debugTitle = "[RelocationScanner::handle relocs]: " + strType + ": "; - if (isDebug) { - traceSym(debugTitle, sym); - lld::outs() << " offset before: 0x" << Twine::utohexstr(offset) << '\n'; - } - if (offset + sec.address) - offset -= sec.address; - - Symbol *s = &sym; - if (!(expr == R_PLT || expr == R_PLT_PC || expr == R_GOT || expr == R_GOT_PC)) - if (Symbol *tmp = &file->getSymbolFromElfSymTab(symIndex)) { - if (isDebug) - traceSym(debugTitle + "changed to tmp: ", *tmp); - s = tmp; - } - - s = sym.getName().size() ? elf::symtab->find(sym.getName()) : &sym; - if (!s) { // if symbol was not found in elf::symtab - s = &sym; - in.symTab->addSymbol(s); - } - if (isDebug) - traceSym(debugTitle + "before push: ", *s); - - if (s->isUndefined()) { - if (expr == R_PLT || expr == R_PLT_PC) - s->needsPlt = 1; - else if (expr == R_GOT || expr == R_GOT_PC) - s->needsGot = 1; - } - - auto pushReloc = [&]() { - sec.relocations.push_back({expr, type, offset, addend, s}); - }; - - bool isSymDefined = s && s->isDefined(); - - switch (type) { - // abs relocs - case R_AARCH64_ABS32: - case R_AARCH64_ABS64: - case R_AARCH64_ADD_ABS_LO12_NC: - case R_AARCH64_ADR_PREL_PG_HI21: - case R_AARCH64_LDST8_ABS_LO12_NC: - case R_AARCH64_LDST16_ABS_LO12_NC: - case R_AARCH64_LDST32_ABS_LO12_NC: - case R_AARCH64_LDST64_ABS_LO12_NC: - case R_AARCH64_LDST128_ABS_LO12_NC: - case R_AARCH64_PREL32: - case R_AARCH64_PREL64: - pushReloc(); - return; - // plt relocs - case R_AARCH64_CALL26: - case R_AARCH64_JUMP26: { - if (isSymDefined) - expr = R_PC; // prev: R_PLT_PC - pushReloc(); - return; - } - - // got relocs - case R_AARCH64_ADR_GOT_PAGE: - if (isSymDefined && !s->needsGot) { - if (isDebug) { - lld::outs() << "[ADLT] R_AARCH64_ADR_GOT_PAGE: sym not in GOT! "; - file->traceSymbol(*s); - } - expr = R_PC; // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || - // R_GOT || R_GOT_PC - } - LLVM_FALLTHROUGH; - case R_AARCH64_LD64_GOT_LO12_NC: - pushReloc(); - return; - default: - fatal("Unhandled reloc: " + strType); - break; - } - if (isDebug) - lld::outs() << " offset after: 0x" << Twine::utohexstr(offset) << "\n\n"; + Relocation r = {expr, type, offset, addend, &sym}; + processForADLT(rel, &r); + return; } if (config->emachine == EM_PPC64) {