From 3316b3e116a7906ab08af1f84c02c66d8fa76c1c Mon Sep 17 00:00:00 2001 From: Khomutov Nikita Date: Fri, 29 Mar 2024 12:07:43 +0300 Subject: [PATCH 1/5] [ADLT] .adlt section generation - generate .adlt and .adlt.strtab sections - pass .init_array and .fini_array to .adlt PSODs - dump input DT_SONAME and DT_NEEDED names to .adlt.strtab - dump DT_NEEDED dependency graph to .adlt blob - enable gnu-hash by default for soname - .adlt version 1.0.0 Signed-off-by: Khomutov Nikita Change-Id: I4c09053fc05a38c8d28d9325ce1ccea146623a3c --- lld/ELF/InputFiles.cpp | 51 ++++++- lld/ELF/InputFiles.h | 31 ++++- lld/ELF/SyntheticSections.cpp | 249 ++++++++++++++++++++++++++++++++++ lld/ELF/SyntheticSections.h | 150 ++++++++++++++++++++ lld/ELF/Writer.cpp | 12 ++ 5 files changed, 489 insertions(+), 4 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 8bd05c5a253f..38eab6703e75 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1689,7 +1689,22 @@ template void SharedFileExtended::postParseForAdlt() { } template -StringRef SharedFileExtended::addAdltPostfix(StringRef input) { +const adlt::StringRefVector& SharedFileExtended::getDtNeeded() const { + return dtNeeded; +} + +template +StringRef SharedFileExtended::getSoName() const { + return soName; +} + +template +StringRef SharedFileExtended::getSectionNameWPostfix(StringRef name) const { + return addAdltPostfix(name); +} + +template +StringRef SharedFileExtended::addAdltPostfix(StringRef input) const { return markItemForAdlt(input, soName); } @@ -2359,6 +2374,40 @@ ELFFileBase *elf::createSharedFileExtended(MemoryBufferRef mb, StringRef soName) return f; } +namespace lld { namespace elf { namespace adlt { + +AdltInputInterface* queryAdltInterface(InputFile* file) { + AdltInputInterface* ifc = nullptr; + switch (config->ekind) + { + case ELF32LEKind: + if (auto* soext = dyn_cast>(file)) { + ifc = soext; + } + break; + case ELF32BEKind: + if (auto* soext = dyn_cast>(file)) { + ifc = soext; + } + break; + case ELF64LEKind: + if (auto* soext = dyn_cast>(file)) { + ifc = soext; + } + break; + case ELF64BEKind: + if (auto* soext = dyn_cast>(file)) { + ifc = soext; + } + break; + default: + break; + } + return ifc; +} + +}}} + template void ObjFile::parseLazy() { const ArrayRef eSyms = this->getELFSyms(); SymbolTable &symtab = *elf::symtab; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index bc3d594189ee..28c275f9c9b5 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -384,9 +384,28 @@ private: }; +namespace adlt { + +using StringRefVector = SmallVector; + +class AdltInputInterface { +public: + virtual ~AdltInputInterface() = default; + + virtual const StringRefVector& getDtNeeded() const = 0; + virtual StringRef getSoName() const = 0; + virtual StringRef getSectionNameWPostfix(StringRef name) const = 0; +}; + +AdltInputInterface* queryAdltInterface(InputFile* file); + +} // namespace adlt + // ADLT template -class SharedFileExtended : public ObjFile { +class SharedFileExtended : + public ObjFile, + public adlt::AdltInputInterface { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) public: @@ -396,10 +415,15 @@ public: return f->kind() == InputFile::SharedKind; } + // adlt::AdltInputInterface impl + const adlt::StringRefVector& getDtNeeded() const override; + StringRef getSoName() const override; + StringRef getSectionNameWPostfix(StringRef name) const override; + void parseForAdlt(); void postParseForAdlt(); - StringRef addAdltPostfix(StringRef input); + StringRef addAdltPostfix(StringRef input) const; bool addAdltPostfix(Symbol *s); bool saveSymbol(const Defined& d) const; @@ -436,6 +460,7 @@ public: void traceSymbol(const Symbol &sym, StringRef title = "") const; void traceSection(const SectionBase &sec, StringRef title = "") const; +public: int dynSymSecIdx = 0; int symTabSecIdx = 0; int symTabShndxSecIdx = 0; @@ -448,7 +473,7 @@ public: // Verdefs, otherwise it is empty. SmallVector vernauxs; static unsigned vernauxNum; - SmallVector dtNeeded; + adlt::StringRefVector dtNeeded; StringRef soName; StringRef simpleSoName; // Used for --as-needed diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 29135ddb16d7..fbae7c57a992 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3950,6 +3950,8 @@ void InStruct::reset() { strTab.reset(); symTab.reset(); symTabShndx.reset(); + adltData.reset(); + adltStrTab.reset(); } constexpr char kMemtagAndroidNoteName[] = "Android"; @@ -3996,6 +3998,253 @@ size_t PackageMetadataNote::getSize() const { alignTo(config->packageMetadata.size() + 1, 4); } + +// OHOS_LOCAL begin +namespace lld { namespace elf { namespace adlt { + +#define DEBUG_TYPE "lld-adlt-section" + +AdltSection::AdltSection(StringTableSection& strTabSec) + : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") + , strTabSec(strTabSec) +{ + assert(config->adlt); +} + +void AdltSection::finalizeContents() { + soInputs.clear(); + soInputs.reserve(ctx->sharedFilesExtended.size()); + for (InputFile* file : ctx->sharedFilesExtended) { + const auto* soIfc = queryAdltInterface(file); + if (!soIfc) { + warn(Twine(".adlt-section: input file is not an adlt input: ") + + file->getName()); + continue; + } + soInputs.push_back(makeSoData(soIfc)); + } + + assert((soInputs.size() < 1<<16) && + "the number of input libs exeeds ELF limit on number of sections"); + const Elf64_Half soNum = soInputs.size(); + + header = AdltSectionHeader{ + {1, 0, 0}, // .schemaVersion + sizeof(PSOD), // .schemaPSODSize + soNum, // .sharedObjectsNum + HashType::MUSL_GNU_HASH, // .stringHashType + getBlobStartOffset(), // .blobStart + estimateBlobSize(), // .blobSize + }; + + buildSonameIndex(); + linkInternalDtNeeded(); + extractInitFiniArray(); +} + +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)); + } + } +} + +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; + } + } + } +} + +OutputSection* AdltSection::findOutSection(StringRef name) { + 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; +} + +void AdltSection::extractInitFiniArray() { + for (auto& soData : soInputs) { + auto initArrayName = soData.ifc->getSectionNameWPostfix(".init_array"); + auto finiArrayName = soData.ifc->getSectionNameWPostfix(".fini_array"); + soData.initArraySec = findOutSection(initArrayName); + soData.finiArraySec = findOutSection(finiArrayName); + } +} + +AdltSection::SoData AdltSection::makeSoData(const AdltInputInterface* ifc) { + SoData data = {}; + data.ifc = ifc; + + StringRef soname = ifc->getSoName(); + data.soName = SectionString{soname, strTabSec.addString(soname)}; + + for (const auto& neededName: ifc->getDtNeeded()) { + data.dtNeededs.push_back({ + SectionString{neededName, strTabSec.addString(neededName)}, + {}, // internal PSOD index is uknown by the moment, will be linked + }); + } + + // TODO: + // sharedLocalIndex + // sharedGlobalIndex + + // TODO: get section index for sharedLocalIndex + // TODO: get section index for sharedGlobalIndex + + return data; +} + +Elf64_Xword AdltSection::calculateHash(StringRef str) const { + switch(header.stringHashType) { + case HashType::NONE: + return 0x0; + case HashType::MUSL_GNU_HASH: + return hashGnu(str); + case HashType::DEBUG_CONST: + return 0xdeadbeef1337c0de; + default: + llvm_unreachable(".adlt hash type not implemented"); + } +} + +PSOD AdltSection::serialize(const SoData& soData) const { + return PSOD { + soData.soName.strtabOff, // .soName + calculateHash(soData.soName.ref), // .soNameHash + soData.initArraySec ? CrossSectionVec{ // .initArray + soData.initArraySec->sectionIndex, + soData.initArraySec->size / sizeof(Elf64_Addr), // size + soData.initArraySec->addr, + } : CrossSectionVec{0, 0, 0}, + soData.finiArraySec ? CrossSectionVec{ // .finiArray + soData.finiArraySec->sectionIndex, + soData.finiArraySec->size / sizeof(Elf64_Addr), // size + soData.finiArraySec->addr, + } : CrossSectionVec{0, 0, 0}, + 0x0, // .dtNeeded // filled by blob serialization + soData.dtNeededs.size(), // .dtNeededSz + CrossSectionRef { + 0, // .sectionIndex + soData.sharedLocalIndex, // .offsetFromStart + }, // .sharedLocalSymbolIndex + CrossSectionRef { + 0, // .sectionIndex + soData.sharedGlobalIndex, // .offsetFromStart + }, // .sharedGlobalSymbolIndex + }; +} + +Elf64_Off AdltSection::getBlobStartOffset() const { + return sizeof(header) + sizeof(PSOD) * soInputs.size(); +} + +size_t AdltSection::estimateBlobSize() const { + size_t blobSize = sizeof(BlobStartMark); + + for (const auto& soData: soInputs) { + blobSize += sizeof(DtNeededIndex) * soData.dtNeededs.size(); + }; + + return blobSize; +} + +size_t AdltSection::writeDtNeededVec( + uint8_t* buff, const DtNeededsVec& neededVec) const { + if (neededVec.empty()) return 0; + + SmallVector needIndexes; + needIndexes.reserve(neededVec.size()); + for (const auto& need_data : neededVec) { + needIndexes.push_back(DtNeededIndex{ + need_data.psodIndex.has_value(), // .hasInternalPSOD + need_data.psodIndex.value_or(0), // .PSODindex + need_data.str.strtabOff, // .sonameOffset + }); + } + + memcpy(buff, needIndexes.data(), needIndexes.size_in_bytes()); + return needIndexes.size_in_bytes(); +} + +void AdltSection::writeTo(uint8_t* buf) { + // TODO: take care of endianness, use write32 / write64 etc. + // pre-serialized SoData, enriched with offsets during blob writing + SmallVector psods; + + for (const auto& it: llvm::enumerate(soInputs)) { + const SoData& soData = it.value(); + PSOD psod = serialize(soData); + psods.push_back(psod); + } + + // serialize blob data + { + uint8_t* const blob_buf = buf + header.blobStart; + size_t blob_off = 0; + memcpy(blob_buf + blob_off, &BlobStartMark, sizeof(BlobStartMark)); + blob_off += sizeof(BlobStartMark); + + // dt-needed + for(const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + PSOD& psod = psods[it.index()]; + + psod.dtNeededSz = soData.dtNeededs.size(); + psod.dtNeeded = blob_off; + blob_off += writeDtNeededVec(blob_buf + blob_off, soData.dtNeededs); + } + + // finalize header.blobSize + assert((blob_off <= header.blobSize) && + ".adlt-section: blob output exeeds its initial estimation"); + header.blobSize = blob_off; + } + + // 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)) { + PSOD& psod = psods[it.index()]; + memcpy(psods_buf + psods_off, &psod, sizeof(PSOD)); + psods_off += sizeof(PSOD); + } + } +} + +size_t AdltSection::getSize() const { + const size_t pre_blob_size = sizeof(header) + sizeof(PSOD) * soInputs.size(); + assert(pre_blob_size <= header.blobStart); + return header.blobStart + header.blobSize; +} + +#undef DEBUG_TYPE +}}} // namespace lld::elf::adlt +// OHOS_LOCAL end + + InStruct elf::in; std::vector elf::partitions; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 83a2bd7d34df..2561de8fccf4 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1220,6 +1220,152 @@ public: size_t getSize() const override; }; + +namespace adlt { + +using llvm::ELF::Elf64_Half; +using llvm::ELF::Elf64_Off; +using llvm::ELF::Elf64_Addr; +using llvm::ELF::Elf64_Word; +using llvm::ELF::Elf64_Xword; +using Elf64_Byte = uint8_t; + +struct CrossSectionRef { + Elf64_Word sectionIndex; + Elf64_Off offsetFromStart; +}; + +struct SemanticVersion { + Elf64_Half major: 6; + Elf64_Half minor: 6; + Elf64_Half patch: 4; +}; + +static_assert( + sizeof(SemanticVersion) == sizeof(Elf64_Half), + ".adlt semantic version is designed to occupy uint16_t" +); + +enum HashType : Elf64_Byte { + NONE = 0, + MUSL_GNU_HASH = 1, + MUSL_SYSV_HASH = 2, + MUSL_KEYHASH = 3, + DEBUG_CONST = 0xff, +}; + +struct DtNeededIndex { + bool hasInternalPSOD : 1; // true if soname + Elf64_Off PSODindex : 16; // PSOD in the current ADLT image + Elf64_Off sonameOffset : 47; // string start in bound strTabSec +}; + +static_assert( + sizeof(DtNeededIndex) == sizeof(Elf64_Off), + "DtNeededIndex have to be an offset with intrused flags" +); + +struct CrossSectionVec { + Elf64_Xword secIndex; + Elf64_Xword numElem; + Elf64_Addr addr; +}; + +// Serializable representation per-shared-object-data in .adlt section +struct PSOD { + Elf64_Off soName; // offset in strTabSec + Elf64_Xword soNameHash; + CrossSectionVec initArray; + CrossSectionVec finiArray; + Elf64_Off dtNeeded; // offset to DtNeededIndex[] in blob + Elf64_Xword dtNeededSz; + CrossSectionRef sharedLocalSymbolIndex; + CrossSectionRef sharedGlobalSymbolIndex; +}; + +struct AdltSectionHeader { + SemanticVersion schemaVersion = {1, 0, 0}; + Elf64_Half schemaPSODSize = sizeof(PSOD); + Elf64_Half sharedObjectsNum; + HashType stringHashType = HashType::NONE; + Elf64_Off blobStart; // binary blob start offset from the .adlt start + Elf64_Xword blobSize; +}; + +// serialized blob structures + +constexpr char BlobStartMark[4] = {0xA, 0xD, 0x1, 0x7}; + + +// fwd +class AdltInputInterface; + +class AdltSection final : public SyntheticSection { +public: + struct SectionString { + StringRef ref; + Elf64_Off strtabOff; // offset in strTabSec + }; + + // will be serialized to DtNeededIndex + struct DtNeededData { + SectionString str; + llvm::Optional psodIndex; + }; + + using SectionStringVector = SmallVector; + using DtNeededsVec = SmallVector; + + // will be serialized to PSOD + struct SoData { + const AdltInputInterface* ifc; + + SectionString soName; + DtNeededsVec dtNeededs; + + OutputSection* initArraySec; + OutputSection* finiArraySec; + + Elf64_Off sharedLocalIndex; // TODO + Elf64_Off sharedGlobalIndex; // TODO + }; + + +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(); + + Elf64_Xword calculateHash(StringRef str) const; + SoData makeSoData(const AdltInputInterface*); + PSOD serialize(const SoData&) const; + + size_t estimateBlobSize() const; + size_t writeDtNeededVec(uint8_t* buff, const DtNeededsVec& neededVec) const; + +private: + StringTableSection& strTabSec; + + AdltSectionHeader header = {}; + std::vector soInputs; + llvm::DenseMap sonameToIndexMap; +}; + +} // namespace adlt + + + InputSection *createInterpSection(); MergeInputSection *createCommentSection(); template void splitSections(); @@ -1295,6 +1441,10 @@ struct InStruct { std::unique_ptr strTab; std::unique_ptr symTab; std::unique_ptr symTabShndx; + std::unique_ptr adltData; + // TODO: research DT_SONAME and DT_NEEDED location in .dynstr + // TODO: replace with dynStrTab + std::unique_ptr adltStrTab; void reset(); }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index de16dec8e609..6834e6cebfa7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -312,6 +312,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); @@ -2127,6 +2134,11 @@ template void Writer::finalizeSections() { finalizeSynthetic(in.iplt.get()); 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. -- Gitee From 6dea2b3e80932986dce014890d753ece09a366d1 Mon Sep 17 00:00:00 2001 From: Khomutov Nikita Date: Fri, 29 Mar 2024 14:49:26 +0300 Subject: [PATCH 2/5] review fix: - better containers - styling Signed-off-by: Khomutov Nikita Change-Id: I0577a18ba5f6f1fbe20e8a11e1f459d6abab9aa4 --- lld/ELF/InputFiles.cpp | 2 +- lld/ELF/InputFiles.h | 6 +++--- lld/ELF/SyntheticSections.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 38eab6703e75..60b172c0db30 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1689,7 +1689,7 @@ template void SharedFileExtended::postParseForAdlt() { } template -const adlt::StringRefVector& SharedFileExtended::getDtNeeded() const { +const SmallVector& SharedFileExtended::getDtNeeded() const { return dtNeeded; } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 28c275f9c9b5..bade20df08f2 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -392,7 +392,7 @@ class AdltInputInterface { public: virtual ~AdltInputInterface() = default; - virtual const StringRefVector& getDtNeeded() const = 0; + virtual const SmallVector& getDtNeeded() const = 0; virtual StringRef getSoName() const = 0; virtual StringRef getSectionNameWPostfix(StringRef name) const = 0; }; @@ -416,7 +416,7 @@ public: } // adlt::AdltInputInterface impl - const adlt::StringRefVector& getDtNeeded() const override; + const SmallVector& getDtNeeded() const override; StringRef getSoName() const override; StringRef getSectionNameWPostfix(StringRef name) const override; @@ -473,7 +473,7 @@ public: // Verdefs, otherwise it is empty. SmallVector vernauxs; static unsigned vernauxNum; - adlt::StringRefVector dtNeeded; + SmallVector dtNeeded; StringRef soName; StringRef simpleSoName; // Used for --as-needed diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 2561de8fccf4..fa97f89a307f 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1358,7 +1358,7 @@ private: StringTableSection& strTabSec; AdltSectionHeader header = {}; - std::vector soInputs; + SmallVector soInputs; llvm::DenseMap sonameToIndexMap; }; -- Gitee From 0b40a65b11ea978af934bee7fe005561286eaacb Mon Sep 17 00:00:00 2001 From: Khomutov Nikita Date: Sat, 30 Mar 2024 11:42:03 +0300 Subject: [PATCH 3/5] review fix: cover llvm_unreachable in the fallback swich case Signed-off-by: Khomutov Nikita Change-Id: I6e46d754914d4ccb953fc6caa653f12c11a78a11 --- lld/ELF/InputFiles.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 60b172c0db30..0c1b31d44b6c 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -2401,6 +2401,7 @@ AdltInputInterface* queryAdltInterface(InputFile* file) { } break; default: + llvm_unreachable("config->ekind"); break; } return ifc; -- Gitee From 94a42a40b9e8b00462398a802d0c341b41807d69 Mon Sep 17 00:00:00 2001 From: Khomutov Nikita Date: Sat, 30 Mar 2024 14:15:31 +0300 Subject: [PATCH 4/5] review fix: - make AdltSection a template with ELFT context - get rid of AdltInputInterface Signed-off-by: Khomutov Nikita Change-Id: I99d2dc2cd631c6a82704607e2d134d3695fec18c --- lld/ELF/InputFiles.cpp | 49 ------------------------ lld/ELF/InputFiles.h | 28 +------------- lld/ELF/SyntheticSections.cpp | 72 ++++++++++++++++++++++------------- lld/ELF/SyntheticSections.h | 18 ++++----- lld/ELF/Writer.cpp | 2 +- 5 files changed, 55 insertions(+), 114 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0c1b31d44b6c..8d541fe52f61 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1688,20 +1688,6 @@ template void SharedFileExtended::postParseForAdlt() { resolveDuplicatesForAdlt(); } -template -const SmallVector& SharedFileExtended::getDtNeeded() const { - return dtNeeded; -} - -template -StringRef SharedFileExtended::getSoName() const { - return soName; -} - -template -StringRef SharedFileExtended::getSectionNameWPostfix(StringRef name) const { - return addAdltPostfix(name); -} template StringRef SharedFileExtended::addAdltPostfix(StringRef input) const { @@ -2374,41 +2360,6 @@ ELFFileBase *elf::createSharedFileExtended(MemoryBufferRef mb, StringRef soName) return f; } -namespace lld { namespace elf { namespace adlt { - -AdltInputInterface* queryAdltInterface(InputFile* file) { - AdltInputInterface* ifc = nullptr; - switch (config->ekind) - { - case ELF32LEKind: - if (auto* soext = dyn_cast>(file)) { - ifc = soext; - } - break; - case ELF32BEKind: - if (auto* soext = dyn_cast>(file)) { - ifc = soext; - } - break; - case ELF64LEKind: - if (auto* soext = dyn_cast>(file)) { - ifc = soext; - } - break; - case ELF64BEKind: - if (auto* soext = dyn_cast>(file)) { - ifc = soext; - } - break; - default: - llvm_unreachable("config->ekind"); - break; - } - return ifc; -} - -}}} - template void ObjFile::parseLazy() { const ArrayRef eSyms = this->getELFSyms(); SymbolTable &symtab = *elf::symtab; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index bade20df08f2..68d76d5fb48e 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -384,28 +384,9 @@ private: }; -namespace adlt { - -using StringRefVector = SmallVector; - -class AdltInputInterface { -public: - virtual ~AdltInputInterface() = default; - - virtual const SmallVector& getDtNeeded() const = 0; - virtual StringRef getSoName() const = 0; - virtual StringRef getSectionNameWPostfix(StringRef name) const = 0; -}; - -AdltInputInterface* queryAdltInterface(InputFile* file); - -} // namespace adlt - // ADLT template -class SharedFileExtended : - public ObjFile, - public adlt::AdltInputInterface { +class SharedFileExtended : public ObjFile { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) public: @@ -415,11 +396,6 @@ public: return f->kind() == InputFile::SharedKind; } - // adlt::AdltInputInterface impl - const SmallVector& getDtNeeded() const override; - StringRef getSoName() const override; - StringRef getSectionNameWPostfix(StringRef name) const override; - void parseForAdlt(); void postParseForAdlt(); @@ -473,7 +449,7 @@ public: // Verdefs, otherwise it is empty. SmallVector vernauxs; static unsigned vernauxNum; - SmallVector dtNeeded; + SmallVector dtNeeded; StringRef soName; StringRef simpleSoName; // Used for --as-needed diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index fbae7c57a992..d3b56395751d 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4004,24 +4004,21 @@ namespace lld { namespace elf { namespace adlt { #define DEBUG_TYPE "lld-adlt-section" -AdltSection::AdltSection(StringTableSection& strTabSec) +template +AdltSection::AdltSection(StringTableSection& strTabSec) : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") , strTabSec(strTabSec) { assert(config->adlt); } -void AdltSection::finalizeContents() { +template +void AdltSection::finalizeContents() { soInputs.clear(); soInputs.reserve(ctx->sharedFilesExtended.size()); for (InputFile* file : ctx->sharedFilesExtended) { - const auto* soIfc = queryAdltInterface(file); - if (!soIfc) { - warn(Twine(".adlt-section: input file is not an adlt input: ") + - file->getName()); - continue; - } - soInputs.push_back(makeSoData(soIfc)); + auto* soext = cast>(file); + soInputs.push_back(makeSoData(soext)); } assert((soInputs.size() < 1<<16) && @@ -4042,7 +4039,8 @@ void AdltSection::finalizeContents() { extractInitFiniArray(); } -void AdltSection::buildSonameIndex() { +template +void AdltSection::buildSonameIndex() { for (const auto& it : llvm::enumerate(soInputs)) { const auto& soData = it.value(); auto res = sonameToIndexMap.try_emplace( @@ -4055,7 +4053,8 @@ void AdltSection::buildSonameIndex() { } } -void AdltSection::linkInternalDtNeeded() { +template +void AdltSection::linkInternalDtNeeded() { for (auto it : llvm::enumerate(soInputs)) { auto& soData = it.value(); for (auto& needed : soData.dtNeededs) { @@ -4068,8 +4067,11 @@ void AdltSection::linkInternalDtNeeded() { } } -OutputSection* AdltSection::findOutSection(StringRef name) { +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) @@ -4078,29 +4080,33 @@ OutputSection* AdltSection::findOutSection(StringRef name) { return nullptr; } -void AdltSection::extractInitFiniArray() { +template +void AdltSection::extractInitFiniArray() { for (auto& soData : soInputs) { - auto initArrayName = soData.ifc->getSectionNameWPostfix(".init_array"); - auto finiArrayName = soData.ifc->getSectionNameWPostfix(".fini_array"); + auto initArrayName = soData.initArrayName; + auto finiArrayName = soData.finiArrayName; soData.initArraySec = findOutSection(initArrayName); soData.finiArraySec = findOutSection(finiArrayName); } } -AdltSection::SoData AdltSection::makeSoData(const AdltInputInterface* ifc) { +template +typename AdltSection::SoData +AdltSection::makeSoData(const SharedFileExtended* soext) { SoData data = {}; - data.ifc = ifc; - - StringRef soname = ifc->getSoName(); + StringRef soname = soext->soName; data.soName = SectionString{soname, strTabSec.addString(soname)}; - for (const auto& neededName: ifc->getDtNeeded()) { + for (const auto& neededName: soext->dtNeeded) { data.dtNeededs.push_back({ SectionString{neededName, strTabSec.addString(neededName)}, {}, // internal PSOD index is uknown by the moment, will be linked }); } + data.initArrayName = soext->addAdltPostfix(".init_array"); + data.finiArrayName = soext->addAdltPostfix(".fini_array"); + // TODO: // sharedLocalIndex // sharedGlobalIndex @@ -4111,7 +4117,8 @@ AdltSection::SoData AdltSection::makeSoData(const AdltInputInterface* ifc) { return data; } -Elf64_Xword AdltSection::calculateHash(StringRef str) const { +template +Elf64_Xword AdltSection::calculateHash(StringRef str) const { switch(header.stringHashType) { case HashType::NONE: return 0x0; @@ -4124,7 +4131,8 @@ Elf64_Xword AdltSection::calculateHash(StringRef str) const { } } -PSOD AdltSection::serialize(const SoData& soData) const { +template +PSOD AdltSection::serialize(const SoData& soData) const { return PSOD { soData.soName.strtabOff, // .soName calculateHash(soData.soName.ref), // .soNameHash @@ -4151,11 +4159,13 @@ PSOD AdltSection::serialize(const SoData& soData) const { }; } -Elf64_Off AdltSection::getBlobStartOffset() const { +template +Elf64_Off AdltSection::getBlobStartOffset() const { return sizeof(header) + sizeof(PSOD) * soInputs.size(); } -size_t AdltSection::estimateBlobSize() const { +template +size_t AdltSection::estimateBlobSize() const { size_t blobSize = sizeof(BlobStartMark); for (const auto& soData: soInputs) { @@ -4165,7 +4175,8 @@ size_t AdltSection::estimateBlobSize() const { return blobSize; } -size_t AdltSection::writeDtNeededVec( +template +size_t AdltSection::writeDtNeededVec( uint8_t* buff, const DtNeededsVec& neededVec) const { if (neededVec.empty()) return 0; @@ -4183,7 +4194,8 @@ size_t AdltSection::writeDtNeededVec( return needIndexes.size_in_bytes(); } -void AdltSection::writeTo(uint8_t* buf) { +template +void AdltSection::writeTo(uint8_t* buf) { // TODO: take care of endianness, use write32 / write64 etc. // pre-serialized SoData, enriched with offsets during blob writing SmallVector psods; @@ -4234,7 +4246,8 @@ void AdltSection::writeTo(uint8_t* buf) { } } -size_t AdltSection::getSize() const { +template +size_t AdltSection::getSize() const { const size_t pre_blob_size = sizeof(header) + sizeof(PSOD) * soInputs.size(); assert(pre_blob_size <= header.blobStart); return header.blobStart + header.blobSize; @@ -4333,3 +4346,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 fa97f89a307f..48edc79a718d 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -34,6 +34,7 @@ namespace elf { class Defined; struct PhdrEntry; class SymbolTableBaseSection; +template class SharedFileExtended; class SyntheticSection : public InputSection { public: @@ -1292,14 +1293,10 @@ struct AdltSectionHeader { Elf64_Xword blobSize; }; -// serialized blob structures - constexpr char BlobStartMark[4] = {0xA, 0xD, 0x1, 0x7}; -// fwd -class AdltInputInterface; - +template class AdltSection final : public SyntheticSection { public: struct SectionString { @@ -1318,11 +1315,12 @@ public: // will be serialized to PSOD struct SoData { - const AdltInputInterface* ifc; - SectionString soName; DtNeededsVec dtNeededs; + StringRef initArrayName; + StringRef finiArrayName; + OutputSection* initArraySec; OutputSection* finiArraySec; @@ -1348,7 +1346,7 @@ private: void extractInitFiniArray(); Elf64_Xword calculateHash(StringRef str) const; - SoData makeSoData(const AdltInputInterface*); + SoData makeSoData(const SharedFileExtended*); PSOD serialize(const SoData&) const; size_t estimateBlobSize() const; @@ -1441,9 +1439,7 @@ struct InStruct { std::unique_ptr strTab; std::unique_ptr symTab; std::unique_ptr symTabShndx; - std::unique_ptr adltData; - // TODO: research DT_SONAME and DT_NEEDED location in .dynstr - // TODO: replace with dynStrTab + std::unique_ptr adltData; std::unique_ptr adltStrTab; void reset(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 6834e6cebfa7..318a9bf2d86d 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -314,7 +314,7 @@ template void elf::createSyntheticSections() { if (config->adlt) { in.adltStrTab = std::make_unique(".adlt.strtab", false); - in.adltData = std::make_unique(*in.adltStrTab); + in.adltData = std::make_unique>(*in.adltStrTab); add(*in.adltStrTab); add(*in.adltData); } -- Gitee From 131becb0e32d87e9d3ab1e423709214a6d6d6ee7 Mon Sep 17 00:00:00 2001 From: Khomutov Nikita Date: Sat, 30 Mar 2024 16:23:32 +0300 Subject: [PATCH 5/5] review fixes: - remove unused macro - add assert on nullable file Signed-off-by: Khomutov Nikita Change-Id: I548d21be6efd2cfbc6ea13394883e48806c23a49 --- lld/ELF/SyntheticSections.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index d3b56395751d..a03781415d6b 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4002,8 +4002,6 @@ size_t PackageMetadataNote::getSize() const { // OHOS_LOCAL begin namespace lld { namespace elf { namespace adlt { -#define DEBUG_TYPE "lld-adlt-section" - template AdltSection::AdltSection(StringTableSection& strTabSec) : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") @@ -4093,6 +4091,7 @@ void AdltSection::extractInitFiniArray() { template typename AdltSection::SoData AdltSection::makeSoData(const SharedFileExtended* soext) { + assert(soext); SoData data = {}; StringRef soname = soext->soName; data.soName = SectionString{soname, strTabSec.addString(soname)}; @@ -4253,7 +4252,6 @@ size_t AdltSection::getSize() const { return header.blobStart + header.blobSize; } -#undef DEBUG_TYPE }}} // namespace lld::elf::adlt // OHOS_LOCAL end -- Gitee