diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 1ea2f4dbe39fac9adab9b8545a81181c91f9e3c6..cd768db8a7ffcf1b04be33e2cac6d7e32418a787 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -34,6 +34,7 @@ class BinaryFile; class BitcodeFile; class ELFFileBase; class SharedFile; +struct PhdrEntry; // OHOS_LOCAL class InputSectionBase; class Symbol; @@ -220,7 +221,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; @@ -408,12 +412,16 @@ struct Ctx { std::pair> backwardReferences; - // ADLT stuff. - bool adltWithCfi = false; - // From input .rela.dyn, .rela.plt: - // Keep input library indexes that are needed for got/plt symbol - llvm::DenseMap> - gotPltInfoAdlt; // sym, soFile->orderIdx array; + // OHOS_LOCAL begin + struct AdltCtx { + 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; + } adlt; + // OHOS_LOCAL end }; // The only instance of Ctx struct. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index c7b4c2fd2b8919027e02a187faeddb3b22eee5ff..2f1fcf79c29a66633f79bb853ee9e25837943069 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1093,6 +1093,7 @@ static void readConfigs(opt::InputArgList &args) { config->bsymbolic = BsymbolicKind::All; } config->adlt = args.hasArg(OPT_adlt); + config->adltTrace = args.hasArg(OPT_adlt_trace); config->checkSections = args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); config->chroot = args.getLastArgValue(OPT_chroot); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index aa908ea4c55083debc4a918847f105c3285ba1ed..3da64f63804d9ac89712a84a0ed987b199fb8fbe 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1041,8 +1041,10 @@ 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); } @@ -1072,8 +1074,7 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { StringRef name = CHECK(eSyms[i].getName(stringTable), this); if (config->adlt && eSyms[i].isDefined() && ctx->eSymsHist.count(CachedHashStringRef(name)) != 0) { - if (!ctx->adltWithCfi && name == "__cfi_check") - ctx->adltWithCfi = true; + ctx->adlt.withCfi = ctx->adlt.withCfi || name == "__cfi_check"; name = this->getUniqueName(name); } symbols[i] = symtab.insert(name); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 46943047df31fec7891eb8bd8b39d13c3bb3ac56..8342d7be88d1227c58bfd179274f4d0f0cdb0c19 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -377,6 +377,8 @@ 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 936a4a2a4bb5bf0dfdce35482e9d1a04fc5f1959..7984401410256df7c663c07ff5d144a63cc9947e 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1311,7 +1311,7 @@ static void trackDynRelocAdlt(SharedFileExtended *soFile) { template static void trackGotPltAdlt(Symbol *sym, SharedFileExtended *soFile) { - ctx->gotPltInfoAdlt[sym].push_back(soFile->orderIdx); + ctx->adlt.gotPltInfo[sym].push_back(soFile->orderIdx); } // ADLT BEGIN @@ -1808,7 +1808,7 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { } template static void addGotPltIndexAdlt(Symbol *s, bool isPlt) { - auto &vec = ctx->gotPltInfoAdlt[s]; + 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; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 83a59320017055f70c51fd9927fc6a2fbb84307b..61d52dc894b5ce2f046fd3a6d075277386f7b8bc 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4084,7 +4084,7 @@ static_assert(sizeof(adltBlobStartMark) == 4, "0xad17 consist of 4 bytes" ); -static_assert(sizeof(adlt_section_header_t) == 40, +static_assert(sizeof(adlt_section_header_t) == 56, "please update version if header has been changed" ); @@ -4126,6 +4126,7 @@ void AdltSection::finalizeContents() { getBlobStartOffset(), // .blobStart estimateBlobSize(), // .blobSize 0, // .overallMappedSize, known on writeTo + adlt_blob_u16_array_t{}, // .phIndexes, filled in writeTo }; buildSonameIndex(); @@ -4198,6 +4199,8 @@ typename AdltSection::CommonData AdltSection::makeCommonData() { return CommonData { UINT32_MAX, // .symtabSecIndex, filled in writeTo + ctx->adlt.commonProgramHeaders.size(), // .programHeadersAllocated + {}, // .phIndexes filled in writeTo }; } @@ -4283,6 +4286,8 @@ 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; @@ -4342,6 +4347,21 @@ void AdltSection::extractProgramHeaderIndexes() { 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 @@ -4405,6 +4425,12 @@ void AdltSection::writeTo(uint8_t* buf) { 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(); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 873f244d68bb28aed1ef18677b628c30278e7317..b51c85ce2ea810c1eab4d880926a0b39dc16e9a6 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1270,6 +1270,8 @@ public: // will be used to form some header data struct CommonData { uint32_t symtabSecIndex = UINT32_MAX; + size_t programHeadersAllocated; + SmallVector phIndexes; }; public: diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 7439ed63c6448f56c82972145328d064124cce6b..dd74a8bc98bfcf890e3e3ad8058adf58ce8c6cd8 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1050,21 +1050,33 @@ void PhdrEntry::add(OutputSection *sec) { lastSec = sec; if (!firstSec) firstSec = sec; - bool adltCFI = config->adlt && ctx->adltWithCfi && p_type == PT_LOAD; - if (adltCFI) // check cfi.h: LIBRARY_ALIGNMENT and _BITS - sec->alignment = 1UL << 18; + p_align = std::max(p_align, sec->alignment); + if (p_type == PT_LOAD) sec->ptLoad = this; - if (config->adlt && (p_type == PT_LOAD || p_type == PT_TLS)) { - auto* insec = getInputSection(sec); - // skip generated sections. - // TODO: fix .rodata_$ADLT_POSTFIX sections. - if (insec && insec->file) { - invokeELFT(addPhdrToSharedFilesExtendedContext, insec->file, 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 = std::max(firstSec->alignment, kCFILibraryAlignment); + p_align = std::max(p_align, kCFILibraryAlignment); + } + + if (p_type == PT_LOAD || p_type == PT_TLS) { + auto* insec = getInputSection(sec); + // skip generated sections. + // TODO: fix .rodata_$ADLT_POSTFIX sections. + if (insec && insec->file) { + invokeELFT(addPhdrToSharedFilesExtendedContext, insec->file, this); + } else { + ctx->adlt.commonProgramHeaders.insert(this); + } } } + // OHOS_LOCAL end } // The beginning and the ending of .rel[a].plt section are marked @@ -2410,12 +2422,22 @@ SmallVector Writer::createPhdrs(Partition &part) { return ret.back(); }; + // OHOS_LOCAL begin + auto getOwnerFileIdx = [](OutputSection* sec) -> llvm::Optional { + auto file = 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. @@ -2494,8 +2516,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; diff --git a/llvm/include/llvm/BinaryFormat/ADLTSection.h b/llvm/include/llvm/BinaryFormat/ADLTSection.h index ac883cb30da8d92c5aed462eb15905d75c32b689..073f24573768b362940f0f249d28de995a22ed26 100644 --- a/llvm/include/llvm/BinaryFormat/ADLTSection.h +++ b/llvm/include/llvm/BinaryFormat/ADLTSection.h @@ -107,11 +107,12 @@ typedef struct { Elf64_Off blobStart; // offset of binary blob start relative to .adlt Elf64_Xword blobSize; Elf64_Xword overallMappedSize; // bytes, required to map the whole ADLT image + adlt_blob_u16_array_t phIndexes; // program header indexes, typeof(e_phnum) } adlt_section_header_t; static const char adltBlobStartMark[4] = { 0xA, 0xD, 0x1, 0x7 }; -static const adlt_semver_t adltSchemaVersion = {1, 0, 0}; +static const adlt_semver_t adltSchemaVersion = {1, 1, 0}; #ifdef __cplusplus } // namespace adlt diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 07e2fbaefaf11c8b53064cefe93ca07ca3a54273..b6de5e52ee58c343f5df456beb94d65c157cb59a 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -7033,6 +7033,16 @@ template void LLVMELFDumper::printAdltSection() { auto* header = reinterpret_cast(adltRaw.data()); const auto& ver = header->schemaVersion; + ArrayRef psodsRaw; + ArrayRef blob; + + if (psodsRaw.data() + psodsRaw.size() > blob.data()) + return this->reportUniqueWarning("invalid .adlt section: " + "PSOD and blob entries are overlapped"); + if (blob.data() + blob.size() > adltRaw.data() + adltRaw.size()) + return this->reportUniqueWarning("invalid .adlt section: " + "blob is out of section range"); + DictScope DSec(W, "ADLT"); do { @@ -7051,19 +7061,35 @@ template void LLVMELFDumper::printAdltSection() { W.printHex("blob-start", header->blobStart); W.printHex("blob-size", header->blobSize); W.printHex("overall-mapped-size", header->overallMappedSize); - } while(0); - - ArrayRef psodsRaw = adltRaw.slice( - header->schemaHeaderSize, - header->sharedObjectsNum * header->schemaPSODSize); - ArrayRef blob = adltRaw.slice(header->blobStart, header->blobSize); - if (psodsRaw.data() + psodsRaw.size() > blob.data()) - return this->reportUniqueWarning("invalid .adlt section: " - "PSOD and blob entries are overlapped"); - if (blob.data() + blob.size() > adltRaw.data() + adltRaw.size()) - return this->reportUniqueWarning("invalid .adlt section: " - "blob is out of section range"); + psodsRaw = adltRaw.slice( + header->schemaHeaderSize, + header->sharedObjectsNum * header->schemaPSODSize); + blob = adltRaw.slice(header->blobStart, header->blobSize); + + if (psodsRaw.data() + psodsRaw.size() > blob.data()) + return this->reportUniqueWarning("invalid .adlt section: " + "PSOD and blob entries are overlapped"); + if (blob.data() + blob.size() > adltRaw.data() + adltRaw.size()) + return this->reportUniqueWarning("invalid .adlt section: " + "blob is out of section range"); + + if (ver.minor >= 1) { + DictScope PHEntry(W, "ph-indexes"); + const auto& arr = header->phIndexes; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + W.printBinary("raw", chunk); + ArrayRef phIdxs( + reinterpret_cast(chunk.data()), + chunk.size() / sizeof(uint16_t)); + W.printList("values", phIdxs); + } + } + } while(0); { ListScope LPsods(W, "PSODs"); @@ -7132,7 +7158,7 @@ template void LLVMELFDumper::printAdltSection() { W.printHex("offset", csref.offset); } { - DictScope PHEntry(W, "ph-index"); + DictScope PHEntry(W, "ph-indexes"); const auto& arr = psod.phIndexes; W.printHex("size", arr.size); W.printHex("offset", arr.offset);