diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 6583d7d8e5627e36bab4f7f58f28ce9a742fa152..22c3dd95ba2b33205ac03f4a1f60694f772e24e8 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -221,6 +221,7 @@ struct Configuration { bool singleRoRx; bool shared; bool adlt = false; + bool adltTrace = false; bool symbolic; bool isStatic = false; bool sysvHash = false; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index b3a387c160d9490a95823a9fa9799a999bb82188..a10d06a016b0b64a45a06bbebd04466f10aad67b 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1093,6 +1093,7 @@ static void readConfigs(opt::InputArgList &args) { config->bsymbolic = BsymbolicKind::All; } config->adlt = args.hasArg(OPT_adlt); + config->adltTrace = args.hasArg(OPT_adlt_trace); config->checkSections = args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); config->chroot = args.getLastArgValue(OPT_chroot); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0c9a7e00682255692e123e1f2f48c6455e4f0362..6e1685c1d61b67bd7abed9c797da709f7d61a19f 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1029,7 +1029,9 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, if (name == ".eh_frame" && !config->relocatable) return make(*this, sec, name); - if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name)) + bool isRodata = name.startswith(".rodata"); // ADLT: .rodata isn't mergeable + if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name) && + (config->adlt && !isRodata)) return make(*this, sec, name); return make(*this, sec, name); } diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 46943047df31fec7891eb8bd8b39d13c3bb3ac56..954ee5baeeff5e9eb73cad9dd50339d4b6fb7d0d 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -376,6 +376,7 @@ defm section_start: Eq<"section-start", "Set address of section">, def shared: F<"shared">, HelpText<"Build a shared object">; def adlt: F<"adlt">, HelpText<"Build adlt library">; +def adlt_trace: F<"adlt-trace">, HelpText<"Print adlt trace">; defm soname: Eq<"soname", "Set DT_SONAME">; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ee310d888053af24f8abb3951aa7468f2ca13dfd..cda7977fa24501f8e6395b1613aa9cdf376bb254 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -117,10 +117,6 @@ static void removeEmptyPTLoad(SmallVector &phdrs) { if (removed.count(sec->ptLoad)) sec->ptLoad = nullptr; - if (config->adlt) { - assert(it == phdrs.end() && "adlt: ph-index in .adlt invalid due to shift"); - } - phdrs.erase(it, phdrs.end()); } @@ -550,6 +546,148 @@ template void elf::createSyntheticSections() { add(*in.strTab); } +static InputSection *getInputSection(OutputSection *sec) { + if (!sec || !sec->hasInputSections || sec->commands.empty()) + return nullptr; + SectionCommand *cmd = sec->commands.front(); + InputSectionDescription *isd = cast(cmd); + return isd->sections.front(); +} + +// ADLT stuff +template static void adltTraceRelocationIndexes() { + auto &relaDyn = mainPart->relaDyn; + assert(!relaDyn->relocs.empty() && "ADLT: relaDyn can't be empty!"); + assert(!in.relaPlt->relocs.empty() && "ADLT: relaPlt can't be empty!"); + + if (config->adltTrace) { // debug hint + auto traceInfo = [&](auto *relSec, auto &outIndexes) -> void { + bool isPlt = relSec == in.relaPlt.get(); + lld::outs() << (isPlt ? "Plt" : "Dyn") << " indexes: "; + for (auto &it : outIndexes) // simple print + lld::outs() << it << ' '; + lld::outs() << '\n'; + for (auto &it : outIndexes) // print relocs + if (DynamicReloc *rel = &relSec->relocs[it]) + lld::outs() << it << ":\t" << rel->inputSec->name << " + 0x" + << utohexstr(rel->offsetInSec) << "\t" + << toString(rel->type) << "\t" << rel->sym->getName() + << " + 0x" << utohexstr(rel->addend) << '\n'; + }; + lld::outs() << "[ADLT]\n"; + lld::outs() << "Dyn relocs (" << relaDyn->relocs.size() << ")\n"; + lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = cast>(file)) { + lld::outs() << "[ADLT] " << soFile->soName << ":\n"; + traceInfo(relaDyn.get(), soFile->dynRelIndexes); + traceInfo(in.relaPlt.get(), soFile->pltRelIndexes); + } + } + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = cast>(file)) { + assert(!soFile->dynRelIndexes.empty() && + "ADLT: relaDyn indexes can't be empty!"); + assert(!soFile->pltRelIndexes.empty() && + "ADLT: relaPlt indexes can't be empty!"); + } +} + +// ADLT stuff +static StringRef phdrTypeToStr(uint32_t p_type) { + StringRef strType = ""; + switch (p_type) { + case PT_PHDR: + strType = "PT_PHDR"; + break; + case PT_ADLT: + strType = "PT_ADLT"; + break; + case PT_LOAD: + strType = "PT_LOAD"; + break; + case PT_TLS: + strType = "PT_TLS"; + break; + case PT_DYNAMIC: + strType = "PT_DYNAMIC"; + break; + case PT_GNU_RELRO: + strType = "PT_GNU_RELRO"; + break; + case PT_GNU_STACK: + strType = "PT_GNU_STACK"; + break; + case PT_NOTE: + strType = "PT_NOTE"; + break; + default: + llvm_unreachable("UNKNOWN TYPE"); + break; + } + return strType; +} + +template static void adltTracePhdrsIndexes() { + if (config->adltTrace) { // debug hint + auto traceInfo = [&](auto &phdrs, auto &outIndexes) -> void { + for (auto &it : outIndexes) // simple print + lld::outs() << it << ' '; + lld::outs() << "\nIdx\tType\tOffset\tVirtAddr\tAlign\tFirstSec\n"; + for (auto &it : outIndexes) // print headers + if (PhdrEntry *p = phdrs[it]) + lld::outs() << it << ":\t" << phdrTypeToStr(p->p_type) << "\t0x" + << utohexstr(p->p_offset) << "\t0x" + << utohexstr(p->p_vaddr) << " \t0x" + << utohexstr(p->p_align) << "\t" << p->firstSec->name + << '\n'; + }; + lld::outs() << "[ADLT]\n"; + lld::outs() << "Program Headers (" << mainPart->phdrs.size() << ")\n"; + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = cast>(file)) { + lld::outs() << "[ADLT] " << soFile->soName << ":\n"; + traceInfo(mainPart->phdrs, soFile->programHeaderIndexes); + } + } + + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = cast>(file)) + assert(!soFile->programHeaderIndexes.empty() && + "ADLT: PHdr indexes can't be empty!"); +} + +template static void adltProcessPhdrs() { + auto add = [&](auto *file, auto idx) { + if (auto *soFile = cast>(file)) + soFile->programHeaderIndexes.insert(idx); + }; + auto addForAll = [&](auto idx) { + for (auto *file : ctx->sharedFilesExtended) + add(file, idx); + }; + for (auto &it : llvm::enumerate(mainPart->phdrs)) { + PhdrEntry *p = it.value(); + if (p->p_type != PT_LOAD && p->p_type != PT_TLS) + continue; + auto *firstIsec = getInputSection(p->firstSec); + auto *lastIsec = getInputSection(p->lastSec); + if (!firstIsec || !lastIsec) { + addForAll(it.index()); + continue; + } + auto *firstFile = firstIsec->file; + auto *lastFile = lastIsec->file; + assert((firstFile == lastFile) && "multiple .so in segments!"); + if (!firstFile || !lastFile) { + addForAll(it.index()); + continue; + } + add(firstFile, it.index()); + } + adltTracePhdrsIndexes(); +} + // The main function of the writer. template void Writer::run() { copyLocalSymbols(); @@ -598,6 +736,10 @@ template void Writer::run() { if (errorCount()) return; + // ADLT: PHdrs: collect indexes and trace results if enabled + if (config->adlt) + adltProcessPhdrs(); + { llvm::TimeTraceScope timeScope("Write output file"); // Write the result down to a file. @@ -1035,7 +1177,7 @@ void PhdrEntry::add(OutputSection *sec) { firstSec = sec; bool adltCFI = config->adlt && ctx->adltWithCfi && p_type == PT_LOAD; if (adltCFI) // check cfi.h: LIBRARY_ALIGNMENT and _BITS - sec->alignment = 1UL << 18; + firstSec->alignment = 1UL << 18; p_align = std::max(p_align, sec->alignment); if (p_type == PT_LOAD) sec->ptLoad = this; @@ -1874,45 +2016,6 @@ static void removeUnusedSyntheticSections() { }); } -template static void adltTraceRelocationIndexes() { - auto &relaDyn = mainPart->relaDyn; - assert(!relaDyn->relocs.empty() && "ADLT: relaDyn can't be empty!"); - assert(!in.relaPlt->relocs.empty() && "ADLT: relaPlt can't be empty!"); - - bool adltRelocsTrace = false; // debug hint - if (adltRelocsTrace) { - auto traceRelocInfo = [&](auto *relSec, auto &outIndexes) -> void { - bool isPlt = relSec == in.relaPlt.get(); - lld::outs() << (isPlt ? "Plt" : "Dyn") << " indexes: "; - for (auto &it : outIndexes) // simple print - lld::outs() << it << ' '; - lld::outs() << '\n'; - for (auto &it : outIndexes) // print relocs - if (DynamicReloc *rel = &relSec->relocs[it]) - lld::outs() << it << ": " << rel->inputSec->name << " + 0x" - << utohexstr(rel->offsetInSec) << "\t" - << toString(rel->type) << "\t" << rel->sym->getName() - << " + 0x" << utohexstr(rel->addend) << '\n'; - }; - lld::outs() << "[ADLT]\n"; - lld::outs() << "Dyn relocs (" << relaDyn->relocs.size() << ")\n"; - lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; - for (auto *file : ctx->sharedFilesExtended) - if (auto *soFile = cast>(file)) { - lld::outs() << "[ADLT] " << soFile->soName << ":\n"; - traceRelocInfo(relaDyn.get(), soFile->dynRelIndexes); - traceRelocInfo(in.relaPlt.get(), soFile->pltRelIndexes); - } - } - for (auto *file : ctx->sharedFilesExtended) { - __attribute__((unused)) auto *soFile = cast>(file); - assert(!soFile->dynRelIndexes.empty() && - "ADLT: relaDyn indexes can't be empty!"); - assert(!soFile->pltRelIndexes.empty() && - "ADLT: relaPlt indexes can't be empty!"); - } -} - // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { Out::preinitArray = findSection(".preinit_array"); @@ -2374,19 +2477,6 @@ static uint64_t computeFlags(uint64_t flags) { return flags; } -static InputSection *getInputSection(OutputSection *sec) { - if (!sec || !sec->hasInputSections || sec->commands.empty()) - return nullptr; - SectionCommand *cmd = sec->commands.front(); - InputSectionDescription *isd = cast(cmd); - return isd->sections.front(); -} - -struct LoadInfoForADLT { - int phIndex; // input - SmallVector phSections; -}; - // Decide which program headers to create and which sections to include in each // one. template @@ -2397,8 +2487,11 @@ SmallVector Writer::createPhdrs(Partition &part) { return ret.back(); }; - auto getCurrentIndex = [&]() -> int { - return static_cast(ret.size()) - 1; + auto getCurrentFileIdx = [](OutputSection *sec) -> llvm::Optional { + auto file = getInputSection(sec)->file; + if (!file) + return llvm::None; + return cast>(file)->orderIdx; }; unsigned partNo = part.getNumber(); @@ -2433,11 +2526,6 @@ SmallVector Writer::createPhdrs(Partition &part) { load = addHdr(PT_LOAD, flags); load->add(Out::elfHeader); load->add(Out::programHeaders); - if (config->adlt) // add common header for all libs - for (auto *base : ctx->sharedFilesExtended) { - auto *soFile = cast>(base); - soFile->programHeaderIndexes.insert(getCurrentIndex()); - } } } @@ -2464,9 +2552,8 @@ SmallVector Writer::createPhdrs(Partition &part) { } } - // ADLT: Collect load headers info - SmallVector adltLoadInfo; - + // ADLT: Generate more PHdrs for each input .so + llvm::Optional lastFileIdx = llvm::None; for (OutputSection *sec : outputSections) { if (!needsPtLoad(sec)) continue; @@ -2498,45 +2585,13 @@ SmallVector Writer::createPhdrs(Partition &part) { (sameLMARegion || load->lastSec == Out::programHeaders))) { load = addHdr(PT_LOAD, newFlags); flags = newFlags; - if (config->adlt) { - adltLoadInfo.emplace_back(); - adltLoadInfo.back().phIndex = getCurrentIndex(); - } } + if (config->adlt && getCurrentFileIdx(sec) != lastFileIdx) + load = addHdr(PT_LOAD, flags); load->add(sec); - if (config->adlt && !adltLoadInfo.empty()) - adltLoadInfo.back().phSections.push_back(sec); - } - - // ADLT: Fill load headers info - if (config->adlt) { - for (LoadInfoForADLT &info : adltLoadInfo) - for (OutputSection *sec : info.phSections) { - auto *isec = getInputSection(sec); - assert(isec); - auto *file = isec->file; - if (!file) // skip generated sections. - continue; // TODO: fix .rodata_$ADLT_POSTFIX sections. - auto *soFile = cast>(file); - soFile->programHeaderIndexes.insert(info.phIndex); - } - - // Check outputs - auto adltTraceNeeded = false; // debug hint - auto trace = [&](auto *file, auto &indexes) { - lld::outs() << "ADLT: " << file->soName << ":\n"; - for (auto &it : indexes) - lld::outs() << it << " "; - lld::outs() << '\n'; - }; - for (ELFFileBase *baseFile : ctx->sharedFilesExtended) { - auto *soFile = cast>(baseFile); - auto &indexes = soFile->programHeaderIndexes; - assert(!indexes.empty()); - if (adltTraceNeeded) - trace(soFile, indexes); - } + if (config->adlt) + lastFileIdx = getCurrentFileIdx(sec); } // Add a TLS segment if any. @@ -2547,7 +2602,7 @@ SmallVector Writer::createPhdrs(Partition &part) { if (config->adlt) tlsHdr = addHdr(PT_TLS, PF_R); tlsHdr->add(sec); - } + } if (!config->adlt && tlsHdr->firstSec) ret.push_back(tlsHdr);