diff --git a/lld/ELF/ADLTSection.h b/lld/ELF/ADLTSection.h index 3441ddb8af2947da4b3cac8ec5b44d0a74f87184..1327de5950ecc432aae70879c08289453ab2bb8d 100644 --- a/lld/ELF/ADLTSection.h +++ b/lld/ELF/ADLTSection.h @@ -29,6 +29,7 @@ namespace adlt { #include #endif // __cplusplus +#ifndef _ELF_H // part of #include typedef uint16_t Elf64_Half; typedef uint64_t Elf64_Off; @@ -36,6 +37,7 @@ typedef uint64_t Elf64_Addr; typedef uint32_t Elf64_Word; typedef uint64_t Elf64_Xword; typedef uint8_t Elf64_Byte; +#endif // _ELF_H typedef struct { Elf64_Word secIndex; @@ -66,12 +68,18 @@ typedef struct { } adlt_semver_t; // DT_NEEDED string index with embedded PSOD index if available -typedef struct { +typedef struct { Elf64_Off hasInternalPSOD : 1; // true if soname Elf64_Off PSODindex : 16; // PSOD in the current ADLT image Elf64_Off sonameOffset : 47; // string start in bound .adlt.strtab } adlt_dt_needed_index_t; +typedef struct { + Elf64_Word relType; // relocation type + Elf64_Word count; // segment length + Elf64_Off startOffset; // segment start offset in .rela.dyn +} adlt_relocations_segment_t; + typedef enum { ADLT_HASH_TYPE_NONE = 0, ADLT_HASH_TYPE_GNU_HASH = 1, @@ -85,13 +93,15 @@ typedef uint8_t adlt_hash_type_t; // Serializable representation per-shared-object-data in .adlt section typedef struct { Elf64_Off soName; // offset in .adlt.strtab - Elf64_Xword soNameHash; // algorithm according to header.stringHashType value + Elf64_Xword soNameHash; // algorithm according to hdr.stringHashType value adlt_cross_section_array_t initArray; adlt_cross_section_array_t finiArray; adlt_blob_array_t dtNeeded; // array of adlt_dt_needed_index_t[] elems adlt_cross_section_ref_t sharedLocalSymbolIndex; adlt_cross_section_ref_t sharedGlobalSymbolIndex; - adlt_blob_u16_array_t phIndexes; // program header index array, typeof(e_phnum) + adlt_blob_u16_array_t phIndexes; // program header indexes, typeof(e_phnum) + adlt_blob_array_t relaDynSegs; // lib's adlt_relocations_segment_t[] + adlt_blob_array_t relaPltSegs; // lib's adlt_relocations_segment_t[] } adlt_psod_t; typedef struct { @@ -103,6 +113,8 @@ 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_array_t relaDynSegs; // common adlt_relocations_segment_t[] + adlt_blob_array_t relaPltSegs; // common adlt_relocations_segment_t[] } adlt_section_header_t; static const char adltBlobStartMark[4] = { 0xA, 0xD, 0x1, 0x7 }; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2e22043920087ea9c2a355d6299fba1b4ea19f3f..33ae89538d5645552d32de40a8d0b9c3974ef343 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4011,20 +4011,30 @@ static_assert( "adlt_dt_needed_index_t have to be an offset with intrused flags" ); +static_assert( + sizeof(adlt_relocations_segment_t) == 16, + "adlt_relocations_segment_t size is 16 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) == 40, - "please udpate version if header has been changed" +static_assert(sizeof(adlt_section_header_t) == 72, + "please update version if header has been changed" ); -static_assert(sizeof(adlt_psod_t) == 128, +static_assert(sizeof(adlt_psod_t) == 160, "please udpate version if adlt_psod_t layout or content changed" ); @@ -4050,6 +4060,8 @@ void AdltSection::finalizeContents() { "the number of input libs exeeds ELF limit on number of sections"); const Elf64_Half soNum = soInputs.size(); + common = makeCommonData(); + header = adlt_section_header_t{ adltSchemaVersion, // .schemaVersion sizeof(adlt_section_header_t), // .schemaHeaderSize @@ -4059,6 +4071,8 @@ void AdltSection::finalizeContents() { getBlobStartOffset(), // .blobStart estimateBlobSize(), // .blobSize 0, // .overallMappedSize + {0, 0}, // .relaDynSegs, filled in writeTo + {0, 0}, // .relaPltSegs, filled in writeTo }; // TODO: estimate and fill overallMappedSize @@ -4119,6 +4133,18 @@ void AdltSection::extractInitFiniArray() { } } +template +typename AdltSection::CommonData +AdltSection::makeCommonData() { + // TODO: fill relaDynSegs + // TODO: fill relaPltSegs + + return CommonData { + {}, // .relaDynSegs + {}, // .relaPltSegs + }; +} + template typename AdltSection::SoData AdltSection::makeSoData(const SharedFileExtended* soext) { @@ -4139,6 +4165,8 @@ AdltSection::makeSoData(const SharedFileExtended* soext) { // TODO: fill data.sharedLocalIndex // TODO: fill data.sharedGlobalIndex + // TODO: fill data.relaDynSegs + // TODO: fill data.relaPltSegs std::copy(soext->programHeaderIndexes.begin(), soext->programHeaderIndexes.end(), @@ -4170,27 +4198,18 @@ adlt_psod_t AdltSection::serialize(const SoData& soData) const { soData.initArraySec->sectionIndex, 0x0, // .init_array function addresses are located at the start soData.initArraySec->size, // size - } : adlt_cross_section_array_t{0, 0, 0}, + } : 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{0, 0, 0}, - adlt_blob_array_t { // .dtNeeded - 0x0, // offset, filled array write in blob - soData.dtNeededs.size() * sizeof(adlt_dt_needed_index_t) - }, - adlt_cross_section_ref_t { // .sharedLocalSymbolIndex - 0, // .secIndex // TODO: dynsym? - soData.sharedLocalIndex, // .offset - }, - adlt_cross_section_ref_t { // .sharedGlobalSymbolIndex - 0, // .secIndex // TODO: dynsym? - soData.sharedGlobalIndex, // .offset - }, - adlt_blob_u16_array_t { // .phIndexes - 0x0, 0 - } + } : adlt_cross_section_array_t{}, + adlt_blob_array_t {}, // .dtNeeded, filled in writeTo + adlt_cross_section_ref_t {}, // .sharedLocalSymbolIndex TODO + adlt_cross_section_ref_t {}, // .sharedGlobalSymbolIndex TOOD + adlt_blob_u16_array_t {}, // .phIndexes, filled in writeTo + adlt_blob_array_t {}, // .relaDynSegs, filled in writeTo + adlt_blob_array_t {}, // .relaPltSegs, filled in writeTo }; } @@ -4206,15 +4225,32 @@ size_t AdltSection::estimateBlobSize() const { for (const auto& soData: soInputs) { blobSize += sizeof(adlt_dt_needed_index_t) * soData.dtNeededs.size(); blobSize += sizeof(uint16_t) * soData.phIndexes.size(); + blobSize += sizeof(adlt_relocations_segment_t) * soData.relaDynSegs.size(); + blobSize += sizeof(adlt_relocations_segment_t) * soData.relaPltSegs.size(); }; + blobSize += sizeof(adlt_relocations_segment_t) * common.relaDynSegs.size(); + blobSize += sizeof(adlt_relocations_segment_t) * common.relaPltSegs.size(); + return blobSize; } template -size_t AdltSection::writeDtNeededVec( - uint8_t* buff, const DtNeededsVec& neededVec) const { - if (neededVec.empty()) return 0; +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 +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()); @@ -4226,8 +4262,7 @@ size_t AdltSection::writeDtNeededVec( }); } - memcpy(buff, needIndexes.data(), needIndexes.size_in_bytes()); - return needIndexes.size_in_bytes(); + return writeArray(buff, offset, needIndexes); } template @@ -4244,39 +4279,42 @@ void AdltSection::writeTo(uint8_t* buf) { // serialize blob data { - uint8_t* const blob_buf = buf + header.blobStart; - size_t blob_off = 0; - memcpy(blob_buf + blob_off, &adltBlobStartMark, sizeof(adltBlobStartMark)); - blob_off += sizeof(adltBlobStartMark); + uint8_t* const blobBuf = buf + header.blobStart; + size_t blobOff = 0; + memcpy(blobBuf + blobOff, &adltBlobStartMark, sizeof(adltBlobStartMark)); + blobOff += sizeof(adltBlobStartMark); - // dt-needed + // psod-related data for(const auto& it : llvm::enumerate(soInputs)) { - const SoData& soData = it.value(); - adlt_psod_t& psod = psods[it.index()]; + 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; - const size_t written = writeDtNeededVec(blob_buf + blob_off, soData.dtNeededs); - psod.dtNeeded.offset = blob_off; - psod.dtNeeded.size = written; - blob_off += written; + psod.relaDynSegs = writeArray(blobBuf, blobOff, soData.relaDynSegs); + blobOff += psod.relaDynSegs.size; + + psod.relaPltSegs = writeArray(blobBuf, blobOff, soData.relaPltSegs); + blobOff += psod.relaPltSegs.size; } - // phIndexes - for (const auto& it : llvm::enumerate(soInputs)) { - const SoData& soData = it.value(); - adlt_psod_t& psod = psods[it.index()]; + // common data + { + header.relaDynSegs = writeArray(blobBuf, blobOff, common.relaDynSegs); + blobOff += header.relaDynSegs.size; - const size_t written = soData.phIndexes.size_in_bytes();; - memcpy(blob_buf + blob_off, - soData.phIndexes.data(), soData.phIndexes.size_in_bytes()); - psod.phIndexes.offset = blob_off; - psod.phIndexes.size = written; - blob_off += written; + header.relaPltSegs = writeArray(blobBuf, blobOff, common.relaPltSegs); + blobOff += header.relaPltSegs.size; } // finalize header.blobSize - assert((blob_off <= header.blobSize) && + assert((blobOff <= header.blobSize) && ".adlt-section: blob output exeeds its initial estimation"); - header.blobSize = blob_off; + header.blobSize = blobOff; } // header diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 8292495940fac85a81f33b24ad2a4a9147506155..c69b95704406e06fcdcad81c394021cff0bcc911 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1257,6 +1257,14 @@ public: Elf64_Off sharedGlobalIndex; // TODO SmallVector phIndexes; // TODO + SmallVector relaDynSegs; // TODO + SmallVector relaPltSegs; // TODO + }; + + // will be used to form some header data + struct CommonData { + SmallVector relaDynSegs; // TODO + SmallVector relaPltSegs; // TODO }; public: @@ -1275,18 +1283,29 @@ private: void linkInternalDtNeeded(); void extractInitFiniArray(); - Elf64_Xword calculateHash(StringRef str) const; + CommonData makeCommonData(); SoData makeSoData(const SharedFileExtended*); + + Elf64_Xword calculateHash(StringRef str) const; adlt_psod_t serialize(const SoData&) const; size_t estimateBlobSize() const; - size_t writeDtNeededVec(uint8_t* buff, const DtNeededsVec& neededVec) const; + + template + adlt_blob_array_t writeArray(uint8_t* buff, size_t offset, + const SmallVector& data); + + adlt_blob_array_t writeDtNeeded(uint8_t* buff, size_t offset, + const DtNeededsVec& neededVec); private: StringTableSection& strTabSec; adlt_section_header_t header = {}; - SmallVector soInputs; + + CommonData common = {}; + SmallVector soInputs; + llvm::DenseMap sonameToIndexMap; };