diff --git a/.gitignore b/.gitignore index 20c4f52cd37860e6d124bf4859c9c795d2db5e53..46ab415ae35f647b721eda5cf475f7cb7b1fc5ed 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,6 @@ pythonenv* /clang/utils/analyzer/projects/*/RefScanBuildResults # automodapi puts generated documentation files here. /lldb/docs/python_api/ + + +musl_copy_* \ No newline at end of file diff --git a/lld/ELF/Adlt.cpp b/lld/ELF/Adlt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3d8f4f56e797c0de62b39ddb1d5cb9591330218 --- /dev/null +++ b/lld/ELF/Adlt.cpp @@ -0,0 +1,65 @@ +//===- Adlt.cpp -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// OHOS_LOCAL begin +#include "Adlt.h" +#include "llvm/Support/Casting.h" + +#include "InputFiles.h" + +using namespace llvm; + +using namespace lld; +using namespace lld::elf; +using namespace llvm::object; + +template +SharedFileExtended *AdltCtx::getSoExt(InputFile *file) { + assert(file); + return cast>(file); +} + +template +SharedFileExtended *AdltCtx::getSoExt(size_t orderId) { + assert(orderId < sharedFilesExtended.size()); + return cast>(sharedFilesExtended[orderId]); +} + +template +void AdltCtx::buildSymbolsHist(std::vector &files) { + for (auto *file : files) + if (auto *soExt = getSoExt(file)) + soExt->buildSymbolsHist(); + assert(!symNamesHist.empty()); +} + +void AdltCtx::scanDuplicatedSymbols() { + assert(!symNamesHist.empty()); + for (auto entry : symNamesHist) + if (entry.second > 1) + duplicatedSymNames.insert(CachedHashStringRef(entry.first)); + symNamesHist.clear(); +} + +// TODO: inherit from SharedFile +template SharedFileExtended *AdltCtx::getSoExt(InputFile *); +template SharedFileExtended *AdltCtx::getSoExt(InputFile *); +template SharedFileExtended *AdltCtx::getSoExt(InputFile *); +template SharedFileExtended *AdltCtx::getSoExt(InputFile *); + +template SharedFileExtended *AdltCtx::getSoExt(size_t); +template SharedFileExtended *AdltCtx::getSoExt(size_t); +template SharedFileExtended *AdltCtx::getSoExt(size_t); +template SharedFileExtended *AdltCtx::getSoExt(size_t); + +template void AdltCtx::buildSymbolsHist(std::vector &); +template void AdltCtx::buildSymbolsHist(std::vector &); +template void AdltCtx::buildSymbolsHist(std::vector &); +template void AdltCtx::buildSymbolsHist(std::vector &); + +// OHOS_LOCAL end diff --git a/lld/ELF/Adlt.h b/lld/ELF/Adlt.h new file mode 100644 index 0000000000000000000000000000000000000000..b6751cf54607edaea0a222f7e3386cff7cfc8487 --- /dev/null +++ b/lld/ELF/Adlt.h @@ -0,0 +1,62 @@ +//===- Adlt.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// OHOS_LOCAL begin +#ifndef LLD_ELF_ADLT_H +#define LLD_ELF_ADLT_H + +#include "llvm/ADT/CachedHashString.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Support/Endian.h" +#include + +namespace lld { +namespace elf { + +class ELFFileBase; +class InputFile; +class Symbol; +struct PhdrEntry; + +template class SharedFileExtended; +struct PhdrEntry; + +class AdltCtx { +public: + llvm::SmallVector sharedFilesExtended; + + void scanDuplicatedSymbols(); + + template void buildSymbolsHist(std::vector &files); + + template SharedFileExtended *getSoExt(InputFile *file); + template SharedFileExtended *getSoExt(size_t orderId); + + llvm::SetVector commonProgramHeaders; + + bool withCfi = false; + + // From input .rela.dyn, .rela.plt: + // Keep input library indexes that are needed for got/plt symbol + llvm::DenseMap> + gotPltInfo; // sym, soFile->orderIdx array; + + llvm::DenseMap + symNamesHist; // hash, count usages + llvm::DenseSet duplicatedSymNames; +}; + +// The only instance of Ctx struct. +extern std::unique_ptr adltCtx; + +} // namespace elf +} // namespace lld + +#endif // LLD_ELF_ADLT_H +// OHOS_LOCAL end diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index b23684819a23967127a1cf2e3f5fea57d9733731..810ff3f5d9d9854c2e505c2aee7217c46119f5ee 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -44,6 +44,8 @@ public: uint32_t getThunkSectionSpacing() const override; bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; bool usesOnlyLowPageBits(RelType type) const override; + void deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const override; // ADLT void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; @@ -79,6 +81,20 @@ 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; + case R_AARCH64_TLSDESC: + return R_TLSDESC; + case R_AARCH64_TLS_TPREL64: + return R_TPREL; + default: + break; + } + switch (type) { case R_AARCH64_ABS16: case R_AARCH64_ABS32: @@ -335,8 +351,84 @@ static void writeSMovWImm(uint8_t *loc, uint32_t imm) { write32le(loc, inst | ((imm & 0xFFFF) << 5)); } +static void adltRelocateDebugMessage(StringRef title, uint8_t *loc, + const Relocation &rel, uint64_t &val) { + lld::outs() << title + << " loc: " << loc /*<< " loc val: " << Twine::utohexstr(*loc)*/ + << " rel expr: " << rel.expr + << " rel type: " << lld::toString(rel.type) << " rel offset: 0x" + << Twine::utohexstr(rel.offset) << " rel addend: 0x" + << Twine::utohexstr(rel.addend) + << " val: 0x" << Twine::utohexstr(val) + << " rel sym: " << (rel.sym ? rel.sym->getName() : "null!"); + + if (rel.sym && rel.sym->isDefined()) { + auto d = cast(rel.sym); + lld::outs() << ": section " << d->section->name + << ", value 0x" << Twine::utohexstr(d->value); + } + lld::outs() << '\n'; +} + +void AArch64::deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const { + bool isDebug = false; + if (isDebug) + adltRelocateDebugMessage("[AArch64::deRelocate]: ", loc, rel, *val); + + auto orClear32le = [&]() { + write32le(loc, read32le(loc) & ~((1 << 26) -1)); + }; + + auto orClearAArch64Imm = [&]() { + write32le(loc, read32le(loc) & ~(0xFFF << 10)); + }; + + switch (rel.type) { + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_MOVW_UABS_G0_NC: + case R_AARCH64_MOVW_UABS_G1_NC: + case R_AARCH64_MOVW_UABS_G2_NC: + case R_AARCH64_MOVW_UABS_G3: + case R_AARCH64_TSTBR14: + orClear32le(); + break; + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: + case R_AARCH64_LD64_GOTPAGE_LO15: + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12: + orClearAArch64Imm(); + break; + } +} + void AArch64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { + bool isDebug = false; + if (config->adlt) { + deRelocate(loc, rel, &val); + } + if (config->adlt && isDebug) + adltRelocateDebugMessage("[AArch64::relocate]: ", loc, rel, val); + switch (rel.type) { case R_AARCH64_ABS16: case R_AARCH64_PREL16: @@ -366,6 +458,8 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, checkInt(loc, val, 33, rel); LLVM_FALLTHROUGH; case R_AARCH64_ADR_PREL_PG_HI21_NC: + if (config->adlt && *(uint32_t*)loc == 0xd503201f) // ignore nop + break; write32AArch64Addr(loc, val >> 12); break; case R_AARCH64_ADR_PREL_LO21: diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index 6d12da1f4b085d8b47ffd4db9535a4417158e743..2361f8682d2799c33343dd09c2f26562831a8c62 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -46,6 +46,7 @@ add_lld_library(lldELF Target.cpp Thunks.cpp Writer.cpp + Adlt.cpp LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index d6babe9f74c256bcf7f16f29389bf7b6712413c2..2eaee71cca74f71662b3a58e2f75b1efb3157919 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -220,6 +220,10 @@ struct Configuration { std::vector> shuffleSections; bool singleRoRx; bool shared; + // OHOS_LOCAL begin + bool adlt = false; + bool adltTrace = false; + // OHOS_LOCAL end bool symbolic; bool isStatic = false; bool sysvHash = false; @@ -382,7 +386,7 @@ struct DuplicateSymbol { struct Ctx { SmallVector> memoryBuffers; - SmallVector objectFiles; + SmallVector objectFiles; SmallVector sharedFiles; SmallVector binaryFiles; SmallVector bitcodeFiles; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index daf16ed3ca444ad4c336df0c0201d7d8b672584c..492956ef3221213af139cbbbd040d760594c7148 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -24,6 +24,7 @@ #include "Driver.h" #include "Config.h" +#include "Adlt.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" @@ -76,6 +77,7 @@ using namespace lld::elf; std::unique_ptr elf::config; std::unique_ptr elf::ctx; +std::unique_ptr elf::adltCtx; // OHOS_LOCAL std::unique_ptr elf::driver; static void setConfigs(opt::InputArgList &args); @@ -278,8 +280,12 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) { // the directory part is ignored. Note that path may be a temporary and // cannot be stored into SharedFile::soName. path = mbref.getBufferIdentifier(); - files.push_back( - make(mbref, withLOption ? path::filename(path) : path)); + if (config->adlt) + files.push_back(createSharedFileExtended( + mbref, withLOption ? path::filename(path) : path)); + else + files.push_back( + make(mbref, withLOption ? path::filename(path) : path)); return; case file_magic::bitcode: files.push_back(make(mbref, "", 0, inLib)); @@ -847,7 +853,8 @@ static std::pair getPackDynRelocs(opt::InputArgList &args) { static void readCallGraph(MemoryBufferRef mb) { // Build a map from symbol name to section DenseMap map; - for (ELFFileBase *file : ctx->objectFiles) + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getSymbols()) map[sym->getName()] = sym; @@ -926,6 +933,7 @@ processCallGraphRelocations(SmallVector &symbolIndices, template static void readCallGraphsFromObjectFiles() { SmallVector symbolIndices; ArrayRef cgProfile; + // ADLT TODO for (auto file : ctx->objectFiles) { auto *obj = cast>(file); if (!processCallGraphRelocations(symbolIndices, cgProfile, obj)) @@ -1091,6 +1099,8 @@ static void readConfigs(opt::InputArgList &args) { else if (arg->getOption().matches(OPT_Bsymbolic)) 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); @@ -1106,7 +1116,7 @@ static void readConfigs(opt::InputArgList &args) { config->dwoDir = args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq); config->dynamicLinker = getDynamicLinker(args); config->ehFrameHdr = - args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); + args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, config->adlt); config->emitLLVM = args.hasArg(OPT_plugin_opt_emit_llvm, false); config->emitRelocs = args.hasArg(OPT_emit_relocs); config->callGraphProfileSort = args.hasFlag( @@ -1222,7 +1232,7 @@ static void readConfigs(opt::InputArgList &args) { config->searchPaths = args::getStrings(args, OPT_library_path); config->sectionStartMap = getSectionStartMap(args); - config->shared = args.hasArg(OPT_shared); + config->shared = config->adlt ? true : args.hasArg(OPT_shared); config->singleRoRx = !args.hasFlag(OPT_rosegment, OPT_no_rosegment, true); config->soName = args.getLastArgValue(OPT_soname); config->sortSection = getSortSection(args); @@ -1824,7 +1834,8 @@ static void excludeLibs(opt::InputArgList &args) { sym->versionId = VER_NDX_LOCAL; }; - for (ELFFileBase *file : ctx->objectFiles) + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) visit(file); for (BitcodeFile *file : ctx->bitcodeFiles) @@ -2020,7 +2031,8 @@ static void writeDependencyFile() { // symbols of type CommonSymbol. static void replaceCommonSymbols() { llvm::TimeTraceScope timeScope("Replace common symbols"); - for (ELFFileBase *file : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) { if (!file->hasCommonSyms) continue; for (Symbol *sym : file->getGlobalSymbols()) { @@ -2096,7 +2108,8 @@ static void findKeepUniqueSections(opt::InputArgList &args) { // Visit the address-significance table in each object file and mark each // referenced symbol as address-significant. - for (InputFile *f : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (InputFile *f : files) { auto *obj = cast>(f); ArrayRef syms = obj->getSymbols(); if (obj->addrsigSec) { @@ -2350,7 +2363,8 @@ static void redirectSymbols(ArrayRef wrapped) { return; // Update pointers in input files. - parallelForEach(ctx->objectFiles, [&](ELFFileBase *file) { + auto files = ctx->objectFiles; + parallelForEach(files, [&](ELFFileBase *file) { for (Symbol *&sym : file->getMutableGlobalSymbols()) if (Symbol *s = map.lookup(sym)) sym = s; @@ -2385,7 +2399,8 @@ static uint32_t getAndFeatures() { return 0; uint32_t ret = -1; - for (ELFFileBase *f : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (ELFFileBase *f : files) { uint32_t features = f->andFeatures; checkAndReportMissingFeature( @@ -2468,6 +2483,25 @@ static void postParseObjectFile(ELFFileBase *file) { } } +static void postParseSharedFile(ELFFileBase *file) { + switch (config->ekind) { + case ELF32LEKind: + adltCtx->getSoExt(file)->postParse(); + break; + case ELF32BEKind: + adltCtx->getSoExt(file)->postParse(); + break; + case ELF64LEKind: + adltCtx->getSoExt(file)->postParse(); + break; + case ELF64BEKind: + adltCtx->getSoExt(file)->postParse(); + break; + default: + llvm_unreachable(""); + } +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. void LinkerDriver::link(opt::InputArgList &args) { @@ -2514,11 +2548,20 @@ void LinkerDriver::link(opt::InputArgList &args) { for (auto *arg : args.filtered(OPT_trace_symbol)) symtab->insert(arg->getValue())->traced = true; + if (config->adlt) // Init ADLT context + elf::adltCtx = std::make_unique(); + // Handle -u/--undefined before input files. If both a.a and b.so define foo, // -u foo a.a b.so will extract a.a. for (StringRef name : config->undefined) addUnusedUndefined(name)->referenced = true; + // Fill duplicatedSymNames for defined syms. This will help to find duplicates. + if (config->adlt) { + invokeELFT(adltCtx->buildSymbolsHist, files); + adltCtx->scanDuplicatedSymbols(); + } + // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. This process might // add files to the link, via autolinking, these files are always @@ -2537,8 +2580,9 @@ void LinkerDriver::link(opt::InputArgList &args) { // producing a shared library. // We also need one if any shared libraries are used and for pie executables // (probably because the dynamic linker needs it). - config->hasDynSymTab = - !ctx->sharedFiles.empty() || config->isPic || config->exportDynamic; + config->hasDynSymTab = (config->adlt ? !adltCtx->sharedFilesExtended.empty() + : !ctx->sharedFiles.empty()) || + config->isPic || config->exportDynamic; // Some symbols (such as __ehdr_start) are defined lazily only when there // are undefined symbols for them, so we add these to trigger that logic. @@ -2593,6 +2637,9 @@ void LinkerDriver::link(opt::InputArgList &args) { // No more lazy bitcode can be extracted at this point. Do post parse work // like checking duplicate symbols. + if (config->adlt) + parallelForEach(adltCtx->sharedFilesExtended, postParseSharedFile); + parallelForEach(ctx->objectFiles, initializeLocalSymbols); parallelForEach(ctx->objectFiles, postParseObjectFile); parallelForEach(ctx->bitcodeFiles, @@ -2699,6 +2746,12 @@ void LinkerDriver::link(opt::InputArgList &args) { // Now that we have a complete list of input files. // Beyond this point, no new files are added. // Aggregate all input sections into one place. + if (config->adlt) + for (auto *file : adltCtx->sharedFilesExtended) + for (InputSectionBase *s : file->getSections()) + if (file->isValidSection(s)) + inputSections.push_back(s); + for (InputFile *f : ctx->objectFiles) for (InputSectionBase *s : f->getSections()) if (s && s != &InputSection::discarded) diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp index 51f3dc3a056e139ae3c92a47d6300a280f72a384..0145d9b9ba0cfdfe59b380ae2365f56c40b0d396 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -64,6 +64,13 @@ static void handleColorDiagnostics(opt::InputArgList &args) { error("unknown option: --color-diagnostics=" + s); } +static void handleAdltOption(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_adlt); + if (!arg) + return; + // slld::outs() << "adlt is active\n"; +} + static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { StringRef s = arg->getValue(); @@ -120,6 +127,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef argv) { args = this->ParseArgs(vec, missingIndex, missingCount); handleColorDiagnostics(args); + handleAdltOption(args); if (missingCount) error(Twine(args.getArgString(missingIndex)) + ": missing argument"); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2518bbaa9af6e6cb301915a7cc2fa4824e0c0d31..c4e0962dfa832d4deb45226fdefebd68e9b87a9f 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -8,6 +8,7 @@ #include "InputFiles.h" #include "Config.h" +#include "Adlt.h" #include "DWARF.h" #include "Driver.h" #include "InputSection.h" @@ -184,6 +185,14 @@ template static void doParseFile(InputFile *file) { message(toString(file)); // .so file + if (config->adlt) + if (auto *f = dyn_cast>(file)) { + f->orderIdx = adltCtx->sharedFilesExtended.size(); + adltCtx->sharedFilesExtended.push_back(f); + f->parse(); + return; + } + if (auto *f = dyn_cast(file)) { f->parse(); return; @@ -326,6 +335,11 @@ static const Elf_Shdr *findSection(ArrayRef sections, uint32_t type) { return nullptr; } +// OHOS_LOCAL begin +void ELFFileBase::buildSymbolsHist() {} +bool ELFFileBase::isValidSection(InputSectionBase *s) const { return true; } +// OHOS_LOCAL end + template void ELFFileBase::init() { using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; @@ -393,6 +407,11 @@ StringRef ObjFile::getShtGroupSignature(ArrayRef sections, return CHECK(sym.getName(this->stringTable), this); } +template +StringRef ObjFile::getUniqueName(StringRef origName) const { + return origName; +} + template bool ObjFile::shouldMerge(const Elf_Shdr &sec, StringRef name) { // On a regular link we don't merge sections if -O0 (default is -O1). This @@ -509,6 +528,11 @@ static void handleSectionGroup(ArrayRef sections, prev->nextInSectionGroup = head; } +template +ArrayRef ObjFile::getShndxTable() { + return shndxTable; +} + template void ObjFile::initializeSections(bool ignoreComdats, const llvm::object::ELFFile &obj) { @@ -548,6 +572,15 @@ void ObjFile::initializeSections(bool ignoreComdats, this->sections[i] = &InputSection::discarded; continue; } + auto secName = check(obj.getSectionName(sec, shstrtab)); + if (config->adlt && sec.sh_type == SHT_NULL) { + // TODO: add unique for output only + auto name = getUniqueName(secName); + this->sections[i] = createInputSection(i, sec, name); + this->sections[i]->address = sec.sh_addr; + this->sections[i]->size = sec.sh_size; + sectionsMap[sec.sh_addr] = i; + } switch (sec.sh_type) { case SHT_GROUP: { @@ -569,9 +602,15 @@ void ObjFile::initializeSections(bool ignoreComdats, symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this) .second; if (keepGroup) { - if (config->relocatable) - this->sections[i] = createInputSection( - i, sec, check(obj.getSectionName(sec, shstrtab))); + if (config->relocatable) { + // TODO: add unique for output only + auto name = config->adlt ? getUniqueName(secName) : secName; + this->sections[i] = createInputSection(i, sec, name); + if (config->adlt) { + this->sections[i]->address = sec.sh_addr; + this->sections[i]->size = sec.sh_size; + } + } selectedGroups.push_back(entries); continue; } @@ -598,8 +637,13 @@ void ObjFile::initializeSections(bool ignoreComdats, ctx->hasSympart.store(true, std::memory_order_relaxed); LLVM_FALLTHROUGH; default: - this->sections[i] = - createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab))); + // TODO: add unique for output only + auto name = config->adlt ? getUniqueName(secName) : secName; + this->sections[i] = createInputSection(i, sec, name); + if (config->adlt) { + this->sections[i]->address = sec.sh_addr; + this->sections[i]->size = sec.sh_size; + } } } @@ -789,7 +833,7 @@ template static uint32_t readAndFeatures(const InputSection &sec) { ArrayRef data = sec.rawData; auto reportFatal = [&](const uint8_t *place, const char *msg) { fatal(toString(sec.file) + ":(" + sec.name + "+0x" + - Twine::utohexstr(place - sec.rawData.data()) + "): " + msg); + utohexstr(place - sec.rawData.data()) + "): " + msg); }; while (!data.empty()) { // Read one NOTE record. @@ -995,11 +1039,12 @@ 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)) + const bool doNotMerge = config->adlt && name.startswith(".rodata"); + if ((sec.sh_flags & SHF_MERGE) && !doNotMerge && shouldMerge(sec, name)) return make(*this, sec, name); + return make(*this, sec, name); } - // Initialize this->Symbols. this->Symbols is a parallel array as // its corresponding ELF symbol table. template @@ -1011,8 +1056,20 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { // Some entries have been filled by LazyObjFile. for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) - if (!symbols[i]) - symbols[i] = symtab.insert(CHECK(eSyms[i].getName(stringTable), this)); + if (!symbols[i]) { + StringRef name = CHECK(eSyms[i].getName(stringTable), this); + if (config->adlt && eSyms[i].isDefined() && + adltCtx->duplicatedSymNames.count(CachedHashStringRef(name)) != 0) { + if (name == "__cfi_check" && !adltCtx->withCfi) { + adltCtx->withCfi = true; + if (config->adltTrace) + lld::outs() << "[ADLT] Cfi mode is ON\n"; + } + // TODO: add unique for output only + name = this->getUniqueName(name); + } + symbols[i] = symtab.insert(name); + } // Perform symbol resolution on non-local symbols. SmallVector undefineds; @@ -1028,10 +1085,21 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { uint8_t stOther = eSym.st_other; uint8_t type = eSym.getType(); uint64_t value = eSym.st_value; + if (config->adlt && secIdx != SHN_ABS) { + auto p = obj.getSection(secIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *eSec = *p; + if (type != STT_TLS) + value -= eSec->sh_addr; + } uint64_t size = eSym.st_size; Symbol *sym = symbols[i]; sym->isUsedInRegularObj = true; + if (config->adlt) + sym->exportDynamic = true; if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON)) { if (value == 0 || value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + sym->getName() + @@ -1060,6 +1128,8 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { eSym.getType()}); sym->isUsedInRegularObj = true; sym->referenced = true; + if (config->adlt) + sym->exportDynamic = true; } } @@ -1095,9 +1165,16 @@ template void ObjFile::initializeLocalSymbols() { if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type, /*discardedSecIdx=*/secIdx); - else + else { + auto p = this->getObj().getSection(secIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *eSec = *p; + auto value = config->adlt ? eSym.st_value - eSec->sh_addr : eSym.st_value; new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, - eSym.st_value, eSym.st_size, sec); + value, eSym.st_size, sec); + } symbols[i]->isUsedInRegularObj = true; } } @@ -1290,6 +1367,36 @@ std::vector SharedFile::parseVerneed(const ELFFile &obj, return verneeds; } +template +std::vector SharedFileExtended::parseVerneed(const ELFFile &obj, + const typename ELFT::Shdr *sec) { + if (!sec) + return {}; + std::vector verneeds; + ArrayRef data = CHECK(obj.getSectionContents(*sec), this); + const uint8_t *verneedBuf = data.begin(); + for (unsigned i = 0; i != sec->sh_info; ++i) { + if (verneedBuf + sizeof(typename ELFT::Verneed) > data.end()) + fatal(toString(this) + " has an invalid Verneed"); + auto *vn = reinterpret_cast(verneedBuf); + const uint8_t *vernauxBuf = verneedBuf + vn->vn_aux; + for (unsigned j = 0; j != vn->vn_cnt; ++j) { + if (vernauxBuf + sizeof(typename ELFT::Vernaux) > data.end()) + fatal(toString(this) + " has an invalid Vernaux"); + auto *aux = reinterpret_cast(vernauxBuf); + if (aux->vna_name >= this->stringTable.size()) + fatal(toString(this) + " has a Vernaux with an invalid vna_name"); + uint16_t version = aux->vna_other & VERSYM_VERSION; + if (version >= verneeds.size()) + verneeds.resize(version + 1); + verneeds[version] = aux->vna_name; + vernauxBuf += aux->vna_next; + } + verneedBuf += vn->vn_next; + } + return verneeds; +} + // We do not usually care about alignments of data in shared object // files because the loader takes care of it. However, if we promote a // DSO symbol to point to .bss due to copy relocation, we need to keep @@ -1497,6 +1604,387 @@ template void SharedFile::parse() { } } +template +SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, + StringRef soName) + : ObjFile(InputFile::SharedKind, mb, soName), soName(soName) {} + +template void SharedFileExtended::buildSymbolsHist() { + ArrayRef eSyms = this->template getELFSyms(); + for (size_t i = this->firstGlobal, end = eSyms.size(); i != end; ++i) { + if (!eSyms[i].isDefined()) + continue; + StringRef name = CHECK(eSyms[i].getName(this->stringTable), this); + adltCtx->symNamesHist[CachedHashStringRef(name)]++; + } +} + +template +bool SharedFileExtended::isValidSection(InputSectionBase *s) const { + if (!s || s == &InputSection::discarded) + return false; + uint32_t type = s->type; + StringRef name = s->name; + + bool isBaseType = type == SHT_NOBITS || type == SHT_NOTE || + type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY; + // TODO: fix .debug-* sections relocation + // TODO: rename sections at outputStage. + bool isNeededProgBits = + type == SHT_PROGBITS && + !(name.startswith(".got") || name.startswith(".plt") || + name.startswith(".eh_frame_hdr") || name.startswith(".debug_")); + bool ret = isBaseType || isNeededProgBits; + return ret; +} + +template +bool SharedFileExtended::isDynamicSection(InputSectionBase *s) const { + // TODO: rename sections at outputStage. + return s->type == llvm::ELF::SHT_NULL || s->name.startswith(".got.plt"); +} + +template void SharedFileExtended::parse(bool ignoreComdats) { + ObjFile::parse(ignoreComdats); + parseDynamics(); + parseElfSymTab(); +} + +template void SharedFileExtended::postParse() { + ObjFile::initializeLocalSymbols(); + ObjFile::postParse(); +} + +template +StringRef SharedFileExtended::getUniqueName(StringRef input) const { + if (input.empty()) return input; + auto suffix = Twine("__") + Twine::utohexstr(this->orderIdx); + return saver().save(input + suffix); +} + +template +Defined &SharedFileExtended::getDefinedLocalSym(uint64_t offset) { + auto getSym = [&](unsigned offs) { + return localSymbols[this->definedSymbolsMap[offs]]; + }; + auto *s = getSym(offset); + if (!s || s == localSymbols[0]) { + auto sec = findSection(offset); + s = getSym(sec->address); + } + assert(s && s->isDefined()); + return cast(*s); +} + +template +InputSectionBase &SharedFileExtended::getSection(uint64_t offset) { + auto *sec = this->sections[this->sectionsMap[offset]]; + if (offset && sec->type == SHT_NULL) + sec = findSection(offset); + return *sec; +} + +template +InputSectionBase &SharedFileExtended::getSectionByOrder(size_t idx) { + auto *sec = this->sections[idx]; + if (!sec) + sec = &InputSection::discarded; + return *sec; +} + +template +InputSectionBase *SharedFileExtended::findSection(uint64_t offset) { + llvm::SmallVector candidates; + for (InputSectionBase *sec : this->sections) { + if (!sec) + continue; + auto low = sec->address; + auto high = low + sec->size; + if (offset >= low && offset < high) + candidates.push_back(sec); + } + if (candidates.empty()) // no suitable items found + return nullptr; + llvm::sort(candidates, + [](auto *a, auto *b) { return a->address < b->address; }); + return *candidates.begin(); +} + +template +Symbol &SharedFileExtended::getDynamicSymbol(size_t symbolIndex) const { + return *this->symbols[symbolIndex]; +} +template +Symbol &SharedFileExtended::getLocalSymbol(size_t symbolIndex) const{ + assert(symbolIndex && (symbolIndex < localSymbols.size())); + return *localSymbols[symbolIndex]; +} + +template +Symbol &SharedFileExtended::getSymbol(size_t symbolIndex, + bool fromDynamic) { + if (!symbolIndex) + return *localSymbols[0]; + /* TODO + if (symbolIndex > static_cast(symTabFirstGlobal)) + return getDynamicSymbol(symbolIndex - (symTabFirstGlobal + 1)); + return fromDynamic ? getDynamicSymbol(symbolIndex) + : getLocalSymbol(symbolIndex); */ + + Symbol &sym = fromDynamic ? getDynamicSymbol(symbolIndex) + : getLocalSymbol(symbolIndex); + StringRef name = sym.getName(); + if (name.empty()) + return sym; + // check SymbolTable + auto res = elf::symtab->find(name); + if (res && (res->exportDynamic || res->versionId)) + 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 +ArrayRef SharedFileExtended::getLocalSymbols() { + assert(!localSymbols.empty()); + return llvm::makeArrayRef(localSymbols).slice(0, symTabFirstGlobal); +} + +template void SharedFileExtended::parseDynamics() { + const ELFFile obj = this->getObj(); + ArrayRef sections = this->template getELFShdrs(); + + ArrayRef dynamicTags; + const Elf_Shdr *versymSec = nullptr; + const Elf_Shdr *verdefSec = nullptr; + const Elf_Shdr *verneedSec = nullptr; + + // parse external lib deps + int secIdx = 0; + for (const Elf_Shdr &sec : sections) { + switch (sec.sh_type) { + case SHT_DYNAMIC: + dynamicTags = + CHECK(obj.template getSectionContentsAsArray(sec), this); + break; + case SHT_DYNSYM: + dynSymSecIdx = secIdx; + break; + case SHT_SYMTAB: + symTabSecIdx = secIdx; + break; + case SHT_SYMTAB_SHNDX: + symTabShndxSecIdx = secIdx; + break; + case SHT_GNU_versym: + versymSec = &sec; + break; + case SHT_GNU_verdef: + verdefSec = &sec; + break; + case SHT_GNU_verneed: + verneedSec = &sec; + break; + } + auto secName = check(this->getObj().getSectionName(sec)); + if (secName == ".got.plt") + gotPltSecIdx = secIdx; + secIdx++; + } + + if (versymSec && this->numELFSyms == 0) { + error("SHT_GNU_versym should be associated with symbol table"); + return; + } + + // Search for a DT_SONAME tag to initialize this->soName. + for (const Elf_Dyn &dyn : dynamicTags) { + if (dyn.d_tag == DT_NEEDED) { + uint64_t val = dyn.getVal(); + if (val >= this->stringTable.size()) + fatal(toString(this) + ": invalid DT_NEEDED entry"); + dtNeeded.push_back(this->stringTable.data() + val); + } else if (dyn.d_tag == DT_SONAME) { + uint64_t val = dyn.getVal(); + if (val >= this->stringTable.size()) + fatal(toString(this) + ": invalid DT_SONAME entry"); + soName = this->stringTable.data() + val; + } + } + + verdefs = parseVerdefs(obj.base(), verdefSec); + std::vector verneeds = parseVerneed(obj, verneedSec); + + // Parse ".gnu.version" section which is a parallel array for the symbol + // table. If a given file doesn't have a ".gnu.version" section, we use + // VER_NDX_GLOBAL. + size_t size = this->numELFSyms - this->firstGlobal; + std::vector versyms(size, VER_NDX_GLOBAL); + if (versymSec) { + ArrayRef versym = + CHECK(obj.template getSectionContentsAsArray(*versymSec), + this) + .slice(this->firstGlobal); + for (size_t i = 0; i < size; ++i) + versyms[i] = versym[i].vs_index; + } + + // System libraries can have a lot of symbols with versions. Using a + // fixed buffer for computing the versions name (foo@ver) can save a + // lot of allocations. + SmallString<0> versionedNameBuffer; + + // Add symbols to the symbol table. + SymbolTable &symtab = *elf::symtab; + ArrayRef syms = this->template getGlobalELFSyms(); + for (size_t i = 0, e = syms.size(); i != e; ++i) { + const Elf_Sym &sym = syms[i]; + + // ELF spec requires that all local symbols precede weak or global + // symbols in each symbol table, and the index of first non-local symbol + // is stored to sh_info. If a local symbol appears after some non-local + // symbol, that's a violation of the spec. + StringRef name = CHECK(sym.getName(this->stringTable), this); + // Add postfix for defined duplicates. + if (config->adlt && sym.isDefined() && + adltCtx->duplicatedSymNames.count(CachedHashStringRef(name)) != 0) + name = getUniqueName(name); // TODO: add unique for output only + + if (sym.getBinding() == STB_LOCAL) { + warn("found local symbol '" + name + + "' in global part of symbol table in file " + toString(this)); + continue; + } + + uint16_t idx = versyms[i] & ~VERSYM_HIDDEN; + if (sym.isUndefined()) { + // For unversioned undefined symbols, VER_NDX_GLOBAL makes more sense but + // as of binutils 2.34, GNU ld produces VER_NDX_LOCAL. + if (idx != VER_NDX_LOCAL && idx != VER_NDX_GLOBAL) { + if (idx >= verneeds.size()) { + error("corrupt input file: version need index " + Twine(idx) + + " for symbol " + name + " is out of bounds\n>>> defined in " + + toString(this)); + continue; + } + StringRef verName = this->stringTable.data() + verneeds[idx]; + versionedNameBuffer.clear(); + name = saver().save( + (name + "@" + verName).toStringRef(versionedNameBuffer)); + } + Symbol *s = symtab.addSymbol( + Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); + s->exportDynamic = true; + if (s->isUndefined() && sym.getBinding() != STB_WEAK && + config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) + requiredSymbols.push_back(s); + continue; + } + // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly + // assigns VER_NDX_LOCAL to this section global symbol. Here is a + // workaround for this bug. + if (config->emachine == EM_MIPS && idx == VER_NDX_LOCAL && + name == "_gp_disp") + continue; + + uint32_t alignment = getAlignment(sections, sym); + if (!(versyms[i] & VERSYM_HIDDEN)) { + auto *s = symtab.addSymbol( + SharedSymbol{*this, name, sym.getBinding(), sym.st_other, + sym.getType(), sym.st_value, sym.st_size, alignment}); + if (s->file == this) + s->verdefIndex = idx; + } + + // Also add the symbol with the versioned name to handle undefined symbols + // with explicit versions. + if (idx == VER_NDX_GLOBAL) + continue; + + if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) { + error("corrupt input file: version definition index " + Twine(idx) + + " for symbol " + name + " is out of bounds\n>>> defined in " + + toString(this)); + continue; + } + + StringRef verName = + this->stringTable.data() + + reinterpret_cast(verdefs[idx])->getAux()->vda_name; + versionedNameBuffer.clear(); + name = (name + "@" + verName).toStringRef(versionedNameBuffer); + auto *s = symtab.addSymbol( + SharedSymbol{*this, saver().save(name), sym.getBinding(), sym.st_other, + sym.getType(), sym.st_value, sym.st_size, alignment}); + if (s->file == this) + s->verdefIndex = idx; + } +} + +template void SharedFileExtended::parseElfSymTab() { + const ELFFile obj = this->getObj(); + ArrayRef eSections = this->template getELFShdrs(); + + // Find a symbol table. + const Elf_Shdr *eSymtabSec = ::findSection(eSections, SHT_SYMTAB); + if (!eSymtabSec) + return; + + symTabFirstGlobal = eSymtabSec->sh_info; + + ArrayRef eSyms = CHECK(obj.symbols(eSymtabSec), this); + auto numESyms = uint32_t(eSyms.size()); + auto eStringTable = CHECK(obj.getStringTableForSymtab(*eSymtabSec, eSections), this); + this->localSymbols.resize(numESyms); + + for (size_t i = 0; i < numESyms; i++) { + const Elf_Sym &eSym = eSyms[i]; + StringRef name(eStringTable.data() + eSym.st_name); + auto bind = eSym.getBinding(); + auto type = eSym.getType(); + auto other = eSym.st_other; + if (eSym.isDefined()) { + auto secIdx = eSym.st_shndx; + if (LLVM_UNLIKELY(secIdx == SHN_XINDEX)) + secIdx = check( + getExtendedSymbolTableIndex(eSym, i, this->getShndxTable())); + else if (secIdx >= SHN_LORESERVE) + secIdx = 0; + auto p = obj.getSection(secIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *eSec = *p; + InputSectionBase *sec = this->sections[secIdx]; + auto val = eSym.st_value; + if (type != STT_TLS) + val -= eSec->sh_addr; + auto dynSym = llvm::find_if(this->symbols, [=](const Symbol *s) { + return s && s->getName() == name; + }); + bool isInDynSym = dynSym != this->symbols.end(); + if (!isInDynSym) + name = getUniqueName(name); // TODO: add unique for output only + /*if (name == "TLS_data1") // debug hint + lld::outs() << name << '\n'; */ + this->localSymbols[i] = + make(this, name, bind, other, type, val, eSym.st_size, sec); + this->definedSymbolsMap[eSym.st_value] = i; + } else { + this->localSymbols[i] = make(this, name, bind, other, type, + /*discardedSecIdx=*/i); + } + } +} + static ELFKind getBitcodeELFKind(const Triple &t) { if (t.isLittleEndian()) return t.isArch64Bit() ? ELF64LEKind : ELF32LEKind; @@ -1740,6 +2228,27 @@ ELFFileBase *elf::createObjFile(MemoryBufferRef mb, StringRef archiveName, return f; } +ELFFileBase *elf::createSharedFileExtended(MemoryBufferRef mb, StringRef soName) { + ELFFileBase *f; + switch (getELFKind(mb, soName)) { + case ELF32LEKind: + f = make>(mb, soName); + break; + case ELF32BEKind: + f = make>(mb, soName); + break; + case ELF64LEKind: + f = make>(mb, soName); + break; + case ELF64BEKind: + f = make>(mb, soName); + break; + default: + llvm_unreachable("getELFKind"); + } + return f; +} + template void ObjFile::parseLazy() { const ArrayRef eSyms = this->getELFSyms(); SymbolTable &symtab = *elf::symtab; @@ -1792,3 +2301,8 @@ template void SharedFile::parse(); template void SharedFile::parse(); template void SharedFile::parse(); template void SharedFile::parse(); + +template class elf::SharedFileExtended; +template class elf::SharedFileExtended; +template class elf::SharedFileExtended; +template class elf::SharedFileExtended; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index a24e664a7e168392a24bde93756705132adef115..41f1561bb54510d5989180469742abf8b4e1178c 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -38,6 +38,7 @@ namespace elf { class InputSection; class Symbol; +struct PhdrEntry; // OHOS_LOCAL // If --reproduce is specified, all input files are written to this tar archive. extern std::unique_ptr tar; @@ -76,18 +77,23 @@ public: // Returns sections. It is a runtime error to call this function // on files that don't have the notion of sections. ArrayRef getSections() const { - assert(fileKind == ObjKind || fileKind == BinaryKind); + if (config->adlt) + assert(fileKind == SharedKind); + else + assert(fileKind == ObjKind || fileKind == BinaryKind); return sections; } // Returns object file symbols. It is a runtime error to call this // function on files of other types. ArrayRef getSymbols() const { - assert(fileKind == BinaryKind || fileKind == ObjKind || - fileKind == BitcodeKind); + if (config->adlt) + assert(fileKind == SharedKind); + else + assert(fileKind == BinaryKind || fileKind == ObjKind || + fileKind == BitcodeKind); return symbols; } - // Get filename to use for linker script processing. StringRef getNameForScript() const; @@ -161,6 +167,7 @@ private: class ELFFileBase : public InputFile { public: ELFFileBase(Kind k, MemoryBufferRef m); + virtual ~ELFFileBase() {} static bool classof(const InputFile *f) { return f->isElf(); } template llvm::object::ELFFile getObj() const { @@ -169,7 +176,7 @@ public: StringRef getStringTable() const { return stringTable; } - ArrayRef getLocalSymbols() { + virtual ArrayRef getLocalSymbols() { if (symbols.empty()) return {}; return llvm::makeArrayRef(symbols).slice(1, firstGlobal - 1); @@ -194,6 +201,11 @@ public: return getELFSyms().slice(firstGlobal); } + // OHOS_LOCAL begin + virtual void buildSymbolsHist(); + virtual bool isValidSection(InputSectionBase *s) const; + // OHOS_LOCAL end + protected: // Initializes this class's member variables. template void init(); @@ -224,8 +236,13 @@ public: ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) { this->archiveName = archiveName; } + ObjFile(Kind k, MemoryBufferRef m, StringRef archiveName) // OHOS_LOCAL + : ELFFileBase(k, m) { + this->archiveName = archiveName; + } + virtual ~ObjFile() {} - void parse(bool ignoreComdats = false); + virtual void parse(bool ignoreComdats = false); void parseLazy(); StringRef getShtGroupSignature(ArrayRef sections, @@ -247,6 +264,8 @@ public: llvm::Optional getDILineInfo(InputSectionBase *, uint64_t); llvm::Optional> getVariableLoc(StringRef name); + ArrayRef getShndxTable(); + // Name of source file obtained from STT_FILE symbol value, // or empty string if there is no such symbol in object file // symbol table. @@ -275,7 +294,17 @@ public: DWARFCache *getDwarf(); void initializeLocalSymbols(); - void postParse(); + virtual void postParse(); + + // OHOS_LOCAL begin + // TODO: move to SharedFileExtended + virtual StringRef getUniqueName(StringRef origName) const; + +protected: + // TODO: move to SharedFileExtended + llvm::DenseMap sectionsMap; // offset, orderIdx + llvm::DenseMap definedSymbolsMap; // abs offset, orderIdx + // OHOS_LOCAL end private: void initializeSections(bool ignoreComdats, @@ -364,6 +393,96 @@ private: const typename ELFT::Shdr *sec); }; + +// ADLT +template +class SharedFileExtended : public ObjFile { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + +public: + SharedFileExtended(MemoryBufferRef mb, StringRef soName); + + static bool classof(const InputFile *f) { + return f->kind() == InputFile::SharedKind; + } + void buildSymbolsHist() override; + bool isValidSection(InputSectionBase *s) const override; + bool isDynamicSection(InputSectionBase *s) const; + + void parse(bool ignoreComdats = false) override; + void postParse() override; + + Defined &getDefinedLocalSym(uint64_t offset); + + InputSectionBase &getSection(uint64_t offset); + InputSectionBase &getSectionByOrder(size_t idx); + InputSectionBase *findSection(uint64_t offset); + + template Symbol &getRelocTargetSym(const RelT &rel) { + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + return getSymbol(symIndex, false); + } + + Symbol &getDynamicSymbol(size_t symbolIndex) const; + Symbol &getLocalSymbol(size_t symbolIndex) const; + Symbol &getSymbol(size_t symbolIndex, bool fromDynamic); + + ArrayRef getLocalSymbols() override; + + +public: + // the input order of the file as it presented in ADLT image + size_t orderIdx = 0; + int dynSymSecIdx = 0; + int symTabSecIdx = 0; + int symTabShndxSecIdx = 0; + int symTabFirstGlobal = 0; + int gotPltSecIdx = 0; + + // .symtab's start of local symbols owned by library + llvm::Optional sharedLocalSymbolIndex; + // .symtab's start of global symbols owned by library + llvm::Optional sharedGlobalSymbolIndex; + + // Output information data: + llvm::SetVector programHeaders; + + // From input .rela.dyn, .rela.plt: + llvm::SetVector + relaDynIndexes; // If not .relr.dyn exists, contains only Got/Abs/Tls + // relocs. Otherwise contains relative relocs also. + llvm::SetVector relaPltIndexes; // .got.plt relocs + + // SharedFile compability layer: + // This is actually a vector of Elf_Verdef pointers. + SmallVector verdefs; + // If the output file needs Elf_Verneed data structures for this file, this is + // a vector of Elf_Vernaux version identifiers that map onto the entries in + // Verdefs, otherwise it is empty. + SmallVector vernauxs; + static unsigned vernauxNum; + SmallVector dtNeeded; + StringRef soName; + StringRef simpleSoName; + // Used for --as-needed + // bool isNeeded; + // Non-weak undefined symbols which are not yet resolved when the SO is + // parsed. Only filled for `--no-allow-shlib-undefined`. + SmallVector requiredSymbols; + + // TODO: add unique for output only + StringRef getUniqueName(StringRef origName) const override; + +private: + SmallVector localSymbols; + + void parseDynamics(); // SharedFile compability + void parseElfSymTab(); // ObjectFile compability + + std::vector parseVerneed(const llvm::object::ELFFile &obj, + const typename ELFT::Shdr *sec); +}; + class BinaryFile : public InputFile { public: explicit BinaryFile(MemoryBufferRef m) : InputFile(BinaryKind, m) {} @@ -374,6 +493,8 @@ public: ELFFileBase *createObjFile(MemoryBufferRef mb, StringRef archiveName = "", bool lazy = false); +ELFFileBase *createSharedFileExtended(MemoryBufferRef mb, StringRef soName = ""); + std::string replaceThinLTOSuffix(StringRef path); } // namespace elf diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 1420d8ce4e58ad9cfcc1b1689cf4cf717a62e53f..782127aece1c4ddfd29ef6148e6904f219fdcdfd 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -348,7 +348,9 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { for (const RelTy &rel : rels) { RelType type = rel.getType(config->isMips64EL); const ObjFile *file = getFile(); - Symbol &sym = file->getRelocTargetSym(rel); + Symbol &sym = config->adlt + ? getSoExt()->getRelocTargetSym(rel) + : file->getRelocTargetSym(rel); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -863,7 +865,18 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend += target.getImplicitAddend(bufLoc, type); - Symbol &sym = getFile()->getRelocTargetSym(rel); + Symbol &sym = config->adlt ? getSoExt()->getRelocTargetSym(rel) + : getFile()->getRelocTargetSym(rel); + if (config->adlt) { // TODO improve + switch (type) { + case R_AARCH64_RELATIVE: + case R_AARCH64_GLOB_DAT: + case R_AARCH64_JUMP_SLOT: + return; + default: + break; + } + } RelExpr expr = target.getRelExpr(type, sym, bufLoc); if (expr == R_NONE) continue; @@ -967,7 +980,8 @@ static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) { template void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { - if ((flags & SHF_EXECINSTR) && LLVM_UNLIKELY(getFile()->splitStack)) + if (!config->adlt && flags & SHF_EXECINSTR && + LLVM_UNLIKELY(getFile()->splitStack)) adjustSplitStackFunctionPrologues(buf, bufEnd); if (flags & SHF_ALLOC) { @@ -1004,6 +1018,8 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { if (auto *sec = dyn_cast(this)) secAddr += sec->outSecOff; const uint64_t addrLoc = secAddr + offset; + /*if (config->adlt && addrLoc == 68600) // debug hint + lld::outs() << "addrLoc 0x" << utohexstr(addrLoc) << "\n";*/ const uint64_t targetVA = SignExtend64(getRelocTargetVA(file, rel.type, rel.addend, addrLoc, *rel.sym, rel.expr), diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index d1b889750bbd485e85dc0a97841cda1d8473c9ab..1bcf8b4eca2053d6f808ee15c7eb08ec53a7f4e3 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Object/ELF.h" +#include "Adlt.h" namespace lld { namespace elf { @@ -28,6 +29,7 @@ class Defined; struct Partition; class SyntheticSection; template class ObjFile; +template class SharedFileExtended; class OutputSection; extern std::vector partitions; @@ -74,6 +76,9 @@ public: uint32_t type; uint32_t link; uint32_t info; + uint64_t address = 0; // store input sec addr for ADLT + uint64_t size = 0; // store input sec size for ADLT + OutputSection *getOutputSection(); const OutputSection *getOutputSection() const { @@ -133,6 +138,11 @@ public: return cast_or_null>(file); } + template + SharedFileExtended *getSoExt() const { + return adltCtx->getSoExt(file); + } + // Used by --optimize-bb-jumps and RISC-V linker relaxation temporarily to // indicate the number of bytes which is not counted in the size. This should // be reset to zero after uses. @@ -392,7 +402,7 @@ private: template void copyShtGroup(uint8_t *buf); }; -static_assert(sizeof(InputSection) <= 160, "InputSection is too big"); +static_assert(sizeof(InputSection) <= 180, "InputSection is too big"); inline bool isDebugSection(const InputSectionBase &sec) { return (sec.flags & llvm::ELF::SHF_ALLOC) == 0 && diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 51c505d159d53a811172e360a0a2065ea49a5c25..68729e4ebc4bfc88515e33cfd1f49e3a2a6fc1d2 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -104,7 +104,9 @@ static StringRef getOutputSectionName(const InputSectionBase *s) { {".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", ".gcc_except_table", ".init_array", ".fini_array", ".tbss", ".tdata", ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors", ".ohos.randomdata"}) // OHOS_LOCAL - if (isSectionPrefix(v, s->name)) + if (config->adlt && s->name.startswith(v)) + return s->name; + else if (isSectionPrefix(v, s->name)) return v; return s->name; diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index 893511929a3a50aa3b7e21a2b4821aa596be1e6d..5c1d109ef73b2dcaa2ace9eb95d184eedd143b03 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -55,7 +55,8 @@ static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma, // Returns a list of all symbols that we want to print out. static std::vector getSymbols() { std::vector v; - for (ELFFileBase *file : ctx->objectFiles) + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *b : file->getSymbols()) if (auto *dr = dyn_cast(b)) if (!dr->isSection() && dr->section && dr->section->isLive() && @@ -224,7 +225,8 @@ static void writeMapFile(raw_fd_ostream &os) { static void writeCref(raw_fd_ostream &os) { // Collect symbols and files. MapVector> map; - for (ELFFileBase *file : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) { for (Symbol *sym : file->getSymbols()) { if (isa(sym)) map[sym].insert(file); diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 12a23390e663b1defc3243f38876a5bdf7c0c1ad..f4fa5b90e2650800f51d0dda53bb5192c66b92ce 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -345,12 +345,14 @@ template void MarkLive::mark() { // to from __start_/__stop_ symbols because there will only be one set of // symbols for the whole program. template void MarkLive::moveToMain() { - for (ELFFileBase *file : ctx->objectFiles) - for (Symbol *s : file->getSymbols()) - if (auto *d = dyn_cast(s)) - if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && - d->section->isLive()) - markSymbol(s); + auto files = ctx->objectFiles; + if (!config->adlt) + for (ELFFileBase *file : files) + for (Symbol *s : file->getSymbols()) + if (auto *d = dyn_cast(s)) + if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && + d->section->isLive()) + markSymbol(s); for (InputSectionBase *sec : inputSections) { if (!sec->isLive() || !isValidCIdentifier(sec->name)) diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 4e6c20f5c7f6014f4f23ed17b0962212966989c6..8342d7be88d1227c58bfd179274f4d0f0cdb0c19 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -375,6 +375,10 @@ 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<"Enable ADLT trace logs">; + defm soname: Eq<"soname", "Set DT_SONAME">; defm sort_section: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index a617d55bfe000a08884d58b288f9e724111e6119..2a40434722d63d8cfcef060308bf272ca6f319f4 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -42,6 +42,7 @@ #include "Relocations.h" #include "Config.h" +#include "Adlt.h" #include "InputFiles.h" #include "LinkerScript.h" #include "OutputSections.h" @@ -100,7 +101,8 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, ErrorPlace errPlace = getErrorPlace(loc); std::string hint; if (rel.sym && !rel.sym->isSection()) - hint = "; references " + lld::toString(*rel.sym); + hint = "; references " + lld::toString(*rel.sym) + + (config->adlt ? ": raw-name: " + rel.sym->getName().str() + " " : ""); if (!errPlace.srcLoc.empty()) hint += "\n>>> referenced by " + errPlace.srcLoc; if (rel.sym && !rel.sym->isSection()) @@ -110,6 +112,11 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, hint += "; consider recompiling with -fdebug-types-section to reduce size " "of debug sections"; + if (config->adlt) { + auto offset = errPlace.isec->address + rel.offset; // debug hint: put bkpt here + hint += " [ADLT] Offset: 0x" + utohexstr(offset) + "\n"; + } + errorOrWarn(errPlace.loc + "relocation " + lld::toString(rel.type) + " out of range: " + v.str() + " is not in [" + Twine(min).str() + ", " + Twine(max).str() + "]" + hint); @@ -432,6 +439,47 @@ private: size_t i = 0; }; + +// OHOS_LOCAL begin +template class AdltRelocationScanner { +public: + AdltRelocationScanner(InputSectionBase &isec) + : file(adltCtx->getSoExt(isec.file)), + fromDynamic(file->isDynamicSection(&isec)), sec(isec) {} + + SharedFileExtended *getSoExt() { return file; } + + Symbol &getSymbol(unsigned idx) { return file->getSymbol(idx, fromDynamic); } + + void process(Relocation *r); + void trackGotPlt(Symbol *sym); + void trackRelatives(); + void trackDynamics(); + + bool toProcessAux = false; + +private: + SharedFileExtended *file = nullptr; + bool fromDynamic = false; + InputSectionBase &sec; +}; + +template +void AdltRelocationScanner::trackGotPlt(Symbol *sym) { + adltCtx->gotPltInfo[sym].push_back(file->orderIdx); +} + +template void AdltRelocationScanner::trackRelatives() { + auto count = mainPart->relaDyn->relocs.size(); + file->relaDynIndexes.insert(count - 1); +} + +template void AdltRelocationScanner::trackDynamics() { + auto count = mainPart->relaDyn->relocs.size(); + file->relaDynIndexes.insert(count - 1); +} +// OHOS_LOCAL end + // This class encapsulates states needed to scan relocations for one // InputSectionBase. class RelocationScanner { @@ -457,6 +505,7 @@ private: int64_t computeAddend(const RelTy &rel, RelExpr expr, bool isLocal) const; bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym, uint64_t relOff) const; + void processAux(Relocation &r); // OHOS_LOCAL void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) const; template void scanOne(RelTy *&i); @@ -1030,6 +1079,11 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, // sections. Given that it is ro, we will need an extra PT_LOAD. This // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. + +void RelocationScanner::processAux(Relocation &r) { // OHOS_LOCAL + processAux(r.expr, r.type, r.offset, *r.sym, r.addend); +} + void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) const { // If the relocation is known to be a link-time constant, we know no dynamic @@ -1301,10 +1355,132 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return 0; } +// OHOS_LOCAL begin +template +void AdltRelocationScanner::process(Relocation *r) { + /*if (r->offset == 0x21F) // debug hint + isDebug = true; + /*if (r->type == R_AARCH64_ABS64 && + r->sym->getName() == "__emutls_t.TLS_data1") + isDebug = true;*/ + + // parse offset (where) + InputSectionBase &secWhere = + (sec.type != SHT_NULL) ? sec : file->getSection(r->offset); + + // process offset + r->offset -= secWhere.address; + assert(r->type); + + // resolve relocs + switch (r->type) { + // dyn relocs + case R_AARCH64_RELATIVE: { + Defined *d = &file->getDefinedLocalSym(r->addend); + assert(d && "R_AARCH64_RELATIVE: r->sym not found by addend!"); + r->sym = d; + r->addend -= d->section->address + d->value; + addRelativeReloc(secWhere, r->offset, *r->sym, r->addend, r->expr, + r->type); + trackRelatives(); + return; + } + case R_AARCH64_GLOB_DAT: + assert(r->sym->exportDynamic); + if (!r->sym->needsGot) + r->sym->needsGot = 1; + trackGotPlt(r->sym); + return; + case R_AARCH64_JUMP_SLOT: + assert(r->sym->exportDynamic); + if (r->sym->isUndefined() && !r->sym->needsPlt) + r->sym->needsPlt = 1; + trackGotPlt(r->sym); + return; + // abs relocs + case R_AARCH64_ABS32: + sec.relocations.push_back(*r); + return; + case R_AARCH64_ABS64: + if (fromDynamic) { + assert(r->sym->exportDynamic); + sec.getPartition().relaDyn->addSymbolReloc(r->type, secWhere, + r->offset, *r->sym, r->addend, + r->type); + trackDynamics(); + return; + } + sec.relocations.push_back(*r); + return; + 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: + toProcessAux = true; + return; + // plt relocs + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_CONDBR19: + case R_AARCH64_TSTBR14: + if (r->sym->isDefined()) + r->expr = R_PC; // prev: R_PLT_PC + sec.relocations.push_back(*r); + return; + // got relocs + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_ADR_PREL_PG_HI21: + sec.relocations.push_back(*r); // TODO: optimize GOT + return; + case R_AARCH64_ADR_GOT_PAGE: + if (r->sym->isDefined() && !r->sym->needsGot) { + // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || R_GOT || R_GOT_PC + r->expr = R_PC; + sec.relocations.push_back(*r); + return; + } + LLVM_FALLTHROUGH; + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_LD64_GOTPAGE_LO15: + toProcessAux = true; + return; + // tls relocs + case R_AARCH64_TLSDESC: + if (fromDynamic && !r->sym->needsTlsDesc) + r->sym->needsTlsDesc = 1; + trackGotPlt(r->sym); + return; + case R_AARCH64_TLSDESC_CALL: + case R_AARCH64_TLS_TPREL64: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSDESC_ADR_PAGE21: + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + handleTlsRelocation(r->type, *r->sym, sec, r->offset, r->addend, r->expr); + return; + default: + fatal("[ADLT] Unhandled " + toString(fromDynamic ? "dynamic " : "") + + "reloc: " + toString(r->type)); + break; + } +} +// ADLT END + template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; + std::unique_ptr> adltScanner = nullptr; + if (config->adlt) + adltScanner = std::make_unique>(sec); uint32_t symIndex = rel.getSymbol(config->isMips64EL); - Symbol &sym = sec.getFile()->getSymbol(symIndex); + Symbol &sym = config->adlt + ? adltScanner->getSymbol(symIndex) + : sec.getFile()->getSymbol(symIndex); RelType type; // Deal with MIPS oddity. @@ -1322,7 +1498,7 @@ template void RelocationScanner::scanOne(RelTy *&i) { // Error if the target symbol is undefined. Symbol index 0 may be used by // marker relocations, e.g. R_*_NONE and R_ARM_V4BX. Don't error on them. - if (sym.isUndefined() && symIndex != 0 && + if (symIndex != 0 && sym.isUndefined() && maybeReportUndefined(cast(sym), sec, offset)) return; @@ -1336,6 +1512,14 @@ template void RelocationScanner::scanOne(RelTy *&i) { // Read an addend. int64_t addend = computeAddend(rel, expr, sym.isLocal()); + if (config->adlt) { + Relocation r = {expr, type, offset, addend, &sym}; + adltScanner->process(&r); + if (adltScanner->toProcessAux) + processAux(r); + return; + } + if (config->emachine == EM_PPC64) { // We can separate the small code model relocations into 2 categories: // 1) Those that access the compiler generated .toc sections. @@ -1634,18 +1818,45 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { return true; } +// OHOS_LOCAL begin +namespace lld { +namespace elf { +namespace adlt { +template static void addGotPltIndex(Symbol *s, bool isPlt) { + auto &vec = adltCtx->gotPltInfo[s]; + for (auto &orderId : vec) { + auto *soFile = adltCtx->getSoExt(orderId); + auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; + auto &output = isPlt ? soFile->relaPltIndexes : soFile->relaDynIndexes; + auto index = entries.size() - 1; + output.insert(index); + } +} +} // namespace adlt +} // namespace elf +} // namespace lld + +// OHOS_LOCAL end + void elf::postScanRelocations() { auto fn = [](Symbol &sym) { if (handleNonPreemptibleIfunc(sym)) return; if (!sym.needsDynReloc()) return; - sym.allocateAux(); + if (!sym.allocateAux()) + return; - if (sym.needsGot) + if (sym.needsGot) { addGotEntry(sym); - if (sym.needsPlt) + if (config->adlt) + invokeELFT(adlt::addGotPltIndex, &sym, false); + } + if (sym.needsPlt) { addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym); + if (config->adlt) + invokeELFT(adlt::addGotPltIndex, &sym, true); + } if (sym.needsCopy) { if (sym.isObject()) { invokeELFT(addCopyRelSymbol, cast(sym)); @@ -1679,6 +1890,8 @@ void elf::postScanRelocations() { mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible( target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym, target->tlsDescRel); + if (config->adlt) + invokeELFT(adlt::addGotPltIndex, &sym, false); } if (sym.needsTlsGd) { in.got->addDynTlsEntry(sym); @@ -1732,7 +1945,8 @@ void elf::postScanRelocations() { // Local symbols may need the aforementioned non-preemptible ifunc and GOT // handling. They don't need regular PLT. - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? adltCtx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) fn(*sym); } @@ -2180,7 +2394,6 @@ bool ThunkCreator::createThunks(uint32_t pass, // original target so another Thunk can be generated. if (pass > 0 && normalizeExistingThunk(rel, src)) continue; - if (!target->needsThunk(rel.expr, rel.type, isec->file, src, *rel.sym, rel.addend)) continue; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 657c19a00ba364cf3bd429141fe53d097f3decc2..d65ebd486dd24632333cd9b9a7acc5ce6da07d4d 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -307,10 +307,12 @@ public: return needsCopy || needsGot || needsPlt || needsTlsDesc || needsTlsGd || needsTlsGdToIe || needsGotDtprel || needsTlsIe; } - void allocateAux() { - assert(auxIdx == uint32_t(-1)); + bool allocateAux() { + if (auxIdx != uint32_t(-1)) + return false; auxIdx = symAux.size(); symAux.emplace_back(); + return true; } bool isSection() const { return type == llvm::ELF::STT_SECTION; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f298b83bda0e4f00b253c28a201d7a1b69a759a0..491a61dd15da04be1d3469dd45c4c24416b19e33 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -15,6 +15,7 @@ #include "SyntheticSections.h" #include "Config.h" +#include "Adlt.h" #include "DWARF.h" #include "EhFrame.h" #include "InputFiles.h" @@ -1397,9 +1398,22 @@ DynamicSection::computeContents() { addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH, part.dynStrTab->addString(config->rpath)); - for (SharedFile *file : ctx->sharedFiles) - if (file->isNeeded) - addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); + if (config->adlt) { + for (InputFile *file : adltCtx->sharedFilesExtended) { + auto *soExt = adltCtx->getSoExt(file); + for (size_t i = 0; i < soExt->dtNeeded.size(); i++) { + auto tag = DT_NEEDED; + auto val = part.dynStrTab->addString(soExt->dtNeeded[i]); + if (llvm::find(entries, std::pair{tag, val}) == + entries.end()) + addInt(tag, val); + } + } + addInt(DT_SONAME, part.dynStrTab->addString(config->outputFile)); + } else + for (SharedFile *file : ctx->sharedFiles) + if (file->isNeeded) + addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); if (isMain) { if (!config->soName.empty()) @@ -1518,7 +1532,8 @@ DynamicSection::computeContents() { } if (config->emachine == EM_AARCH64) { - if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) + if (!config->adlt && + config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) addInt(DT_AARCH64_BTI_PLT, 0); if (config->zPacPlt) addInt(DT_AARCH64_PAC_PLT, 0); @@ -2207,6 +2222,11 @@ void SymbolTableBaseSection::sortSymTabSymbols() { size_t numLocals = e - symbols.begin(); getParent()->info = numLocals + 1; + if (config->adlt && this->type == SHT_SYMTAB) { + invokeELFT(sortSymTabSymbolsInAdlt, numLocals); + return; + } + // We want to group the local symbols by file. For that we rebuild the local // part of the symbols vector. We do not need to care about the STT_FILE // symbols, they are already naturally placed first in each group. That @@ -2222,6 +2242,50 @@ void SymbolTableBaseSection::sortSymTabSymbols() { *i++ = entry; } +template +void SymbolTableBaseSection::sortSymTabSymbolsInAdlt(size_t numLocals) { + auto localEnd = symbols.begin() + numLocals; + + using SortKey = std::tuple; + auto makeKey = [](const SymbolTableEntry& ent) -> SortKey { + const InputFile* file = ent.sym->file; + if(auto* soext = dyn_cast_or_null>(file)) { + return {static_cast(soext->orderIdx), file}; + } + return {-1, file}; + }; + + for (InputFile* file : adltCtx->sharedFilesExtended) { + auto* soext = cast>(file); + soext->sharedLocalSymbolIndex = llvm::None; + soext->sharedGlobalSymbolIndex = llvm::None; + } + + // sort local symbols + llvm::stable_sort(llvm::make_range(symbols.begin(), localEnd), + [makeKey](const SymbolTableEntry& lhs, const SymbolTableEntry& rhs) { + return makeKey(lhs) <= makeKey(rhs); + }); + + // sort global symbols + llvm::stable_sort(llvm::make_range(localEnd, symbols.end()), + [makeKey](const SymbolTableEntry& lhs, const SymbolTableEntry& rhs) { + return makeKey(lhs) <= makeKey(rhs); + }); + + // extract file boundaries for local symbols + for (auto iter = symbols.begin(); iter != localEnd; ++iter) + if (auto* soext = dyn_cast_or_null>(iter->sym->file)) + if (!soext->sharedLocalSymbolIndex) + soext->sharedLocalSymbolIndex = std::distance(symbols.begin(), iter); + + // extract file boundaries for global symbols + for (auto iter = localEnd; iter != symbols.end(); ++iter) + if (auto* soext = dyn_cast_or_null>(iter->sym->file)) + if (!soext->sharedGlobalSymbolIndex) + soext->sharedGlobalSymbolIndex = std::distance(symbols.begin(), iter); +} + void SymbolTableBaseSection::addSymbol(Symbol *b) { // Adding a local symbol to a .dynsym is a bug. assert(this->type != SHT_DYNSYM || !b->isLocal()); @@ -3410,7 +3474,8 @@ template void elf::splitSections() { llvm::TimeTraceScope timeScope("Split sections"); // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - parallelForEach(ctx->objectFiles, [](ELFFileBase *file) { + auto files = ctx->objectFiles; + parallelForEach(files, [](ELFFileBase *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) continue; @@ -3912,6 +3977,8 @@ void InStruct::reset() { strTab.reset(); symTab.reset(); symTabShndx.reset(); + adltData.reset(); + adltStrTab.reset(); } constexpr char kMemtagAndroidNoteName[] = "Android"; @@ -3958,6 +4025,450 @@ size_t PackageMetadataNote::getSize() const { alignTo(config->packageMetadata.size() + 1, 4); } + +// OHOS_LOCAL begin +namespace lld { namespace elf { namespace adlt { + +static_assert( + sizeof(adlt_semver_t) == sizeof(Elf64_Half), + ".adlt semantic version is designed to occupy uint16_t" +); + +static_assert( + sizeof(adlt_dt_needed_index_t) == sizeof(Elf64_Off), + "adlt_dt_needed_index_t have to be an offset with intrused flags" +); + +static_assert( + sizeof(adlt_cross_section_ref_t) == 16, + "adlt_cross_section_ref_t size is 16 bytes" +); + +static_assert( + sizeof(adlt_cross_section_array_t) == 24, + "adlt_cross_section_ref_t size is 24 bytes" +); + +static_assert( + sizeof(adlt_hash_type_t) == sizeof(Elf64_Byte), + "String hash type enum should occupy only one byte" +); + +static_assert( + sizeof(adlt_blob_array_t) == 16, + "blob array reference occupies 16 bytes in PSOD" +); + +static_assert(sizeof(adltBlobStartMark) == 4, + "0xad17 consist of 4 bytes" +); + +static_assert(sizeof(adlt_section_header_t) == 56, + "please update version if header has been changed" +); + +static_assert(sizeof(adlt_psod_t) == 160, + "please udpate version if adlt_psod_t layout or content changed" +); + + +template +AdltSection::AdltSection(StringTableSection& strTabSec) + : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") + , strTabSec(strTabSec) +{ + assert(config->adlt); +} + +template +void AdltSection::finalizeContents() { + soInputs.clear(); + soInputs.reserve(adltCtx->sharedFilesExtended.size()); + for (InputFile* file : adltCtx->sharedFilesExtended) { + auto* soext = cast>(file); + soInputs.push_back(makeSoData(soext)); + } + + assert((soInputs.size() < 1<<16) && + "the number of input libs exeeds ELF limit on number of sections"); + const Elf64_Half soNum = soInputs.size(); + + common = makeCommonData(); + + std::memset(&header, 0, sizeof(header)); + header = adlt_section_header_t{ + adltSchemaVersion, // .schemaVersion + sizeof(adlt_section_header_t), // .schemaHeaderSize + sizeof(adlt_psod_t), // .schemaPSODSize + soNum, // .sharedObjectsNum + ADLT_HASH_TYPE_GNU_HASH, // .stringHashType + getBlobStartOffset(), // .blobStart + estimateBlobSize(), // .blobSize + 0, // .overallMappedSize, known on writeTo + adlt_blob_u16_array_t{}, // .phIndexes, filled in writeTo + }; + + buildSonameIndex(); + linkInternalDtNeeded(); + extractInitFiniArray(); +} + +template +void AdltSection::buildSonameIndex() { + for (const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + auto res = sonameToIndexMap.try_emplace( + CachedHashStringRef(soData.soName.ref), it.index()); + if (!res.second) { + warn(Twine(".adlt-section: duplicated soname: ") + soData.soName.ref + + " at pos=" + Twine(it.index()) + + " collided with pos=" + Twine(res.first->second)); + } + } +} + +template +void AdltSection::linkInternalDtNeeded() { + for (auto it : llvm::enumerate(soInputs)) { + auto& soData = it.value(); + for (auto& needed : soData.dtNeededs) { + auto cref = CachedHashStringRef(needed.str.ref); + auto res = sonameToIndexMap.find(cref); + if (res != sonameToIndexMap.end()) { + needed.psodIndex = res->second; + } + } + } +} + +template +OutputSection* AdltSection::findOutSection(StringRef name) { + if (name.empty()) return nullptr; + const unsigned partition = 1; + + for (SectionCommand* cmd : script->sectionCommands) { + if (auto* osd = dyn_cast(cmd)) + if (osd->osec.name == name && osd->osec.partition == partition) + return &osd->osec; + } + return nullptr; +} + +template +void AdltSection::extractInitFiniArray() { + for (auto& soData : soInputs) { + auto initArrayName = soData.initArrayName; + auto finiArrayName = soData.finiArrayName; + soData.initArraySec = findOutSection(initArrayName); + soData.finiArraySec = findOutSection(finiArrayName); + } +} + +template +size_t AdltSection::estimateOverallMappedSize() { + size_t totalMemsz = 0; + for (PhdrEntry* ph : mainPart->phdrs) + if (ph->p_type == PT_LOAD) + totalMemsz += ph->p_memsz; + return totalMemsz; +} + +template +typename AdltSection::CommonData +AdltSection::makeCommonData() { + return CommonData { + UINT32_MAX, // .symtabSecIndex, filled in writeTo + adltCtx->commonProgramHeaders.size(), // .programHeadersAllocated + {}, // .phIndexes filled in writeTo + }; +} + +template +typename AdltSection::SoData +AdltSection::makeSoData(const SharedFileExtended* soext) { + assert(soext); + SoData data = {}; + StringRef soname = soext->soName; + data.soName = SectionString{soname, strTabSec.addString(soname)}; + + for (const auto& neededName: soext->dtNeeded) { + data.dtNeededs.push_back({ + SectionString{neededName, strTabSec.addString(neededName)}, + {}, // unknown now, filled by linkInternalDtNeeded + }); + } + + data.initArrayName = soext->getUniqueName(".init_array"); + data.finiArrayName = soext->getUniqueName(".fini_array"); + + data.relaDynIndx = soext->relaDynIndexes.getArrayRef(); + data.relaPltIndx = soext->relaPltIndexes.getArrayRef(); + + data.programHeadersAllocated = soext->programHeaders.size(); + data.programHeaders = soext->programHeaders.getArrayRef(); + + return data; +} + +template +Elf64_Xword AdltSection::calculateHash(StringRef str) const { + switch(static_cast(header.stringHashType)) { + case ADLT_HASH_TYPE_NONE: + return 0x0; + case ADLT_HASH_TYPE_GNU_HASH: + return hashGnu(str); + case ADLT_HASH_TYPE_SYSV_HASH: + return hashSysV(str); + case ADLT_HASH_TYPE_DEBUG_CONST: + return 0xdeadbeef1337c0de; + default: + llvm_unreachable(".adlt hash type not implemented"); + } +} + +template +adlt_psod_t AdltSection::serialize(const SoData& soData) const { + return adlt_psod_t { + soData.soName.strtabOff, // .soName + calculateHash(soData.soName.ref), // .soNameHash + soData.initArraySec ? adlt_cross_section_array_t{ // .initArray + soData.initArraySec->sectionIndex, + 0x0, // .init_array function addresses are located at the start + soData.initArraySec->size, // size + } : adlt_cross_section_array_t{}, + soData.finiArraySec ? adlt_cross_section_array_t{ // .finiArray + soData.finiArraySec->sectionIndex, + 0x0, // .fini_array function addresses are located at the start + soData.finiArraySec->size, // size + } : adlt_cross_section_array_t{}, + adlt_blob_array_t {}, // .dtNeeded, filled in writeTo + adlt_cross_section_ref_t { + soData.sharedLocalIndex ? common.symtabSecIndex : UINT32_MAX, + soData.sharedLocalIndex.value_or(0), + }, // .sharedLocalSymbolIndex + adlt_cross_section_ref_t { + soData.sharedGlobalIndex ? common.symtabSecIndex : UINT32_MAX, + soData.sharedGlobalIndex.value_or(0), + }, // .sharedGlobalSymbolIndex + adlt_blob_u16_array_t {}, // .phIndexes, filled in writeTo + adlt_blob_u32_array_t {}, // .relaDynIndx, filled in writeTo + adlt_blob_u32_array_t {}, // .relaPltIndx, filled in writeTo + }; +} + +template +Elf64_Off AdltSection::getBlobStartOffset() const { + return sizeof(adlt_section_header_t) + sizeof(adlt_psod_t) * soInputs.size(); +} + +template +size_t AdltSection::estimateBlobSize() const { + size_t blobSize = sizeof(adltBlobStartMark); + + blobSize += sizeof(uint16_t) * common.programHeadersAllocated; + + for (const auto& soData: soInputs) { + blobSize += sizeof(adlt_dt_needed_index_t) * soData.dtNeededs.size(); + blobSize += sizeof(uint16_t) * soData.programHeadersAllocated; + blobSize += sizeof(uint32_t) * soData.relaDynIndx.size(); + blobSize += sizeof(uint32_t) * soData.relaPltIndx.size(); + }; + + return blobSize; +} + +template +template +adlt_blob_array_t AdltSection::writeArray( + uint8_t* buff, size_t offset, const SmallVector& data) { + if (data.empty()) return {0x0, 0}; + + const size_t to_write = data.size_in_bytes(); + memcpy(buff + offset, data.data(), to_write); + + return {offset, to_write}; +} + +template +template +adlt_blob_array_t AdltSection::writeArray( + uint8_t* buff, size_t offset, const ArrayRef& data) { + if (data.empty()) return {0x0, 0}; + + const size_t to_write = data.size() * sizeof(T); + memcpy(buff + offset, data.data(), to_write); + + return {offset, to_write}; +} + + +template +adlt_blob_array_t AdltSection::writeDtNeeded( + uint8_t* buff, size_t offset, const DtNeededsVec& neededVec) { + if (neededVec.empty()) return {0x0, 0}; + + SmallVector needIndexes; + needIndexes.reserve(neededVec.size()); + for (const auto& need_data : neededVec) { + needIndexes.push_back(adlt_dt_needed_index_t{ + need_data.psodIndex.has_value(), // .hasInternalPSOD + need_data.psodIndex.value_or(0), // .PSODindex + need_data.str.strtabOff, // .sonameOffset + }); + } + + return writeArray(buff, offset, needIndexes); +} + +template +void AdltSection::extractProgramHeaderIndexes() { + phdrsIndexes.clear(); + for (const auto& it : llvm::enumerate(mainPart->phdrs)) { + phdrsIndexes[it.value()] = static_cast(it.index()); + }; + + for (const PhdrEntry* phentry : adltCtx->commonProgramHeaders) { + auto it = phdrsIndexes.find(phentry); + if (it != phdrsIndexes.end()) { + common.phIndexes.push_back(it->second); + } + } + + assert(common.phIndexes.size() <= common.programHeadersAllocated); + if (common.phIndexes.size() != common.programHeadersAllocated) { + warn(Twine(".adlt section: overallocated common ph-indexes") + + " allocated=" + Twine(common.programHeadersAllocated) + + " actual=" + Twine(common.phIndexes.size()) + ); + } +} + +template +void AdltSection::finalizeOnWrite() { + // require optimizing Writer::removeEmptyPTLoad been called + extractProgramHeaderIndexes(); + // require Writer::setPhdrs previously been called + header.overallMappedSize = estimateOverallMappedSize(); + + if (OutputSection* osec = findOutSection(".symtab")) { + common.symtabSecIndex = osec->sectionIndex; + } + + for (auto& it: llvm::enumerate(soInputs)) { + finalizeOnWrite(it.index(), it.value()); + } +} + +template +void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { + auto* soext = cast>(adltCtx->sharedFilesExtended[idx]); + + // require SymbolTableBaseSection::sortSymTabSymbolsInAdlt for .symtab called + soData.sharedLocalIndex = soext->sharedLocalSymbolIndex; + soData.sharedGlobalIndex = soext->sharedGlobalSymbolIndex; + + // phIndexes may shift if called before Writer::removeEmptyPTLoad + soData.phIndexes.clear(); + for (const PhdrEntry* phentry : soData.programHeaders) { + auto it = phdrsIndexes.find(phentry); + if (it != phdrsIndexes.end()) { + soData.phIndexes.push_back(it->second); + } + } + + assert(soData.phIndexes.size() <= soData.programHeadersAllocated); + if (soData.phIndexes.size() != soData.programHeadersAllocated) { + warn(Twine(".adlt section: overallocated ph-indexes for psod-") + Twine(idx) + + " allocated=" + Twine(soData.programHeadersAllocated) + + " actual=" + Twine(soData.phIndexes.size()) + ); + } +} + +template +void AdltSection::writeTo(uint8_t* buf) { + // TODO: take care of endianness, use write32 / write64 etc. + finalizeOnWrite(); + + // pre-serialized SoData, enriched with offsets during blob writing + SmallVector psods; + for (const auto& it: llvm::enumerate(soInputs)) { + const SoData& soData = it.value(); + psods.push_back(serialize(soData)); + } + + // serialize blob data + { + uint8_t* const blobBuf = buf + header.blobStart; + size_t blobOff = 0; + memcpy(blobBuf + blobOff, &adltBlobStartMark, sizeof(adltBlobStartMark)); + blobOff += sizeof(adltBlobStartMark); + + // common header-related data + { + header.phIndexes = writeArray(blobBuf, blobOff, common.phIndexes); + blobOff += header.phIndexes.size; + } + + // psod-related data + for(const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + auto& psod = psods[it.index()]; + + psod.dtNeeded = writeDtNeeded(blobBuf, blobOff, soData.dtNeededs); + blobOff += psod.dtNeeded.size; + + psod.phIndexes = writeArray(blobBuf, blobOff, soData.phIndexes); + blobOff += psod.phIndexes.size; + } + + // group up relaDyn and relaPlt idxs, it tends to be size-consuming + for(const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + auto& psod = psods[it.index()]; + + psod.relaDynIndx = writeArray(blobBuf, blobOff, soData.relaDynIndx); + blobOff += psod.relaDynIndx.size; + + psod.relaPltIndx = writeArray(blobBuf, blobOff, soData.relaPltIndx); + blobOff += psod.relaPltIndx.size; + } + + // finalize header.blobSize + assert((blobOff <= header.blobSize) && + ".adlt-section: blob output exeeds its initial estimation"); + header.blobSize = blobOff; + } + + // header + { + memcpy(buf, &header, sizeof(header)); + } + + // PSODs + { + uint8_t* const psods_buf = buf + sizeof(header); + size_t psods_off = 0; + for (const auto& it: llvm::enumerate(soInputs)) { + adlt_psod_t& psod = psods[it.index()]; + memcpy(psods_buf + psods_off, &psod, sizeof(adlt_psod_t)); + psods_off += sizeof(adlt_psod_t); + } + } +} + +template +size_t AdltSection::getSize() const { + assert(sizeof(adlt_section_header_t) + + sizeof(adlt_psod_t) * soInputs.size() + <= header.blobStart); + return header.blobStart + header.blobSize; +} + +}}} // namespace lld::elf::adlt +// OHOS_LOCAL end + + InStruct elf::in; std::vector elf::partitions; @@ -4046,3 +4557,8 @@ template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; + +template class elf::adlt::AdltSection; +template class elf::adlt::AdltSection; +template class elf::adlt::AdltSection; +template class elf::adlt::AdltSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 83a2bd7d34dfd0efd99cb12b442793d340dcfec8..b51c85ce2ea810c1eab4d880926a0b39dc16e9a6 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -25,6 +25,7 @@ #include "InputSection.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/BinaryFormat/ADLTSection.h" // OHOS_LOCAL #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Threading.h" @@ -34,6 +35,7 @@ namespace elf { class Defined; struct PhdrEntry; class SymbolTableBaseSection; +template class SharedFileExtended; class SyntheticSection : public InputSection { public: @@ -643,6 +645,7 @@ public: protected: void sortSymTabSymbols(); + template void sortSymTabSymbolsInAdlt(size_t numLocals); // A vector of symbols and their string table offsets. SmallVector symbols; @@ -1220,6 +1223,110 @@ public: size_t getSize() const override; }; + +namespace adlt { + +using namespace llvm::adlt; + +template +class AdltSection final : public SyntheticSection { +public: + struct SectionString { + StringRef ref; + Elf64_Off strtabOff; // offset in strTabSec + }; + + // will be serialized to adlt_dt_needed_index_t + struct DtNeededData { + SectionString str; + llvm::Optional psodIndex; + }; + + using SectionStringVector = SmallVector; + using DtNeededsVec = SmallVector; + + // will be serialized to adlt_psod_t + struct SoData { + SectionString soName; + DtNeededsVec dtNeededs; + + StringRef initArrayName; + StringRef finiArrayName; + + OutputSection* initArraySec; + OutputSection* finiArraySec; + + llvm::Optional sharedLocalIndex; + llvm::Optional sharedGlobalIndex; + + size_t programHeadersAllocated; + ArrayRef programHeaders; + SmallVector phIndexes; + + ArrayRef relaDynIndx; + ArrayRef relaPltIndx; + }; + + // will be used to form some header data + struct CommonData { + uint32_t symtabSecIndex = UINT32_MAX; + size_t programHeadersAllocated; + SmallVector phIndexes; + }; + +public: + AdltSection(StringTableSection& strTabSec); + + void writeTo(uint8_t* buf) override; + size_t getSize() const override; + void finalizeContents() override; + + Elf64_Off getBlobStartOffset() const; + +private: + static OutputSection* findOutSection(StringRef name); + + void buildSonameIndex(); + void linkInternalDtNeeded(); + void extractInitFiniArray(); + size_t estimateOverallMappedSize(); + void extractProgramHeaderIndexes(); + Elf64_Xword calculateHash(StringRef str) const; + + CommonData makeCommonData(); + SoData makeSoData(const SharedFileExtended*); + adlt_psod_t serialize(const SoData&) const; + size_t estimateBlobSize() const; + + void finalizeOnWrite(); + void finalizeOnWrite(size_t idx, SoData& sodata); + + template + adlt_blob_array_t writeArray(uint8_t* buff, size_t offset, + const SmallVector& data); + + template + adlt_blob_array_t writeArray(uint8_t* buff, size_t offset, + const ArrayRef& data); + + adlt_blob_array_t writeDtNeeded(uint8_t* buff, size_t offset, + const DtNeededsVec& neededVec); + +private: + StringTableSection& strTabSec; + + adlt_section_header_t header = {}; + + CommonData common = {}; + SmallVector soInputs; + + llvm::DenseMap sonameToIndexMap; + llvm::DenseMap phdrsIndexes; +}; + +} // namespace adlt + + InputSection *createInterpSection(); MergeInputSection *createCommentSection(); template void splitSections(); @@ -1295,6 +1402,8 @@ struct InStruct { std::unique_ptr strTab; std::unique_ptr symTab; std::unique_ptr symTabShndx; + std::unique_ptr adltData; + std::unique_ptr adltStrTab; void reset(); }; diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 27ef93e00b8b51f2a00c9f0848591d87b136410d..8e1a7d2665aa6ee904f4802f1bec07444ca0e4b3 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -88,6 +88,9 @@ public: virtual bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const; + virtual void deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const {}; // ADLT + virtual void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const = 0; void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e27e656d43c712b18ce1c8a63629382e589c840d..93fd33ccb2b9f1cf12d28e30dfa3d9165d0e3286 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -11,6 +11,7 @@ #include "ARMErrataFix.h" #include "CallGraphSort.h" #include "Config.h" +#include "Adlt.h" #include "InputFiles.h" #include "LinkerScript.h" #include "MapFile.h" @@ -116,6 +117,7 @@ static void removeEmptyPTLoad(SmallVector &phdrs) { for (OutputSection *sec : outputSections) if (removed.count(sec->ptLoad)) sec->ptLoad = nullptr; + phdrs.erase(it, phdrs.end()); } @@ -273,7 +275,9 @@ void elf::addReservedSymbols() { static OutputSection *findSection(StringRef name, unsigned partition = 1) { for (SectionCommand *cmd : script->sectionCommands) if (auto *osd = dyn_cast(cmd)) - if (osd->osec.name == name && osd->osec.partition == partition) + if ((config->adlt ? osd->osec.name.startswith(name) + : osd->osec.name == name) && + osd->osec.partition == partition) return &osd->osec; return nullptr; } @@ -310,6 +314,14 @@ template void elf::createSyntheticSections() { in.symTabShndx = std::make_unique(); } + if (config->adlt) { + assert(adltCtx && "ADLT: ctx not initialized!"); + in.adltStrTab = std::make_unique(".adlt.strtab", false); + in.adltData = std::make_unique>(*in.adltStrTab); + add(*in.adltStrTab); + add(*in.adltData); + } + in.bss = std::make_unique(".bss", 0, 1); add(*in.bss); @@ -516,7 +528,7 @@ template void elf::createSyntheticSections() { in.iplt = std::make_unique(); add(*in.iplt); - if (config->andFeatures) + if (!config->adlt && config->andFeatures) add(*make()); // .note.GNU-stack is always added when we are creating a re-linkable @@ -536,6 +548,168 @@ template void elf::createSyntheticSections() { add(*in.strTab); } +// OHOS_LOCAL begin +namespace { +static struct AdltWriter { + InputSection *getInputSection(OutputSection *sec); + StringRef phdrTypeToStr(uint32_t p_type); + + template void checkPhdrs(); + template void checkRelocs(); + + template void trackPhdr(OutputSection *sec, PhdrEntry *phdr); + template void traceRelocs(); + template void tracePhdrs(); +} adltWriter; +} // namespace + +InputSection *AdltWriter::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(); +} + +template void AdltWriter::checkPhdrs() { + assert(!adltCtx->commonProgramHeaders.empty() && + "Common headers can't be empty!"); + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) + assert(!soFile->programHeaders.empty() && + "ADLT: PHdr indexes can't be empty!"); +} + +template void AdltWriter::checkRelocs() { + assert(!mainPart->relaDyn->relocs.empty() && "ADLT: relaDyn can't be empty!"); + assert(!in.relaPlt->relocs.empty() && "ADLT: relaPlt can't be empty!"); + + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) { + assert(!soFile->relaDynIndexes.empty() && + "ADLT: relaDyn indexes can't be empty!"); + assert(!soFile->relaPltIndexes.empty() && + "ADLT: relaPlt indexes can't be empty!"); + } +} + +template +void AdltWriter::trackPhdr(OutputSection *sec, PhdrEntry *phdr) { + auto *isec = getInputSection(sec); + if (isec && isec->file) { + isec->getSoExt()->programHeaders.insert(phdr); + return; + } + adltCtx->commonProgramHeaders.insert(phdr); +} + +template void AdltWriter::traceRelocs() { + lld::outs() << "[ADLT]\n"; + auto dynRelsSize = mainPart->relaDyn->relocs.size(); + lld::outs() << "Dyn relocs (" << dynRelsSize << ")\n"; + lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; + + auto printIndexes = [&](auto &vec) { + lld::outs() << ": "; + for (auto &it : vec) + lld::outs() << it << ' '; + lld::outs() << "\n"; + }; + + auto printSym = [&](Symbol *sym) { + if (sym->getName().empty() && sym->isSection()) { + Defined *d = cast(sym); + return d->section->name; + } + return sym->getName(); + }; + + auto printRelaTable = [&](auto *relSec, auto &outIndexes) { + 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" << printSym(rel->sym) + << " + 0x" << utohexstr(rel->addend) << '\n'; + }; + + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) { + lld::outs() << soFile->soName << ":\n"; + lld::outs() << ".rela.dyn relocs (" << soFile->relaDynIndexes.size() << ")"; + printIndexes(soFile->relaDynIndexes); + printRelaTable(mainPart->relaDyn.get(), soFile->relaDynIndexes); + + lld::outs() << ".rela.plt relocs (" << soFile->relaPltIndexes.size() << ")"; + printIndexes(soFile->relaPltIndexes); + printRelaTable(in.relaPlt.get(), soFile->relaPltIndexes); + } +} + +template void AdltWriter::tracePhdrs() { + lld::outs() << "[ADLT]\n"; + lld::outs() << "Program Headers (" << mainPart->phdrs.size() << ")\n"; + + llvm::DenseMap phIndexMap; + for (auto &it : llvm::enumerate(mainPart->phdrs)) + phIndexMap[it.value()] = it.index(); + + + auto printIndexes = [&](auto &vec) { + lld::outs() << ": "; + for (auto &it : vec) + lld::outs() << phIndexMap[it] << ' '; + lld::outs() << "\n"; + }; + + auto printPhTable = [&](auto &vec) { + lld::outs() << "Idx\tType\tOffset\tVirtAddr\tAlign\tFirstSec\n"; + for (const PhdrEntry *p : vec) + lld::outs() << phIndexMap[p] << ":\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'; + }; + + auto &common = adltCtx->commonProgramHeaders; + lld::outs() << "Common Program Headers (" << common.size() << ")"; + printIndexes(common); + printPhTable(common); + + for (auto *file : adltCtx->sharedFilesExtended) + if (auto *soFile = adltCtx->getSoExt(file)) { + auto &headers = soFile->programHeaders; + lld::outs() << soFile->soName << "\n"; + lld::outs() << "Program headers (" << headers.size() << ")"; + printIndexes(headers); + printPhTable(headers); + } +} + +StringRef AdltWriter::phdrTypeToStr(uint32_t p_type) { + switch (p_type) { + case PT_PHDR: + return "PT_PHDR"; + case PT_ADLT: + return "PT_ADLT"; + case PT_LOAD: + return "PT_LOAD"; + case PT_TLS: + return "PT_TLS"; + case PT_DYNAMIC: + return "PT_DYNAMIC"; + case PT_GNU_RELRO: + return "PT_GNU_RELRO"; + case PT_GNU_STACK: + return "PT_GNU_STACK"; + case PT_NOTE: + return "PT_NOTE"; + } + llvm_unreachable("UNKNOWN TYPE"); + return ""; +} +// OHOS_LOCAL end + // The main function of the writer. template void Writer::run() { copyLocalSymbols(); @@ -628,7 +802,8 @@ template static void markUsedLocalSymbols() { // See MarkLive::resolveReloc(). if (config->gcSections) return; - for (ELFFileBase *file : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) { ObjFile *f = cast>(file); for (InputSectionBase *s : f->getSections()) { InputSection *isec = dyn_cast_or_null(s); @@ -699,7 +874,8 @@ template void Writer::copyLocalSymbols() { llvm::TimeTraceScope timeScope("Add local symbols"); if (config->copyRelocs && config->discard != DiscardPolicy::None) markUsedLocalSymbols(); - for (ELFFileBase *file : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) { for (Symbol *b : file->getLocalSymbols()) { assert(b->isLocal() && "should have been caught in initializeSymbols()"); auto *dr = dyn_cast(b); @@ -829,6 +1005,12 @@ static bool isRelroSection(const OutputSection *sec) { // ELF in spirit. But in reality many linker features depend on // magic section names. StringRef s = sec->name; + if (config->adlt) + return s.startswith(".data.rel.ro") || s.startswith(".bss.rel.ro") || + s.startswith(".ctors") || s.startswith(".dtors") || + s.startswith(".eh_frame") || s.startswith(".fini_array") || + s.startswith(".init_array") || s.startswith(".preinit_array"); + return s == ".data.rel.ro" || s == ".bss.rel.ro" || s == ".ctors" || s == ".dtors" || s == ".jcr" || s == ".eh_frame" || s == ".fini_array" || s == ".init_array" || @@ -1011,9 +1193,25 @@ void PhdrEntry::add(OutputSection *sec) { lastSec = sec; if (!firstSec) firstSec = sec; + p_align = std::max(p_align, sec->alignment); + if (p_type == PT_LOAD) sec->ptLoad = this; + + // OHOS_LOCAL begin + if (config->adlt) { + if (adltCtx->withCfi && p_type == PT_LOAD) { + // check cfi.h: LIBRARY_ALIGNMENT and _BITS + constexpr uint32_t kCFILibraryAlignment = 1UL << 18; + firstSec->alignment = kCFILibraryAlignment; + p_align = kCFILibraryAlignment; + } + + if (p_type == PT_LOAD || p_type == PT_TLS) + invokeELFT(adltWriter.trackPhdr, sec, this); + } + // OHOS_LOCAL end } // The beginning and the ending of .rel[a].plt section are marked @@ -1303,7 +1501,8 @@ static DenseMap buildSectionOrder() { for (Symbol *sym : symtab->symbols()) addSym(*sym); - for (ELFFileBase *file : ctx->objectFiles) + auto files = ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) addSym(*sym); @@ -1719,7 +1918,8 @@ template void Writer::finalizeAddressDependentContent() { // block sections, input sections can shrink when the jump instructions at // the end of the section are relaxed. static void fixSymbolsAfterShrinking() { - for (InputFile *File : ctx->objectFiles) { + auto files = ctx->objectFiles; + for (InputFile *File : files) { parallelForEach(File->getSymbols(), [&](Symbol *Sym) { auto *def = dyn_cast(Sym); if (!def) @@ -1847,6 +2047,7 @@ static void removeUnusedSyntheticSections() { }); } + // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { Out::preinitArray = findSection(".preinit_array"); @@ -1937,9 +2138,29 @@ template void Writer::finalizeSections() { // determine if it needs special treatment, such as creating GOT, PLT, // copy relocations, etc. Note that relocations for non-alloc sections are // directly processed by InputSection::relocateNonAlloc. - for (InputSectionBase *sec : inputSections) - if (sec->isLive() && isa(sec) && (sec->flags & SHF_ALLOC)) - scanRelocations(*sec); + if (config->adlt) + for (auto &it : llvm::enumerate(adltCtx->sharedFilesExtended)) { + auto *soFile = cast>(it.value()); + auto sections = soFile->getSections(); + // scan .rela.dyn (base: SHT_NULL) + scanRelocations(*sections[0]); + // scan .rela.plt (base: .got.plt) + scanRelocations(*sections[soFile->gotPltSecIdx]); + // scan other sections + // excluding .rela.plt and .rela.dyn + auto gotPltIdx = static_cast(soFile->gotPltSecIdx); + auto isNotExcludedIdx = [&](auto idx) { + return idx != 0 && idx != gotPltIdx; + }; + for (auto &it : llvm::enumerate(soFile->getSections())) + if (InputSectionBase *sec = it.value()) + if (sec && sec->isLive() && isNotExcludedIdx(it.index())) + scanRelocations(*sec); + } + else + for (InputSectionBase *sec : inputSections) + if (sec->isLive() && isa(sec) && (sec->flags & SHF_ALLOC)) + scanRelocations(*sec); for (Partition &part : partitions) { for (EhInputSection *sec : part.ehFrame->sections) scanRelocations(*sec); @@ -1998,9 +2219,10 @@ template void Writer::finalizeSections() { if (sym->includeInDynsym()) { partitions[sym->partition - 1].dynSymTab->addSymbol(sym); - if (auto *file = dyn_cast_or_null(sym->file)) - if (file->isNeeded && !sym->isUndefined()) - addVerneed(sym); + if (!config->adlt) // ADLT support ver syms + if (auto *file = dyn_cast_or_null(sym->file)) + if (file->isNeeded && !sym->isUndefined()) + addVerneed(sym); } } @@ -2109,6 +2331,11 @@ template void Writer::finalizeSections() { finalizeSynthetic(in.ppc32Got2.get()); finalizeSynthetic(in.partIndex.get()); + if (config->adlt) { + finalizeSynthetic(in.adltData.get()); + finalizeSynthetic(in.adltStrTab.get()); + } + // Dynamic section must be the last one in this list and dynamic // symbol table section (dynSymTab) must be the first one. for (Partition &part : partitions) { @@ -2128,6 +2355,16 @@ template void Writer::finalizeSections() { finalizeSynthetic(part.verNeed.get()); finalizeSynthetic(part.dynamic.get()); } + // OHOS_LOCAL begin + if (config->adlt) { // check ouput entries and indexes + adltWriter.checkPhdrs(); + adltWriter.checkRelocs(); + if (config->adltTrace) { + adltWriter.tracePhdrs(); + adltWriter.traceRelocs(); + } + } + // OHOS_LOCAL end } if (!script->hasSectionsCommand && !config->relocatable) @@ -2291,12 +2528,22 @@ SmallVector Writer::createPhdrs(Partition &part) { return ret.back(); }; + // OHOS_LOCAL begin + auto getOwnerFileIdx = [](OutputSection* sec) -> llvm::Optional { + auto file = adltWriter.getInputSection(sec)->file; + if (!file) + return llvm::None; + return adltCtx->getSoExt(file)->orderIdx; + }; + // OHOS_LOCAL end + unsigned partNo = part.getNumber(); bool isMain = partNo == 1; // Add the first PT_LOAD segment for regular output sections. uint64_t flags = computeFlags(PF_R); PhdrEntry *load = nullptr; + llvm::Optional lastOwnerIdx = llvm::None; // OHOS_LOCAL // nmagic or omagic output does not have PT_PHDR, PT_INTERP, or the readonly // PT_LOAD. @@ -2312,6 +2559,10 @@ SmallVector Writer::createPhdrs(Partition &part) { if (OutputSection *cmd = findSection(".interp", partNo)) addHdr(PT_INTERP, cmd->getPhdrFlags())->add(cmd); + // PT_ADLT info. + if (OutputSection *adlt = findSection(".adlt", partNo)) + addHdr(PT_ADLT, adlt->getPhdrFlags())->add(adlt); + // Add the headers. We will remove them if they don't fit. // In the other partitions the headers are ordinary sections, so they don't // need to be added here. @@ -2371,8 +2622,19 @@ SmallVector Writer::createPhdrs(Partition &part) { uint64_t newFlags = computeFlags(sec->getPhdrFlags()); bool sameLMARegion = load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion; + + // OHOS_LOCAL begin + // ALDT image sections have additional addribute: input file owner. + // The ownership contiguousity allows to map only related sections + // when processing program headers that + bool sameFileOwner = config->adlt && lastOwnerIdx == getOwnerFileIdx(sec); + if (config->adlt) + lastOwnerIdx = getOwnerFileIdx(sec); + // OHOS_LOCAL end + if (!(load && newFlags == flags && sec != relroEnd && sec->memRegion == load->firstSec->memRegion && + (!config->adlt || sameFileOwner) && (sameLMARegion || load->lastSec == Out::programHeaders))) { load = addHdr(PT_LOAD, newFlags); flags = newFlags; @@ -2384,9 +2646,13 @@ SmallVector Writer::createPhdrs(Partition &part) { // Add a TLS segment if any. PhdrEntry *tlsHdr = make(PT_TLS, PF_R); for (OutputSection *sec : outputSections) - if (sec->partition == partNo && sec->flags & SHF_TLS) + if (sec->partition == partNo && sec->flags & SHF_TLS) { + // It making TLS hdr for each TLS section, for adlt. + if (config->adlt) + tlsHdr = addHdr(PT_TLS, PF_R); tlsHdr->add(sec); - if (tlsHdr->firstSec) + } + if (!config->adlt && tlsHdr->firstSec) ret.push_back(tlsHdr); // Add an entry for .dynamic. @@ -2474,6 +2740,9 @@ template void Writer::fixSectionAlignments() { OutputSection *cmd = p->firstSec; if (!cmd) return; + if (config->adlt &&cmd->name == ".text") { + lld::outs() << "Writer::fixSectionAlignments()\n"; + } cmd->alignExpr = [align = cmd->alignment]() { return align; }; if (!cmd->addrExpr) { // Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid @@ -2611,6 +2880,11 @@ template void Writer::assignFileOffsets() { if (config->zSeparate != SeparateSegmentKind::None && lastRX && lastRX->lastSec == sec) off = alignToPowerOf2(off, config->maxPageSize); + bool debug = false; + if (debug) + lld::outs() << "assignFileOffsets() Sec: " << sec->name + << " Off: " << std::to_string(off) + << " Offset: " << std::to_string(sec->offset) << '\n'; } for (OutputSection *osec : outputSections) if (!(osec->flags & SHF_ALLOC)) { diff --git a/llvm-build/build.py b/llvm-build/build.py index 11f19925a9dd61ce3a86fd0e70d55f09f70f39cc..d18201444e0e7875acc6e917323a4c13882c4ae5 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -289,6 +289,12 @@ class BuildConfig(): default=False, help='Enable lldb performance monitoring') + parser.add_argument( + '--adlt-debug-build', + action='store_true', + default=False, + help='Build adlt with debug flags') + compression_formats = ['bz2', 'gz'] parser.add_argument( @@ -304,12 +310,6 @@ class BuildConfig(): default=False, help='Append -g to build flags in build_libs') - parser.add_argument( - '--adlt-debug-build', - action='store_true', - default=False, - help='Build adlt with debug flags') - parser.add_argument( '--enable-check-abi', nargs='?', @@ -563,7 +563,9 @@ class BuildUtils(object): """subprocess.check_call with logging.""" self.logger().info('check_call:%s %s', datetime.datetime.now().strftime("%H:%M:%S"), subprocess.list2cmdline(cmd)) - + print("=======cmd: " + str(cmd) + "\n") + # print("=======args: " + args + "\n") + # print("=======kwargs: " + kwargs + "\n") subprocess.check_call(cmd, *args, **kwargs) @staticmethod @@ -2242,6 +2244,66 @@ class LlvmLibs(BuildUtils): os.path.join(llvm_install, 'include', 'gtest'), dirs_exist_ok = True) + def copy_gtest_to_sysroot(self, build_dir): + build_lib_dir = os.path.join(build_dir, 'lib') + self.logger().info('LlvmPackage copy_gtest_to_sysroot from %s', build_lib_dir) + libs = [ "libLLVMSupport.so", "libLLVMDemangle.so", "libllvm_gtest.so" ] + sysroot_lib_dir = self.merge_out_path('sysroot', 'aarch64-linux-ohos', 'usr', 'lib') + + os.chdir(build_lib_dir) + for f in libs: + self.check_copy_file(f'{f}.15', sysroot_lib_dir) + os.chdir(sysroot_lib_dir) + self.force_symlink(f'{f}.15', f) + os.chdir(build_lib_dir) + + def build_gtest_defines(self, llvm_install): + sysroot = self.merge_out_path('sysroot', 'aarch64-linux-ohos', 'usr') + common_flags = f'--target=aarch64-linux-ohos -B{sysroot}/lib -L{sysroot}/lib' + libcxx = self.merge_out_path('llvm-install', 'include', 'libcxx-ohos', 'include', 'c++', 'v1') + libc = os.path.join(sysroot, "include") + + gtest_defines = {} + gtest_defines['BUILD_SHARED_LIBS'] = 'YES' + gtest_defines['CMAKE_BUILD_TYPE'] = 'Release' + gtest_defines['CMAKE_C_COMPILER'] = os.path.join(llvm_install, 'bin', 'clang') + gtest_defines['CMAKE_CXX_COMPILER'] = os.path.join(llvm_install, 'bin', 'clang++') + gtest_defines['LLVM_TABLEGEN'] = os.path.join(llvm_install, 'bin', 'llvm-tblgen') + gtest_defines['CMAKE_LINKER'] = os.path.join(llvm_install, 'bin', 'ld.lld') + gtest_defines['CMAKE_EXE_LINKER_FLAGS'] = f'{common_flags}' + gtest_defines['CMAKE_C_FLAGS'] = f'{common_flags} -I{libc}' + gtest_defines['CMAKE_CXX_FLAGS'] = f'{common_flags} -I{libcxx} -I{libc}' + + return gtest_defines + + def build_gtest(self, compiler_path, llvm_install): + gtest_defines = self.build_gtest_defines(compiler_path) + gtest_cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm')) + + gtest_build_path = self.merge_out_path('gtest') + + self.rm_cmake_cache(gtest_build_path) + + self.invoke_cmake(gtest_cmake_path, + gtest_build_path, + gtest_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=gtest_build_path, + env=dict(self.build_config.ORIG_ENV), + target=[ "LLVMSupport", "LLVMDemangle", "llvm_gtest" ], + install=False) + + self.copy_gtest_to_sysroot(gtest_build_path) + shutil.copytree( + os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm', 'utils', 'unittest', 'googlemock', 'include', 'gmock'), + os.path.join(llvm_install, 'include', 'gmock'), + dirs_exist_ok = True) + shutil.copytree( + os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm', 'utils', 'unittest', 'googletest', 'include', 'gtest'), + os.path.join(llvm_install, 'include', 'gtest'), + dirs_exist_ok = True) + def build_libxml2_defines(self): libxml2_defines = {} libxml2_defines['LIBXML2_WITH_PYTHON'] = 'OFF' @@ -3156,6 +3218,37 @@ def main(): for (_, target) in configs: llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'runtimes', False, False) + if build_config.build_only: + if "musl" in build_config.build_only_libs: + # change compiller path to prebuilds in clang.gni file + clang_gni = os.path.join(build_config.REPOROOT_DIR, "build", "config", "clang", "clang.gni") + clang_gni_tmp = f"{clang_gni}_tmp" + shutil.move(clang_gni, clang_gni_tmp) + with open(clang_gni_tmp, 'r') as f1: + data = f1.read() + with open(clang_gni, 'w') as f2: + data = data.replace("//out/llvm-install", "${toolchains_dir}/${host_platform_dir}/" + f"clang-{build_config.CLANG_VERSION}") + f2.write(data) + # build musl + for (arch, target) in configs: + sysroot_composer.build_musl_header(arch, target) + sysroot_composer.build_musl(arch, target) + # return original version of clang.gni + shutil.move(clang_gni_tmp, clang_gni) + + if "compiler-rt" in build_config.build_only_libs: + assert os.path.exists(os.path.join(build_config.REPOROOT_DIR, "out", "sysroot")), "Error! Compiler-rt require musl!" + for (_, target) in configs: + llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'crts', True, False) + llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'crts', False, False) + + if "libcxx" in build_config.build_only_libs: + assert os.path.exists(os.path.join(build_config.REPOROOT_DIR, "out", "sysroot")), "Error! Libcxx require musl!" + for (_, target) in configs: + llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'runtimes', False, False) + # return original lib/cmake dir + shutil.move(lib_cmake_tmp, lib_cmake) + windows_python_builder = None if build_config.do_build and need_windows: diff --git a/llvm/include/llvm/BinaryFormat/ADLTSection.h b/llvm/include/llvm/BinaryFormat/ADLTSection.h index 6d57903cdd09deae23b0790d0db0237e8b032713..79b7eeab634dc6d34b2b9713ea2dddd1a7d5dc54 100644 --- a/llvm/include/llvm/BinaryFormat/ADLTSection.h +++ b/llvm/include/llvm/BinaryFormat/ADLTSection.h @@ -69,17 +69,17 @@ typedef struct { // DT_NEEDED string index with embedded PSOD index if available typedef struct { - Elf64_Off hasInternalPSOD : 1; // true if soname - Elf64_Off PSODindex : 16; // PSOD in the current ADLT image - Elf64_Off sonameOffset : 47; // string start in bound .adlt.strtab + Elf64_Off hasInternalPSOD : 1; // true if soname + Elf64_Off PSODindex : 16; // PSOD in the current ADLT image + Elf64_Off sonameOffset : 47; // string start in bound .adlt.strtab } adlt_dt_needed_index_t; typedef enum { - ADLT_HASH_TYPE_NONE = 0, - ADLT_HASH_TYPE_GNU_HASH = 1, - ADLT_HASH_TYPE_SYSV_HASH = 2, - ADLT_HASH_TYPE_DEBUG_CONST = 0xfe, - ADLT_HASH_TYPE_MAX = 0xff, + ADLT_HASH_TYPE_NONE = 0, + ADLT_HASH_TYPE_GNU_HASH = 1, + ADLT_HASH_TYPE_SYSV_HASH = 2, + ADLT_HASH_TYPE_DEBUG_CONST = 0xfe, + ADLT_HASH_TYPE_MAX = 0xff, } adlt_hash_type_enum_t; typedef uint8_t adlt_hash_type_t; diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 68c635abf99c43ada159ed57acd1a2a4116d62b7..f0d1e092ad5515d0f982385f521285d28c0ecbb4 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -261,6 +261,9 @@ static void printProgramHeaders(const ELFFile &Obj, StringRef FileName) { outs() << " OHOS_RANDOMDATA "; break; // OHOS_LOCAL end + case ELF::PT_ADLT: + outs() << " ADLT "; + break; case ELF::PT_PHDR: outs() << " PHDR "; break;