From 7fa27ce4a07f19b07799a767fc29416f3b625afb Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 26 Jul 2023 21:03:47 +0200 Subject: Vendor import of llvm-project main llvmorg-17-init-19304-gd0b54bb50e51, the last commit before the upstream release/17.x branch was created. --- llvm/lib/Object/ELF.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 9 deletions(-) (limited to 'llvm/lib/Object/ELF.cpp') diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 81c9a097170d..0d1862e57371 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/ELF.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/DataExtractor.h" @@ -270,6 +271,11 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { case ELF::EM_RISCV: switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_RISCV_ATTRIBUTES); } break; + case ELF::EM_AARCH64: + switch (Type) { + STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC); + STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_MEMTAG_GLOBALS_STATIC); + } default: break; } @@ -307,6 +313,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP_V0); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_OFFLOADING); + STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LTO); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef); @@ -640,7 +647,26 @@ ELFFile::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const { template Expected> -ELFFile::decodeBBAddrMap(const Elf_Shdr &Sec) const { +ELFFile::decodeBBAddrMap(const Elf_Shdr &Sec, + const Elf_Shdr *RelaSec) const { + bool IsRelocatable = getHeader().e_type == ELF::ET_REL; + + // This DenseMap maps the offset of each function (the location of the + // reference to the function in the SHT_LLVM_BB_ADDR_MAP section) to the + // addend (the location of the function in the text section). + llvm::DenseMap FunctionOffsetTranslations; + if (IsRelocatable && RelaSec) { + assert(RelaSec && + "Can't read a SHT_LLVM_BB_ADDR_MAP section in a relocatable " + "object file without providing a relocation section."); + Expected Relas = this->relas(*RelaSec); + if (!Relas) + return createError("unable to read relocations for section " + + describe(*this, Sec) + ": " + + toString(Relas.takeError())); + for (Elf_Rela Rela : *Relas) + FunctionOffsetTranslations[Rela.r_offset] = Rela.r_addend; + } Expected> ContentsOrErr = getSectionContents(Sec); if (!ContentsOrErr) return ContentsOrErr.takeError(); @@ -650,6 +676,7 @@ ELFFile::decodeBBAddrMap(const Elf_Shdr &Sec) const { DataExtractor::Cursor Cur(0); Error ULEBSizeErr = Error::success(); + Error MetadataDecodeErr = Error::success(); // Helper to extract and decode the next ULEB128 value as uint32_t. // Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the uint32_t // limit. @@ -670,7 +697,8 @@ ELFFile::decodeBBAddrMap(const Elf_Shdr &Sec) const { }; uint8_t Version = 0; - while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) { + while (!ULEBSizeErr && !MetadataDecodeErr && Cur && + Cur.tell() < Content.size()) { if (Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) { Version = Data.getU8(Cur); if (!Cur) @@ -680,32 +708,97 @@ ELFFile::decodeBBAddrMap(const Elf_Shdr &Sec) const { Twine(static_cast(Version))); Data.getU8(Cur); // Feature byte } + uint64_t SectionOffset = Cur.tell(); uintX_t Address = static_cast(Data.getAddress(Cur)); + if (!Cur) + return Cur.takeError(); + if (IsRelocatable) { + assert(Address == 0); + auto FOTIterator = FunctionOffsetTranslations.find(SectionOffset); + if (FOTIterator == FunctionOffsetTranslations.end()) { + return createError("failed to get relocation data for offset: " + + Twine::utohexstr(SectionOffset) + " in section " + + describe(*this, Sec)); + } + Address = FOTIterator->second; + } uint32_t NumBlocks = ReadULEB128AsUInt32(); std::vector BBEntries; uint32_t PrevBBEndOffset = 0; for (uint32_t BlockIndex = 0; - !ULEBSizeErr && Cur && (BlockIndex < NumBlocks); ++BlockIndex) { + !MetadataDecodeErr && !ULEBSizeErr && Cur && (BlockIndex < NumBlocks); + ++BlockIndex) { uint32_t ID = Version >= 2 ? ReadULEB128AsUInt32() : BlockIndex; uint32_t Offset = ReadULEB128AsUInt32(); uint32_t Size = ReadULEB128AsUInt32(); - uint32_t Metadata = ReadULEB128AsUInt32(); + uint32_t MD = ReadULEB128AsUInt32(); if (Version >= 1) { // Offset is calculated relative to the end of the previous BB. Offset += PrevBBEndOffset; PrevBBEndOffset = Offset + Size; } - BBEntries.push_back({ID, Offset, Size, Metadata}); + Expected MetadataOrErr = + BBAddrMap::BBEntry::Metadata::decode(MD); + if (!MetadataOrErr) { + MetadataDecodeErr = MetadataOrErr.takeError(); + break; + } + BBEntries.push_back({ID, Offset, Size, *MetadataOrErr}); } FunctionEntries.push_back({Address, std::move(BBEntries)}); } - // Either Cur is in the error state, or ULEBSizeError is set (not both), but - // we join the two errors here to be safe. - if (!Cur || ULEBSizeErr) - return joinErrors(Cur.takeError(), std::move(ULEBSizeErr)); + // Either Cur is in the error state, or we have an error in ULEBSizeErr or + // MetadataDecodeErr (but not both), but we join all errors here to be safe. + if (!Cur || ULEBSizeErr || MetadataDecodeErr) + return joinErrors(joinErrors(Cur.takeError(), std::move(ULEBSizeErr)), + std::move(MetadataDecodeErr)); return FunctionEntries; } +template +Expected< + MapVector> +ELFFile::getSectionAndRelocations( + std::function(const Elf_Shdr &)> IsMatch) const { + MapVector SecToRelocMap; + Error Errors = Error::success(); + for (const Elf_Shdr &Sec : cantFail(this->sections())) { + Expected DoesSectionMatch = IsMatch(Sec); + if (!DoesSectionMatch) { + Errors = joinErrors(std::move(Errors), DoesSectionMatch.takeError()); + continue; + } + if (*DoesSectionMatch) { + if (SecToRelocMap.insert(std::make_pair(&Sec, (const Elf_Shdr *)nullptr)) + .second) + continue; + } + + if (Sec.sh_type != ELF::SHT_RELA && Sec.sh_type != ELF::SHT_REL) + continue; + + Expected RelSecOrErr = this->getSection(Sec.sh_info); + if (!RelSecOrErr) { + Errors = joinErrors(std::move(Errors), + createError(describe(*this, Sec) + + ": failed to get a relocated section: " + + toString(RelSecOrErr.takeError()))); + continue; + } + const Elf_Shdr *ContentsSec = *RelSecOrErr; + Expected DoesRelTargetMatch = IsMatch(*ContentsSec); + if (!DoesRelTargetMatch) { + Errors = joinErrors(std::move(Errors), DoesRelTargetMatch.takeError()); + continue; + } + if (*DoesRelTargetMatch) + SecToRelocMap[ContentsSec] = &Sec; + } + if(Errors) + return std::move(Errors); + return SecToRelocMap; +} + template class llvm::object::ELFFile; template class llvm::object::ELFFile; template class llvm::object::ELFFile; -- cgit v1.2.3