diff --git a/lld/ELF/ADLTSection.h b/lld/ELF/ADLTSection.h new file mode 100644 index 0000000000000000000000000000000000000000..74fc486005547d4a92e2193935768edf099bef86 --- /dev/null +++ b/lld/ELF/ADLTSection.h @@ -0,0 +1,106 @@ +//===- ADLTSection.h - ADLT Section data types --------------------*- C -*-===// +// +// Copyright (C) 2024 Huawei Device Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_ELF_ADLT_SECTION_H +#define LLD_ELF_ADLT_SECTION_H + +#ifdef __cplusplus +#include +namespace lld { +namespace elf { +namespace adlt { + +#else // __cplusplus +#include +#endif // __cplusplus + +// part of #include +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef uint8_t Elf64_Byte; + +typedef struct { + Elf64_Word secIndex; + Elf64_Off offset; // in-section offset from start +} adlt_cross_section_ref_t; + +typedef struct { + Elf64_Xword secIndex; + Elf64_Xword numElem; + Elf64_Addr addr; +} adlt_cross_section_vec_t; + +typedef struct { + Elf64_Half major: 6; + Elf64_Half minor: 6; + Elf64_Half patch: 4; +} adlt_semver_t; + +// DT_NEEDED string index with embedded PSOD index if available +typedef struct { + Elf64_Off hasInternalPSOD : 1; // true if soname + Elf64_Off PSODindex : 16; // PSOD in the current ADLT image + Elf64_Off sonameOffset : 47; // string start in bound .adlt.strtab +} adlt_dt_needed_index_t; + +typedef enum { + ADLT_HASH_TYPE_NONE = 0, + ADLT_HASH_TYPE_GNU_HASH = 1, + ADLT_HASH_TYPE_SYSV_HASH = 2, + ADLT_HASH_TYPE_DEBUG_CONST = 0xfe, + ADLT_HASH_TYPE_MAX = 0xff, +} adlt_hash_type_enum_t; + +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; // algorith according to header.stringHashType value + adlt_cross_section_vec_t initArray; + adlt_cross_section_vec_t finiArray; + Elf64_Off dtNeeded; // offset to adlt_dt_needed_index_t[] array in blob + Elf64_Xword dtNeededSz; + adlt_cross_section_ref_t sharedLocalSymbolIndex; + adlt_cross_section_ref_t sharedGlobalSymbolIndex; +} adlt_psod_t; + +typedef struct { + adlt_semver_t schemaVersion; // {major, minor, patch} + Elf64_Half schemaHeaderSize; // >= sizeof(adlt_section_header_t) if comp + Elf64_Half schemaPSODSize; // >= sizeof(adlt_psod_t) if compatible + Elf64_Half sharedObjectsNum; // number of PSOD entries + adlt_hash_type_t stringHashType; // contains adlt_hash_type_enum_t value + Elf64_Off blobStart; // offset of binary blob start relative to .adlt + Elf64_Xword blobSize; +} adlt_section_header_t; + +static const char adltBlobStartMark[4] = { 0xA, 0xD, 0x1, 0x7 }; + +static const adlt_semver_t adltSchemaVersion = {1, 0, 0}; + +#ifdef __cplusplus +} // namespace adlt +} // namespace elf +} // namespace lld +#endif // __cplusplus + +#endif // LLD_ELF_ADLT_SECTION_H diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 35f163c5d2ba8d06d19a732c1feaa737a64d46df..28d699a13f3b557ab87df492406de77578ef830e 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4001,6 +4001,34 @@ size_t PackageMetadataNote::getSize() const { // OHOS_LOCAL begin namespace lld { namespace elf { namespace adlt { +static_assert( + sizeof(SemanticVersion) == sizeof(Elf64_Half), + ".adlt semantic version is designed to occupy uint16_t" +); + +static_assert( + sizeof(DtNeededIndex) == sizeof(Elf64_Off), + "DtNeededIndex have to be an offset with intrused flags" +); + +static_assert( + sizeof(adlt_hash_type_t) == sizeof(Elf64_Byte), + "String hash type enum should occupy only one byte" +); + +static_assert(sizeof(adltBlobStartMark) == 4, + "0xad17 consist of 4 bytes" +); + +static_assert(sizeof(AdltSectionHeader) == 32, + "please udpate major version if header has been changed" +); + +static_assert(sizeof(PSOD) == 112, + "please udpate version if PSOD layout or content changed" +); + + template AdltSection::AdltSection(StringTableSection& strTabSec) : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") @@ -4023,12 +4051,13 @@ void AdltSection::finalizeContents() { 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 + adltSchemaVersion, // .schemaVersion + sizeof(AdltSectionHeader), // .schemaHeaderSize + sizeof(PSOD), // .schemaPSODSize + soNum, // .sharedObjectsNum + ADLT_HASH_TYPE_GNU_HASH, // .stringHashType + getBlobStartOffset(), // .blobStart + estimateBlobSize(), // .blobSize }; buildSonameIndex(); @@ -4117,12 +4146,12 @@ AdltSection::makeSoData(const SharedFileExtended* soext) { template Elf64_Xword AdltSection::calculateHash(StringRef str) const { - switch(header.stringHashType) { - case HashType::NONE: + switch(static_cast(header.stringHashType)) { + case ADLT_HASH_TYPE_NONE: return 0x0; - case HashType::MUSL_GNU_HASH: + case ADLT_HASH_TYPE_GNU_HASH: return hashGnu(str); - case HashType::DEBUG_CONST: + case ADLT_HASH_TYPE_DEBUG_CONST: return 0xdeadbeef1337c0de; default: llvm_unreachable(".adlt hash type not implemented"); @@ -4147,12 +4176,12 @@ PSOD AdltSection::serialize(const SoData& soData) const { 0x0, // .dtNeeded // filled by blob serialization soData.dtNeededs.size(), // .dtNeededSz CrossSectionRef { - 0, // .sectionIndex - soData.sharedLocalIndex, // .offsetFromStart + 0, // .secIndex + soData.sharedLocalIndex, // .offset }, // .sharedLocalSymbolIndex CrossSectionRef { - 0, // .sectionIndex - soData.sharedGlobalIndex, // .offsetFromStart + 0, // .secIndex + soData.sharedGlobalIndex, // .offset }, // .sharedGlobalSymbolIndex }; } @@ -4164,7 +4193,7 @@ Elf64_Off AdltSection::getBlobStartOffset() const { template size_t AdltSection::estimateBlobSize() const { - size_t blobSize = sizeof(BlobStartMark); + size_t blobSize = sizeof(adltBlobStartMark); for (const auto& soData: soInputs) { blobSize += sizeof(DtNeededIndex) * soData.dtNeededs.size(); @@ -4208,8 +4237,8 @@ void AdltSection::writeTo(uint8_t* buf) { { 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); + memcpy(blob_buf + blob_off, &adltBlobStartMark, sizeof(adltBlobStartMark)); + blob_off += sizeof(adltBlobStartMark); // dt-needed for(const auto& it : llvm::enumerate(soInputs)) { @@ -4246,8 +4275,7 @@ void AdltSection::writeTo(uint8_t* buf) { template size_t AdltSection::getSize() const { - const size_t pre_blob_size = sizeof(header) + sizeof(PSOD) * soInputs.size(); - assert(pre_blob_size <= header.blobStart); + assert(sizeof(header) + sizeof(PSOD) * soInputs.size() <= header.blobStart); return header.blobStart + header.blobSize; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 48edc79a718d6822273cc7843373aac5eafa8cb9..ebf03b332d4b4937b7d9dfdbfabbafcff5c61606 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -22,6 +22,7 @@ #include "Config.h" #include "EhFrame.h" // OHOS_LOCAL +#include "ADLTSection.h" // OHOS_LOCAL #include "InputSection.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" @@ -1224,76 +1225,13 @@ public: 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; -}; - -constexpr char BlobStartMark[4] = {0xA, 0xD, 0x1, 0x7}; +using CrossSectionRef = adlt_cross_section_ref_t; +using CrossSectionVec = adlt_cross_section_vec_t; +using SemanticVersion = adlt_semver_t; +using DtNeededIndex = adlt_dt_needed_index_t; +using PSOD = adlt_psod_t; +using AdltSectionHeader = adlt_section_header_t; +using HashType = adlt_hash_type_enum_t; template