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/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index b23684819a23967127a1cf2e3f5fea57d9733731..95b9a6d4a78d9443440e5a9410b010a9ea14a870 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/Config.h b/lld/ELF/Config.h index d6babe9f74c256bcf7f16f29389bf7b6712413c2..1096562ca594431c1f04b93bdc0b327e466ce2de 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -34,6 +34,8 @@ class BinaryFile; class BitcodeFile; class ELFFileBase; class SharedFile; +template class SharedFileExtended; +struct PhdrEntry; // OHOS_LOCAL class InputSectionBase; class Symbol; @@ -220,6 +222,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; @@ -384,6 +390,7 @@ struct Ctx { SmallVector> memoryBuffers; SmallVector objectFiles; SmallVector sharedFiles; + SmallVector sharedFilesExtended; SmallVector binaryFiles; SmallVector bitcodeFiles; SmallVector lazyBitcodeFiles; @@ -402,6 +409,24 @@ struct Ctx { llvm::DenseMap> backwardReferences; + + // OHOS_LOCAL begin + struct AdltCtx { + template + SharedFileExtended *getSoExt(InputFile *file) { + return cast>(file); + } + + 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; + // Store duplicate symbols (only defined). + llvm::DenseSet duplicatedSymNames; + } adlt; + // OHOS_LOCAL end }; // The only instance of Ctx struct. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 185757ad8c29a94775e0b8694a71972659ec2b46..84f24871eebfdbba53c8a21fa3e505beb352c737 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -276,8 +276,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)); @@ -845,7 +849,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 = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getSymbols()) map[sym->getName()] = sym; @@ -924,6 +929,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)) @@ -1088,6 +1094,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); @@ -1103,7 +1111,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( @@ -1219,7 +1227,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); @@ -1820,7 +1828,8 @@ static void excludeLibs(opt::InputArgList &args) { sym->versionId = VER_NDX_LOCAL; }; - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) visit(file); for (BitcodeFile *file : ctx->bitcodeFiles) @@ -2016,7 +2025,8 @@ static void writeDependencyFile() { // symbols of type CommonSymbol. static void replaceCommonSymbols() { llvm::TimeTraceScope timeScope("Replace common symbols"); - for (ELFFileBase *file : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) { if (!file->hasCommonSyms) continue; for (Symbol *sym : file->getGlobalSymbols()) { @@ -2092,7 +2102,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 = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (InputFile *f : files) { auto *obj = cast>(f); ArrayRef syms = obj->getSymbols(); if (obj->addrsigSec) { @@ -2346,7 +2357,8 @@ static void redirectSymbols(ArrayRef wrapped) { return; // Update pointers in input files. - parallelForEach(ctx->objectFiles, [&](ELFFileBase *file) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + parallelForEach(files, [&](ELFFileBase *file) { for (Symbol *&sym : file->getMutableGlobalSymbols()) if (Symbol *s = map.lookup(sym)) sym = s; @@ -2381,7 +2393,8 @@ static uint32_t getAndFeatures() { return 0; uint32_t ret = -1; - for (ELFFileBase *f : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *f : files) { uint32_t features = f->andFeatures; checkAndReportMissingFeature( @@ -2464,6 +2477,47 @@ static void postParseObjectFile(ELFFileBase *file) { } } +static void postParseSharedFileForAdlt(ELFFileBase *file) { + switch (config->ekind) { + case ELF32LEKind: + cast>(file)->postParseForAdlt(); + break; + case ELF32BEKind: + cast>(file)->postParseForAdlt(); + break; + case ELF64LEKind: + cast>(file)->postParseForAdlt(); + break; + case ELF64BEKind: + cast>(file)->postParseForAdlt(); + break; + default: + llvm_unreachable(""); + } +} + +static bool isSectionValidForAdlt(int fileIdx, InputSectionBase *s) { + 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_info relocation + bool isNeededProgBits = + type == SHT_PROGBITS && + !(name.startswith(".got.plt") || name.startswith(".plt") || + name.startswith(".got") || + name.startswith(".eh_frame_hdr")); // || name.startswith(".debug_")); + bool ret = isBaseType || isNeededProgBits; + + bool isDebug = false; + if (ret && isDebug) + lld::outs() << "[isSectionValidForAdlt]: " << name << "\n"; + return ret; +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. void LinkerDriver::link(opt::InputArgList &args) { @@ -2515,6 +2569,18 @@ void LinkerDriver::link(opt::InputArgList &args) { for (StringRef name : config->undefined) addUnusedUndefined(name)->referenced = true; + // Fill duplicatedSymNames for defined syms. This will help to find + // duplicates. + if (config->adlt) { + ESymsCntMap eSymsHist; + for (auto *file : files) + buildSymsHist(file, eSymsHist); + for (auto eSym : eSymsHist) + if (eSym.second > 1) + ctx->adlt.duplicatedSymNames.insert(eSym.first); + eSymsHist.clear(); + } + // 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 @@ -2533,8 +2599,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 ? !ctx->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. @@ -2589,6 +2656,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(ctx->sharedFilesExtended, postParseSharedFileForAdlt); + parallelForEach(ctx->objectFiles, initializeLocalSymbols); parallelForEach(ctx->objectFiles, postParseObjectFile); parallelForEach(ctx->bitcodeFiles, @@ -2656,6 +2726,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // With this the symbol table should be complete. After this, no new names // except a few linker-synthesized ones will be added to the symbol table. const size_t numObjsBeforeLTO = ctx->objectFiles.size(); + const size_t numSoBeforeLTO = ctx->sharedFilesExtended.size(); invokeELFT(compileBitcodeFiles, skipLinkedOutput); // Symbol resolution finished. Report backward reference problems, @@ -2672,6 +2743,11 @@ void LinkerDriver::link(opt::InputArgList &args) { // compileBitcodeFiles may have produced lto.tmp object files. After this, no // more file will be added. + if (config->adlt) { + auto newSharedFiles = + makeArrayRef(ctx->sharedFilesExtended).slice(numSoBeforeLTO); + parallelForEach(newSharedFiles, postParseSharedFileForAdlt); + } auto newObjectFiles = makeArrayRef(ctx->objectFiles).slice(numObjsBeforeLTO); parallelForEach(newObjectFiles, initializeLocalSymbols); parallelForEach(newObjectFiles, postParseObjectFile); @@ -2695,6 +2771,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 it : llvm::enumerate(ctx->sharedFilesExtended)) + for (InputSectionBase *s : it.value()->getSections()) + if (isSectionValidForAdlt(it.index(), 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 ba317d1e4bb06d373f4c63609769e77968b21ecd..455735d3ce0644a9f41b88b6607cf8404d9b79e0 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -158,6 +158,18 @@ static bool isCompatible(InputFile *file) { return false; } +template +static void doBuildSymsHist(InputFile *file, ESymsCntMap &eSymsHist) { + if (!isCompatible(file)) + return; + if (auto *f = dyn_cast>(file)) + f->buildSymsHist(eSymsHist); +} + +void elf::buildSymsHist(InputFile *file, ESymsCntMap &eSymsHist) { + invokeELFT(doBuildSymsHist, file, eSymsHist); +} + template static void doParseFile(InputFile *file) { if (!isCompatible(file)) return; @@ -184,6 +196,14 @@ template static void doParseFile(InputFile *file) { message(toString(file)); // .so file + if (config->adlt) + if (auto *f = dyn_cast>(file)) { + f->orderIdx = ctx->sharedFilesExtended.size(); + ctx->sharedFilesExtended.push_back(cast(file)); + f->parseForAdlt(); + return; + } + if (auto *f = dyn_cast(file)) { f->parse(); return; @@ -393,6 +413,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 +534,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 +578,13 @@ 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) { + 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; + } switch (sec.sh_type) { case SHT_GROUP: { @@ -569,9 +606,14 @@ 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) { + 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 +640,12 @@ 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))); + 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 +835,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 +1041,24 @@ 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); } +template +void ObjFile::buildSymsHist(ESymsCntMap &eSymsHist) { + ArrayRef eSyms = this->getELFSyms(); + for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) { + if (!eSyms[i].isDefined()) + continue; + StringRef name = CHECK(eSyms[i].getName(stringTable), this); + eSymsHist[CachedHashStringRef(name)]++; + } +} + // Initialize this->Symbols. this->Symbols is a parallel array as // its corresponding ELF symbol table. template @@ -1011,8 +1070,15 @@ 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() && + ctx->adlt.duplicatedSymNames.count(CachedHashStringRef(name)) != 0) { + ctx->adlt.withCfi = ctx->adlt.withCfi || name == "__cfi_check"; + name = this->getUniqueName(name); + } + symbols[i] = symtab.insert(name); + } // Perform symbol resolution on non-local symbols. SmallVector undefineds; @@ -1028,10 +1094,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 +1137,8 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { eSym.getType()}); sym->isUsedInRegularObj = true; sym->referenced = true; + if (config->adlt) + sym->exportDynamic = true; } } @@ -1095,9 +1174,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; } } @@ -1160,6 +1246,14 @@ template void ObjFile::postParse() { if (sym.binding == STB_WEAK || binding == STB_WEAK) continue; std::lock_guard lock(mu); + if (config->adlt) { + auto *f = cast>(this); + bool isDebug = false; + if (isDebug) { + lld::outs() << "Put to duplicates for: " << archiveName << "\n"; + f->traceSymbol(sym); + } + } ctx->duplicates.push_back({&sym, this, sec, eSym.st_value}); } } @@ -1290,6 +1384,37 @@ 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 +1622,556 @@ template void SharedFile::parse() { } } +template +void SharedFileExtended::resolveDuplicatesForAdlt() { + auto pred = [&](DuplicateSymbol dup) { + auto sym = dup.sym; + if (!sym->isDefined()) + return true; + + auto d = cast(sym); + return !d->section && !d->getOutputSection(); + }; + static std::mutex mu; + { + std::lock_guard lock(mu); + llvm::erase_if(ctx->duplicates, pred); + } + + if (ctx->duplicates.empty()) + return; + + { + std::lock_guard lock(mu); + for (DuplicateSymbol &dup : ctx->duplicates) + warn("duplicate: " + dup.file->getName() + ": " + dup.section->name + + ": " + dup.sym->getName()); + ctx->duplicates.clear(); + } +} + +template +SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, + StringRef soName) + : ObjFile(mb, soName), soName(soName), + simpleSoName(path::stem(soName)) { + const_cast(this->fileKind) = InputFile::SharedKind; +} + +template void SharedFileExtended::parseForAdlt() { + this->parse(); + parseDynamics(); + parseElfSymTab(); + + bool isDebug = false; // debug hint + if (!isDebug) + return; + + const ELFFile obj = this->getObj(); + ArrayRef objSections = this->template getELFShdrs(); + + lld::outs() << "Parse symbols from .symtab:\n"; + auto p = obj.getSection(symTabSecIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *elfSymTab = *p; + StringRef strTable = *obj.getStringTableForSymtab(*elfSymTab); + + auto eSyms = *obj.symbols(elfSymTab); + this->symbols.resize(this->symbols.size() + eSyms.size()); + for (const Elf_Sym &sym : eSyms) { + if (!sym.isDefined()) + continue; + + auto rawSec = obj.getSection(sym.st_shndx); + if (rawSec.takeError()) + continue; + if (isDebug) + traceElfSymbol(sym, strTable); + } + if (isDebug) + lld::outs() << '\n'; + + lld::outs() << "Parse offsets of some sections:\n"; + for (const Elf_Shdr &sec : objSections) { + auto name = check(obj.getSectionName(sec)); + if (name == ".init_array" || name == ".fini_array" || name == ".data" || + name == ".data.rel.ro" || name == ".bss.rel.ro" || name == ".bss") + traceElfSection(sec); + } + lld::outs() << '\n'; +} + +template void SharedFileExtended::postParseForAdlt() { + this->initializeLocalSymbols(); + this->postParse(); + resolveDuplicatesForAdlt(); +} + +template +StringRef SharedFileExtended::addAdltPostfix(StringRef input) const { + if (input.empty()) + return input; + auto suffix = Twine("__") + Twine::utohexstr(this->orderIdx); + return saver().save(input + suffix); +} + +template +bool SharedFileExtended::addAdltPostfix(Symbol *s) { + StringRef newName = addAdltPostfix(s->getName()); + if (s->getName() == newName) + return false; + s->setName(newName); + return true; +} + +template +StringRef SharedFileExtended::getUniqueName(StringRef origName) const { + return addAdltPostfix(origName); +} + +// TODO: optimize 2 lookups +template +bool SharedFileExtended::saveSymbol(const Defined &d) const { + auto found = elf::symtab->find(d.getName()); + if (found) + return false; + in.symTab->addSymbol(elf::symtab->addSymbol(d)); + return true; +} + +template +Defined *SharedFileExtended::findSectionSymbol(uint64_t offset) const { + bool isDebug = false; + /*if (offset == 0x7738) // debug hint + isDebug = true;*/ + llvm::SmallVector candidates; + for (auto *sym : this->allSymbols) { + if (!sym || !sym->isSection()) + continue; + assert(sym->isDefined()); + Defined *d = cast(sym); + uint64_t low = d->section->address; + uint64_t high = low + d->section->size; + + if (isDebug) + lld::outs() << "offset: 0x" + utohexstr(offset) + + " sect name: " + d->section->name + "low 0x" + + utohexstr(low) + " high: 0x" + utohexstr(high) + "\n"; + bool isGood = (offset >= low) && (offset < high); + if (!isGood) + continue; + candidates.push_back(d); + } + if (candidates.empty()) // no suitable items found + return nullptr; + + llvm::sort(candidates, [offset](Defined *d1, Defined *d2) { + auto a1 = d1->section->address; + auto a2 = d2->section->address; + return (offset - a1 < offset - a2); + }); + + auto d = *candidates.begin(); + if (isDebug) + traceSymbol(*d, "found section sym: "); + return d; +} + +template +InputSectionBase * +SharedFileExtended::findInputSection(StringRef name) const { + for (InputSectionBase *sec : this->sections) + if (sec && sec->name == name) + return sec; + return nullptr; +} + +template +InputSectionBase * +SharedFileExtended::findInputSection(uint64_t offset) const { + llvm::SmallVector candidates; + for (InputSectionBase *sec : this->sections) { + if (!sec) + continue; + if (sec->address == offset) + return sec; + uint64_t low = sec->address; + uint64_t high = low + sec->size; + bool isGood = (offset >= low) && (offset < high); + if (!isGood) + continue; + candidates.push_back(sec); + } + if (candidates.empty()) // no suitable items found + return nullptr; + + auto lessAddr = [&](auto *s1, auto *s2) { return s1->address < s2->address; }; + auto i = candidates.begin(); + auto e = candidates.end(); + auto ret = std::min_element(i, e, lessAddr); + return *ret; +} + +template +bool SharedFileExtended::isDynamicSection(InputSectionBase &sec) const { + return sec.type == llvm::ELF::SHT_NULL || sec.name.startswith(".got.plt"); +} + +template +Defined *SharedFileExtended::findDefinedSymbol( + uint64_t offset, llvm::function_ref extraCond) const { + bool isDebug = false; + /*if (offset == 0x7738) // debug hint + isDebug = true;*/ + auto predRange = [=](Symbol *sym) { + if (!sym || sym->isUndefined()) + return false; + + Defined *d = cast(sym); + if (d->file != this) + return false; + + bool goodVal = d->section->address + d->value == offset; + return goodVal && extraCond(d); + }; + + auto i = this->allSymbols.begin(); + auto e = this->allSymbols.end(); + auto ret = std::find_if(i, e, predRange); + if (ret != e) { // item was found + Defined *d = cast(*ret); + if (isDebug) + traceSymbol(*d, d->isSection() ? "found section sym: " + : "found defined sym: "); + return d; + } + + auto *sectionSym = findSectionSymbol(offset); + if (isDebug && sectionSym) + traceSymbol(*sectionSym, "found section sym: "); + return sectionSym; +} + +template +StringRef +SharedFileExtended::getShStrTab(ArrayRef elfSections) { + return CHECK(this->getObj().getSectionStringTable(elfSections), this); +} + +template +void SharedFileExtended::traceElfSymbol(const Elf_Sym &sym, + StringRef strTable) const { + const ELFFile obj = this->getObj(); + auto rawSec = obj.getSection(sym.st_shndx); + auto parsedSec = + !rawSec.takeError() ? *obj.getSection(sym.st_shndx) : nullptr; + lld::outs() << "File: " << soName << " symName: " << *sym.getName(strTable) + << " val: 0x" << utohexstr(sym.st_value) << " sec of sym: " + << (parsedSec ? *obj.getSectionName(*parsedSec) : "unknown!") + << " sym type: 0x" << utohexstr(sym.getType()) + << " sym binding: 0x" << utohexstr(sym.getBinding()) << '\n'; +} + +template +void SharedFileExtended::traceElfSection(const Elf_Shdr &sec) const { + const ELFFile obj = this->getObj(); + + auto secName = *obj.getSectionName(sec); + lld::outs() << "File: " << soName << " sec: " << secName << " sec addr: 0x" + << utohexstr(sec.sh_addr) << " sec offs: 0x" + << utohexstr(sec.sh_offset) << " sec ent size: 0x" + << utohexstr(sec.sh_entsize) << '\n'; +} + +template +void SharedFileExtended::traceSymbol(const Symbol &sym, + StringRef title) const { + lld::outs() << "File: " << soName << ": " + title + << " symName: " << sym.getName() << " exportDynamic: 0x" + << utohexstr(sym.exportDynamic); + if (!sym.isDefined()) { + lld::outs() << '\n'; + return; + } + auto &d = cast(sym); + lld::outs() << " val: 0x" << utohexstr(d.value) + << " sec of sym: " << (d.section ? d.section->name : "unknown!") + << " sym type: 0x" << utohexstr(d.type) << " sym binding: 0x" + << utohexstr(d.binding) << '\n'; +} + +template +void SharedFileExtended::traceSection(const SectionBase &sec, + StringRef title) const { + lld::outs() << "File: " << soName << ": " + title << " sec: " << sec.name + << " sec addr: 0x" << utohexstr(sec.address) << " sec offs: 0x" + << utohexstr(sec.getOffset(0)) << " sec ent size: 0x" + << utohexstr(sec.entsize) << '\n'; +} + +template +Symbol &SharedFileExtended::getDynamicSymbol(uint32_t symbolIndex) const { + return *this->symbols[symbolIndex]; +} + +template +Symbol &SharedFileExtended::getSymbolADLT(uint32_t symbolIndex, + bool fromDynamic) const { + Symbol &sym = fromDynamic ? getDynamicSymbol(symbolIndex) + : getSymbolFromElfSymTab(symbolIndex); + + StringRef name = sym.getName(); + if (name.empty()) + return sym; + + /*if (name.contains("__emutls_v.TLS_data1")) // debug hint + lld::outs() << "debug getSymbolADLT(): " << name << "\n";*/ + + // 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 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() && + ctx->adlt.duplicatedSymNames.count(CachedHashStringRef(name)) != 0) + name = this->getUniqueName(name); + + 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; + + eFirstGlobal = 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->allSymbols.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 = addAdltPostfix(name); + /*if (name == "TLS_data1") // debug hint + lld::outs() << name << '\n'; */ + this->allSymbols[i] = + make(this, name, bind, other, type, val, eSym.st_size, sec); + } else { + this->allSymbols[i] = make(this, name, bind, other, type, + /*discardedSecIdx=*/i); + } + } +} + static ELFKind getBitcodeELFKind(const Triple &t) { if (t.isLittleEndian()) return t.isArch64Bit() ? ELF64LEKind : ELF32LEKind; @@ -1737,6 +2412,28 @@ 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; @@ -1789,3 +2486,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..918fa90091cb5993708f12b9159e25b85d13d560 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; @@ -46,6 +47,8 @@ extern std::unique_ptr tar; llvm::Optional readFile(StringRef path); // Add symbols in File to the symbol table. +typedef llvm::DenseMap ESymsCntMap; +void buildSymsHist(InputFile *file, ESymsCntMap &eSymsHist); void parseFile(InputFile *file); // The root class of input files. @@ -76,18 +79,30 @@ 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; } + // ADLT beg + ArrayRef getAllSymbols() const { return allSymbols; } + + SmallVector allSymbols; + // ADLT end + // Get filename to use for linker script processing. StringRef getNameForScript() const; @@ -161,6 +176,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 +185,7 @@ public: StringRef getStringTable() const { return stringTable; } - ArrayRef getLocalSymbols() { + virtual ArrayRef getLocalSymbols() { if (symbols.empty()) return {}; return llvm::makeArrayRef(symbols).slice(1, firstGlobal - 1); @@ -224,6 +240,7 @@ public: ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) { this->archiveName = archiveName; } + virtual ~ObjFile() {} void parse(bool ignoreComdats = false); void parseLazy(); @@ -231,7 +248,7 @@ public: StringRef getShtGroupSignature(ArrayRef sections, const Elf_Shdr &sec); - Symbol &getSymbol(uint32_t symbolIndex) const { + virtual Symbol &getSymbol(uint32_t symbolIndex) const { if (symbolIndex >= this->symbols.size()) fatal(toString(this) + ": invalid symbol index"); return *this->symbols[symbolIndex]; @@ -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. @@ -274,9 +293,13 @@ public: // Get cached DWARF information. DWARFCache *getDwarf(); + void buildSymsHist(ESymsCntMap &eSymsHist); void initializeLocalSymbols(); void postParse(); +protected: + virtual StringRef getUniqueName(StringRef origName) const; + private: void initializeSections(bool ignoreComdats, const llvm::object::ELFFile &obj); @@ -364,6 +387,114 @@ 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 parseForAdlt(); + void postParseForAdlt(); + + StringRef addAdltPostfix(StringRef input) const; + bool addAdltPostfix(Symbol *s); + + bool saveSymbol(const Defined &d) const; + + Defined *findSectionSymbol(uint64_t offset) const; + Defined *findDefinedSymbol( + uint64_t offset, llvm::function_ref extraCond = + [](Defined *) { return true; }) const; + + InputSectionBase *findInputSection(StringRef name) const; + InputSectionBase *findInputSection(uint64_t offset) const; + bool isDynamicSection(InputSectionBase &sec) const; + + template + Symbol &getRelocTargetSymADLT(const RelT &rel, InputSectionBase &sec) const { + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + return getSymbolADLT(symIndex, isDynamicSection(sec)); + } + + ArrayRef getLocalSymbols() override { + if (this->allSymbols.empty()) + return {}; + return llvm::makeArrayRef(this->allSymbols).slice(1, eFirstGlobal - 1); + } + + Symbol &getDynamicSymbol(uint32_t symbolIndex) const; + Symbol &getSymbolADLT(uint32_t symbolIndex, bool fromDynamic) const; + + Symbol &getSymbolFromElfSymTab(uint32_t symbolIndex) const { + if (symbolIndex >= this->allSymbols.size()) + fatal(toString(this) + ": invalid symbol index"); + return *this->allSymbols[symbolIndex]; + } + + void traceElfSymbol(const Elf_Sym &sym, StringRef strTable) const; + void traceElfSection(const Elf_Shdr &sec) const; + + void traceSymbol(const Symbol &sym, StringRef title = "") const; + void traceSection(const SectionBase &sec, StringRef title = "") const; + +public: + // the input order of the file as it presented in ADLT image + size_t orderIdx; + int dynSymSecIdx = 0; + int symTabSecIdx = 0; + int symTabShndxSecIdx = 0; + int eFirstGlobal = 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 dynRelIndexes; + llvm::SetVector pltRelIndexes; + + // 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; + +protected: + virtual StringRef getUniqueName(StringRef origName) const override; + +private: + void parseDynamics(); // SharedFile compability + void parseElfSymTab(); // ObjectFile compability + + void resolveDuplicatesForAdlt(); + + StringRef getShStrTab(ArrayRef elfSections); + + 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 +505,9 @@ 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 8fe36eca6a4be91295854af2af08b9f50e2712d0..0eb2968413bddb05fb4888a7c749490fe14e98ac 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -347,8 +347,11 @@ 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); + const ObjFile *file = + config->adlt ? getSharedFile() : getFile(); + Symbol &sym = config->adlt + ? getSharedFile()->getRelocTargetSymADLT(rel, *sec) + : file->getRelocTargetSym(rel); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -844,7 +847,19 @@ 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 ? getSharedFile()->getSymbolFromElfSymTab( + rel.getSymbol(config->isMips64EL)) + : 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; @@ -948,7 +963,9 @@ 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 (flags & SHF_EXECINSTR && + (config->adlt ? LLVM_UNLIKELY(getSharedFile()->splitStack) + : LLVM_UNLIKELY(getFile()->splitStack))) adjustSplitStackFunctionPrologues(buf, bufEnd); if (flags & SHF_ALLOC) { @@ -985,6 +1002,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..14f318d75f7b25f8f38f5fa6f4595d24839421f5 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -28,6 +28,7 @@ class Defined; struct Partition; class SyntheticSection; template class ObjFile; +template class SharedFileExtended; class OutputSection; extern std::vector partitions; @@ -74,6 +75,8 @@ 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 +136,10 @@ public: return cast_or_null>(file); } + template SharedFileExtended *getSharedFile() const { + return cast_or_null>(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 +399,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..51353287c90e540f36549841479d11cc440673a0 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 = config->adlt ? ctx->sharedFilesExtended : 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 = config->adlt ? ctx->sharedFilesExtended : 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..61be1e13287f75665e3d681fa601a22e04a428bb 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -345,7 +345,8 @@ 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) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + 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 && 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 277c57505bb2f920b51068b7def01c75081ad01c..9806113efa30f7386155c9971a666853945d1154 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -100,7 +100,9 @@ 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,12 @@ 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); @@ -455,6 +463,13 @@ private: void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) const; template void scanOne(RelTy *&i); + + // ADLT + template + void processForADLT(const RelTy &rel, Relocation *r, bool fromDynamic); + + template + void tracePushRelocADLT(InputSectionBase &isec, Relocation &r) const; }; } // namespace @@ -1291,10 +1306,171 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return 0; } +template +static void trackDynRelocAdlt(SharedFileExtended *soFile) { + soFile->dynRelIndexes.insert(mainPart->relaDyn->relocs.size() - 1); +} + +template +static void trackGotPltAdlt(Symbol *sym, SharedFileExtended *soFile) { + ctx->adlt.gotPltInfo[sym].push_back(soFile->orderIdx); +} + +// ADLT BEGIN +template +void RelocationScanner::tracePushRelocADLT(InputSectionBase &isec, + Relocation &r) const { + auto file = sec.getSharedFile(); + auto fullOffset = isec.address + r.offset; + lld::outs() << "[ADLT] Before push: [0x" + utohexstr(fullOffset) + + "] type: " + toString(r.type) + + " expr: " + std::to_string(r.expr) + " offset: 0x" + + utohexstr(r.offset) + " addend: 0x" + utohexstr(r.addend) + + ".\n"; + lld::outs() << "section where: "; + file->traceSection(isec); + + lld::outs() << "r->sym: "; + file->traceSymbol(*r.sym); + lld::outs() << "\n"; +} + +template +void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, + bool fromDynamic) { + auto file = sec.getSharedFile(); + bool isDebug = false; + + /*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 = file->findInputSection(r->offset); + assert(secWhere && "not found!"); + + // process offset + r->offset -= fromDynamic ? secWhere->address : sec.address; + assert(r->type); + + if (isDebug) + tracePushRelocADLT(*secWhere, *r); + + // resolve relocs + switch (r->type) { + // dyn relocs + case R_AARCH64_RELATIVE: { + Defined *d = file->findDefinedSymbol(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); + trackDynRelocAdlt(file); + return; + } + case R_AARCH64_GLOB_DAT: + assert(r->sym->exportDynamic); + if (!r->sym->needsGot) + r->sym->needsGot = 1; + trackGotPltAdlt(r->sym, file); + return; + case R_AARCH64_JUMP_SLOT: + assert(r->sym->exportDynamic); + if (r->sym->isUndefined() && !r->sym->needsPlt) + r->sym->needsPlt = 1; + trackGotPltAdlt(r->sym, file); + 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(target.symbolicRel, *secWhere, + r->offset, *r->sym, r->addend, + r->type); + trackDynRelocAdlt(file); + 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: + processAux(r->expr, r->type, r->offset, *r->sym, r->addend); + 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) { + if (isDebug) + lld::outs() << "[ADLT] R_AARCH64_ADR_GOT_PAGE: sym not in GOT! "; + r->expr = R_PC; // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || + // R_GOT || R_GOT_PC + // TODO: replace reloc R_AARCH64_ADR_GOT_PAGE + sec.relocations.push_back(*r); + return; + } + LLVM_FALLTHROUGH; + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_LD64_GOTPAGE_LO15: + processAux(r->expr, r->type, r->offset, *r->sym, r->addend); + return; + // tls relocs + case R_AARCH64_TLSDESC: + if (fromDynamic && !r->sym->needsTlsDesc) + r->sym->needsTlsDesc = 1; + trackDynRelocAdlt(file); + 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; uint32_t symIndex = rel.getSymbol(config->isMips64EL); - Symbol &sym = sec.getFile()->getSymbol(symIndex); + bool fromDynamic = false; + if (config->adlt) + fromDynamic = sec.getSharedFile()->isDynamicSection(sec); + Symbol &sym = + config->adlt + ? sec.getSharedFile()->getSymbolADLT(symIndex, fromDynamic) + : sec.getFile()->getSymbol(symIndex); RelType type; // Deal with MIPS oddity. @@ -1312,7 +1488,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; @@ -1326,6 +1502,12 @@ 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}; + processForADLT(rel, &r, fromDynamic); + 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. @@ -1536,6 +1718,11 @@ void RelocationScanner::scan(ArrayRef rels) { template void elf::scanRelocations(InputSectionBase &s) { RelocationScanner scanner(s); + if (config->adlt) { + bool isDebug = false; + if (isDebug) + lld::outs() << s.file->getName().str() + ": " + s.name.str() + '\n'; + } const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsRel()) scanner.template scan(rels.rels); @@ -1622,18 +1809,35 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { return true; } +template static void addGotPltIndexAdlt(Symbol *s, bool isPlt) { + auto &vec = ctx->adlt.gotPltInfo[s]; + for (auto &it : vec) { + auto *soFile = cast>(ctx->sharedFilesExtended[it]); + auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; + auto &output = isPlt ? soFile->pltRelIndexes : soFile->dynRelIndexes; + output.insert(entries.size() - 1); + } +} + 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(addGotPltIndexAdlt, &sym, false); + } + if (sym.needsPlt) { addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym); + if (config->adlt) + invokeELFT(addGotPltIndexAdlt, &sym, true); + } if (sym.needsCopy) { if (sym.isObject()) { invokeELFT(addCopyRelSymbol, cast(sym)); @@ -1667,6 +1871,7 @@ void elf::postScanRelocations() { mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible( target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym, target->tlsDescRel); + invokeELFT(addGotPltIndexAdlt, &sym, false); } if (sym.needsTlsGd) { in.got->addDynTlsEntry(sym); @@ -1720,7 +1925,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 ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) fn(*sym); } @@ -2168,7 +2374,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..b336778d48b6637523fdb8b5cbc59cd8c85bc8b3 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1397,9 +1397,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 : ctx->sharedFilesExtended) { + auto *f = cast>(file); + for (size_t i = 0; i < f->dtNeeded.size(); i++) { + auto tag = DT_NEEDED; + auto val = part.dynStrTab->addString(f->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()) @@ -1536,17 +1549,40 @@ DynamicSection::computeContents() { addInSec(DT_HASH, *part.hashTab); if (isMain) { - if (Out::preinitArray) { - addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr); - addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size); - } - if (Out::initArray) { - addInt(DT_INIT_ARRAY, Out::initArray->addr); - addInt(DT_INIT_ARRAYSZ, Out::initArray->size); - } - if (Out::finiArray) { - addInt(DT_FINI_ARRAY, Out::finiArray->addr); - addInt(DT_FINI_ARRAYSZ, Out::finiArray->size); + if (config->adlt) { + auto 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) + return &osd->osec; + return (OutputSection *)nullptr; + }; + for (InputFile *file : ctx->sharedFilesExtended) { + auto *f = cast>(file); + auto initArray = findSection(f->addAdltPostfix(".init_array")); + auto finiArray = findSection(f->addAdltPostfix(".fini_array")); + if (initArray) { + addInt(DT_INIT_ARRAY, initArray->addr); + addInt(DT_INIT_ARRAYSZ, initArray->size); + } + if (finiArray) { + addInt(DT_FINI_ARRAY, finiArray->addr); + addInt(DT_FINI_ARRAYSZ, finiArray->size); + } + } + } else { + if (Out::preinitArray) { + addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr); + addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size); + } + if (Out::initArray) { + addInt(DT_INIT_ARRAY, Out::initArray->addr); + addInt(DT_INIT_ARRAYSZ, Out::initArray->size); + } + if (Out::finiArray) { + addInt(DT_FINI_ARRAY, Out::finiArray->addr); + addInt(DT_FINI_ARRAYSZ, Out::finiArray->size); + } } if (Symbol *b = symtab->find(config->init)) @@ -2207,6 +2243,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 +2263,54 @@ 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 : ctx->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 +3499,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 = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + parallelForEach(files, [](ELFFileBase *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) continue; @@ -3912,6 +4002,8 @@ void InStruct::reset() { strTab.reset(); symTab.reset(); symTabShndx.reset(); + adltData.reset(); + adltStrTab.reset(); } constexpr char kMemtagAndroidNoteName[] = "Android"; @@ -3958,6 +4050,424 @@ 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(ctx->sharedFilesExtended.size()); + for (InputFile *file : ctx->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 + ctx->adlt.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->addAdltPostfix(".init_array"); + data.finiArrayName = soext->addAdltPostfix(".fini_array"); + + data.relaDynIndx = soext->dynRelIndexes.getArrayRef(); + data.relaPltIndx = soext->pltRelIndexes.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 : ctx->adlt.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>(ctx->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 adlt +} // namespace elf +} // namespace lld +// OHOS_LOCAL end + InStruct elf::in; std::vector elf::partitions; @@ -4046,3 +4556,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..6172bf99e7ab1fbbb831f912dba37e247171bf1b 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,107 @@ 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 +1399,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 5ec2d85f64e83b6e7f25bfa4c6f702657e91a979..4ed885c2edd431369a679516d0c45a60214245b4 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..10c768bb7b2f0d22d8ba5b8a1107c3dc6f53bf11 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -116,6 +116,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 +274,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 +313,13 @@ template void elf::createSyntheticSections() { in.symTabShndx = std::make_unique(); } + if (config->adlt) { + 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); @@ -536,6 +546,157 @@ 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() { + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = ctx->adlt.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 : ctx->sharedFilesExtended) + if (auto *soFile = ctx->adlt.getSoExt(file)) { + assert(!soFile->dynRelIndexes.empty() && + "ADLT: relaDyn indexes can't be empty!"); + assert(!soFile->pltRelIndexes.empty() && + "ADLT: relaPlt indexes can't be empty!"); + } +} + +template +void AdltWriter::trackPhdr(OutputSection *sec, PhdrEntry *phdr) { + auto *isec = getInputSection(sec); + if (isec && isec->file) + if (auto *soFile = ctx->adlt.getSoExt(isec->file)) { + soFile->programHeaders.insert(phdr); + return; + } + ctx->adlt.commonProgramHeaders.insert(phdr); +} + +template void AdltWriter::traceRelocs() { + lld::outs() << "[ADLT]\n"; + lld::outs() << "Dyn relocs (" << mainPart->relaDyn->relocs.size() << ")\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 printRelocTable = [&](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" << rel->sym->getName() + << " + 0x" << utohexstr(rel->addend) << '\n'; + }; + + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = ctx->adlt.getSoExt(file)) { + lld::outs() << soFile->soName << ":\n"; + lld::outs() << "Dyn relocs (" << soFile->dynRelIndexes.size() << ")"; + printIndexes(soFile->dynRelIndexes); + printRelocTable(mainPart->relaDyn.get(), soFile->dynRelIndexes); + + lld::outs() << "Plt relocs (" << soFile->pltRelIndexes.size() << ")"; + printIndexes(soFile->pltRelIndexes); + printRelocTable(in.relaPlt.get(), soFile->pltRelIndexes); + } +} + +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 = ctx->adlt.commonProgramHeaders; + lld::outs() << "Common Program Headers (" << common.size() << ")"; + printIndexes(common); + printPhTable(common); + + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = ctx->adlt.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 +789,8 @@ template static void markUsedLocalSymbols() { // See MarkLive::resolveReloc(). if (config->gcSections) return; - for (ELFFileBase *file : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) { ObjFile *f = cast>(file); for (InputSectionBase *s : f->getSections()) { InputSection *isec = dyn_cast_or_null(s); @@ -699,7 +861,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 = /*config->adlt ? ctx->sharedFilesExtended :*/ 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 +992,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 +1180,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 (ctx->adlt.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 +1488,8 @@ static DenseMap buildSectionOrder() { for (Symbol *sym : symtab->symbols()) addSym(*sym); - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) addSym(*sym); @@ -1719,7 +1905,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 = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (InputFile *File : files) { parallelForEach(File->getSymbols(), [&](Symbol *Sym) { auto *def = dyn_cast(Sym); if (!def) @@ -1937,9 +2124,30 @@ 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(ctx->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); @@ -2109,6 +2317,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 +2341,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 +2514,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 cast>(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 +2545,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 +2608,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 +2632,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 +2726,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 +2866,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 b378ac12cc9e3456b2a618af91291d1995306207..a8493097c6ecf12636b6daccf831bf0a9baccf64 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -2071,6 +2071,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' diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 68c635abf99c43ada159ed57acd1a2a4116d62b7..c88623c3a2d72b086115fb2a901ed6ef81b40acb 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -260,6 +260,9 @@ static void printProgramHeaders(const ELFFile &Obj, StringRef FileName) { case ELF::PT_OHOS_RANDOMDATA: outs() << " OHOS_RANDOMDATA "; break; + case ELF::PT_ADLT: + outs() << " ADLT "; + break; // OHOS_LOCAL end case ELF::PT_PHDR: outs() << " PHDR ";