diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object')
23 files changed, 1147 insertions, 218 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/Archive.cpp b/contrib/llvm-project/llvm/lib/Object/Archive.cpp index 1dffe007b9a9..2cf924123888 100644 --- a/contrib/llvm-project/llvm/lib/Object/Archive.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Archive.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/Archive.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -136,8 +135,11 @@ BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent, return; ErrorAsOutParameter ErrAsOutParam(Err); - if (Size < getSizeOf()) - *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size); + if (Size < getSizeOf()) { + Error SubErr = createMemberHeaderParseError(this, RawHeaderPtr, Size); + if (Err) + *Err = std::move(SubErr); + } } // This gets the raw name from the ArMemHdr->Name field and checks that it is @@ -1142,7 +1144,7 @@ uint32_t Archive::getNumberOfSymbols() const { return read32le(buf); } -Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const { +Expected<std::optional<Archive::Child>> Archive::findSym(StringRef name) const { Archive::symbol_iterator bs = symbol_begin(); Archive::symbol_iterator es = symbol_end(); @@ -1155,7 +1157,7 @@ Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const { return MemberOrErr.takeError(); } } - return Optional<Child>(); + return std::nullopt; } // Returns true if archive file contains no member file. diff --git a/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp b/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp index dbf5052cdac0..0d3aad658fe4 100644 --- a/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp @@ -598,8 +598,8 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, if (NeedSymbols) { Expected<std::vector<unsigned>> SymbolsOrErr = getSymbols(Buf, SymNames, HasObject); - if (auto E = SymbolsOrErr.takeError()) - return std::move(E); + if (!SymbolsOrErr) + return createFileError(M.MemberName, SymbolsOrErr.takeError()); Symbols = std::move(*SymbolsOrErr); } diff --git a/contrib/llvm-project/llvm/lib/Object/Binary.cpp b/contrib/llvm-project/llvm/lib/Object/Binary.cpp index 8065e3eb1d85..d18aed8b3b8c 100644 --- a/contrib/llvm-project/llvm/lib/Object/Binary.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Binary.cpp @@ -67,6 +67,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, case file_magic::macho_dynamically_linked_shared_lib_stub: case file_magic::macho_dsym_companion: case file_magic::macho_kext_bundle: + case file_magic::macho_file_set: case file_magic::coff_object: case file_magic::coff_import_library: case file_magic::pecoff_executable: diff --git a/contrib/llvm-project/llvm/lib/Object/BuildID.cpp b/contrib/llvm-project/llvm/lib/Object/BuildID.cpp new file mode 100644 index 000000000000..795c22e769aa --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Object/BuildID.cpp @@ -0,0 +1,93 @@ +//===- llvm/Object/BuildID.cpp - Build ID ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines a library for handling Build IDs and using them to find +/// debug info. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/BuildID.h" + +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +namespace llvm { +namespace object { + +namespace { + +template <typename ELFT> +std::optional<BuildIDRef> getBuildID(const ELFFile<ELFT> &Obj) { + auto PhdrsOrErr = Obj.program_headers(); + if (!PhdrsOrErr) { + consumeError(PhdrsOrErr.takeError()); + return {}; + } + for (const auto &P : *PhdrsOrErr) { + if (P.p_type != ELF::PT_NOTE) + continue; + Error Err = Error::success(); + for (auto N : Obj.notes(P, Err)) + if (N.getType() == ELF::NT_GNU_BUILD_ID && + N.getName() == ELF::ELF_NOTE_GNU) + return N.getDesc(); + consumeError(std::move(Err)); + } + return {}; +} + +} // namespace + +std::optional<BuildIDRef> getBuildID(const ObjectFile *Obj) { + if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Obj)) + return getBuildID(O->getELFFile()); + if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Obj)) + return getBuildID(O->getELFFile()); + if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Obj)) + return getBuildID(O->getELFFile()); + if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Obj)) + return getBuildID(O->getELFFile()); + return std::nullopt; +} + +std::optional<std::string> BuildIDFetcher::fetch(BuildIDRef BuildID) const { + auto GetDebugPath = [&](StringRef Directory) { + SmallString<128> Path{Directory}; + sys::path::append(Path, ".build-id", + llvm::toHex(BuildID[0], /*LowerCase=*/true), + llvm::toHex(BuildID.slice(1), /*LowerCase=*/true)); + Path += ".debug"; + return Path; + }; + if (DebugFileDirectories.empty()) { + SmallString<128> Path = GetDebugPath( +#if defined(__NetBSD__) + // Try /usr/libdata/debug/.build-id/../... + "/usr/libdata/debug" +#else + // Try /usr/lib/debug/.build-id/../... + "/usr/lib/debug" +#endif + ); + if (llvm::sys::fs::exists(Path)) + return std::string(Path); + } else { + for (const auto &Directory : DebugFileDirectories) { + // Try <debug-file-directory>/.build-id/../... + SmallString<128> Path = GetDebugPath(Directory); + if (llvm::sys::fs::exists(Path)) + return std::string(Path); + } + } + return std::nullopt; +} + +} // namespace object +} // namespace llvm diff --git a/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp index 91ecea11511d..7090d3ca5618 100644 --- a/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp @@ -38,6 +38,7 @@ static bool is32bit(MachineTypes Machine) { default: llvm_unreachable("unsupported machine"); case IMAGE_FILE_MACHINE_ARM64: + case IMAGE_FILE_MACHINE_ARM64EC: case IMAGE_FILE_MACHINE_AMD64: return false; case IMAGE_FILE_MACHINE_ARMNT: @@ -55,6 +56,7 @@ static uint16_t getImgRelRelocation(MachineTypes Machine) { case IMAGE_FILE_MACHINE_ARMNT: return IMAGE_REL_ARM_ADDR32NB; case IMAGE_FILE_MACHINE_ARM64: + case IMAGE_FILE_MACHINE_ARM64EC: return IMAGE_REL_ARM64_ADDR32NB; case IMAGE_FILE_MACHINE_I386: return IMAGE_REL_I386_DIR32NB; diff --git a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp index 1a4bb329201a..b159ae1bba14 100644 --- a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp @@ -1014,6 +1014,8 @@ StringRef COFFObjectFile::getFileFormatName() const { return "COFF-ARM"; case COFF::IMAGE_FILE_MACHINE_ARM64: return "COFF-ARM64"; + case COFF::IMAGE_FILE_MACHINE_ARM64EC: + return "COFF-ARM64EC"; default: return "COFF-<unknown arch>"; } @@ -1028,6 +1030,7 @@ Triple::ArchType COFFObjectFile::getArch() const { case COFF::IMAGE_FILE_MACHINE_ARMNT: return Triple::thumb; case COFF::IMAGE_FILE_MACHINE_ARM64: + case COFF::IMAGE_FILE_MACHINE_ARM64EC: return Triple::aarch64; default: return Triple::UnknownArch; @@ -1131,7 +1134,7 @@ COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { "Aux Symbol data did not point to the beginning of a symbol"); #endif } - return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); + return ArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); } uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { @@ -1196,7 +1199,7 @@ Error COFFObjectFile::getSectionContents(const coff_section *Sec, uint32_t SectionSize = getSectionSize(Sec); if (Error E = checkOffset(Data, ConStart, SectionSize)) return E; - Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); + Res = ArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); return Error::success(); } @@ -1314,6 +1317,7 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { } break; case COFF::IMAGE_FILE_MACHINE_ARM64: + case COFF::IMAGE_FILE_MACHINE_ARM64EC: switch (Type) { LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); @@ -1896,6 +1900,7 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB; break; case COFF::IMAGE_FILE_MACHINE_ARM64: + case COFF::IMAGE_FILE_MACHINE_ARM64EC: RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB; break; default: diff --git a/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp b/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp index ca859c1f69ae..4d8f261fe4cc 100644 --- a/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp +++ b/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp @@ -9,6 +9,7 @@ #include "llvm/Object/DXContainer.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Object/Error.h" +#include "llvm/Support/FormatVariadic.h" using namespace llvm; using namespace llvm::object; @@ -31,16 +32,21 @@ static Error readStruct(StringRef Buffer, const char *Src, T &Struct) { } template <typename T> -static Error readInteger(StringRef Buffer, const char *Src, T &Val) { - static_assert(std::is_integral<T>::value, +static Error readInteger(StringRef Buffer, const char *Src, T &Val, + Twine Str = "structure") { + static_assert(std::is_integral_v<T>, "Cannot call readInteger on non-integral type."); - assert(reinterpret_cast<uintptr_t>(Src) % alignof(T) == 0 && - "Unaligned read of value from buffer!"); // Don't read before the beginning or past the end of the file if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end()) - return parseFailed("Reading structure out of file bounds"); + return parseFailed(Twine("Reading ") + Str + " out of file bounds"); - Val = *reinterpret_cast<const T *>(Src); + // The DXContainer offset table is comprised of uint32_t values but not padded + // to a 64-bit boundary. So Parts may start unaligned if there is an odd + // number of parts and part data itself is not required to be padded. + if (reinterpret_cast<uintptr_t>(Src) % alignof(T) != 0) + memcpy(reinterpret_cast<char *>(&Val), Src, sizeof(T)); + else + Val = *reinterpret_cast<const T *>(Src); // DXContainer is always little endian if (sys::IsBigEndianHost) sys::swapByteOrder(Val); @@ -53,39 +59,90 @@ Error DXContainer::parseHeader() { return readStruct(Data.getBuffer(), Data.getBuffer().data(), Header); } -Error DXContainer::parseDXILHeader(uint32_t Offset) { +Error DXContainer::parseDXILHeader(StringRef Part) { if (DXIL) return parseFailed("More than one DXIL part is present in the file"); - const char *Current = Data.getBuffer().data() + Offset; + const char *Current = Part.begin(); dxbc::ProgramHeader Header; - if (Error Err = readStruct(Data.getBuffer(), Current, Header)) + if (Error Err = readStruct(Part, Current, Header)) return Err; Current += offsetof(dxbc::ProgramHeader, Bitcode) + Header.Bitcode.Offset; DXIL.emplace(std::make_pair(Header, Current)); return Error::success(); } +Error DXContainer::parseShaderFlags(StringRef Part) { + if (ShaderFlags) + return parseFailed("More than one SFI0 part is present in the file"); + uint64_t FlagValue = 0; + if (Error Err = readInteger(Part, Part.begin(), FlagValue)) + return Err; + ShaderFlags = FlagValue; + return Error::success(); +} + +Error DXContainer::parseHash(StringRef Part) { + if (Hash) + return parseFailed("More than one HASH part is present in the file"); + dxbc::ShaderHash ReadHash; + if (Error Err = readStruct(Part, Part.begin(), ReadHash)) + return Err; + Hash = ReadHash; + return Error::success(); +} + Error DXContainer::parsePartOffsets() { + uint32_t LastOffset = + sizeof(dxbc::Header) + (Header.PartCount * sizeof(uint32_t)); const char *Current = Data.getBuffer().data() + sizeof(dxbc::Header); for (uint32_t Part = 0; Part < Header.PartCount; ++Part) { uint32_t PartOffset; if (Error Err = readInteger(Data.getBuffer(), Current, PartOffset)) return Err; + if (PartOffset < LastOffset) + return parseFailed( + formatv( + "Part offset for part {0} begins before the previous part ends", + Part) + .str()); Current += sizeof(uint32_t); - // We need to ensure that each part offset leaves enough space for a part - // header. To prevent overflow, we subtract the part header size from the - // buffer size, rather than adding to the offset. Since the file header is - // larger than the part header we can't reach this code unless the buffer - // is larger than the part header, so this can't underflow. - if (PartOffset > Data.getBufferSize() - sizeof(dxbc::PartHeader)) + if (PartOffset >= Data.getBufferSize()) return parseFailed("Part offset points beyond boundary of the file"); + // To prevent overflow when reading the part name, we subtract the part name + // size from the buffer size, rather than adding to the offset. Since the + // file header is larger than the part header we can't reach this code + // unless the buffer is at least as large as a part header, so this + // subtraction can't underflow. + if (PartOffset >= Data.getBufferSize() - sizeof(dxbc::PartHeader::Name)) + return parseFailed("File not large enough to read part name"); PartOffsets.push_back(PartOffset); - // If this isn't a dxil part stop here... - if (Data.getBuffer().substr(PartOffset, 4) != "DXIL") - continue; - if (Error Err = parseDXILHeader(PartOffset + sizeof(dxbc::PartHeader))) + dxbc::PartType PT = + dxbc::parsePartType(Data.getBuffer().substr(PartOffset, 4)); + uint32_t PartDataStart = PartOffset + sizeof(dxbc::PartHeader); + uint32_t PartSize; + if (Error Err = readInteger(Data.getBuffer(), + Data.getBufferStart() + PartOffset + 4, + PartSize, "part size")) return Err; + StringRef PartData = Data.getBuffer().substr(PartDataStart, PartSize); + LastOffset = PartOffset + PartSize; + switch (PT) { + case dxbc::PartType::DXIL: + if (Error Err = parseDXILHeader(PartData)) + return Err; + break; + case dxbc::PartType::SFI0: + if (Error Err = parseShaderFlags(PartData)) + return Err; + break; + case dxbc::PartType::HASH: + if (Error Err = parseHash(PartData)) + return Err; + break; + case dxbc::PartType::Unknown: + break; + } } return Error::success(); } diff --git a/contrib/llvm-project/llvm/lib/Object/Decompressor.cpp b/contrib/llvm-project/llvm/lib/Object/Decompressor.cpp index 3842ec92ccfc..f38c0e69e850 100644 --- a/contrib/llvm-project/llvm/lib/Object/Decompressor.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Decompressor.cpp @@ -19,11 +19,8 @@ using namespace object; Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit) { - if (!compression::zlib::isAvailable()) - return createError("zlib is not available"); - Decompressor D(Data); - if (Error Err = D.consumeCompressedZLibHeader(Is64Bit, IsLE)) + if (Error Err = D.consumeCompressedHeader(Is64Bit, IsLE)) return std::move(Err); return D; } @@ -31,8 +28,7 @@ Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data, Decompressor::Decompressor(StringRef Data) : SectionData(Data), DecompressedSize(0) {} -Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, - bool IsLittleEndian) { +Error Decompressor::consumeCompressedHeader(bool Is64Bit, bool IsLittleEndian) { using namespace ELF; uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr); if (SectionData.size() < HdrSize) @@ -40,10 +36,21 @@ Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, DataExtractor Extractor(SectionData, IsLittleEndian, 0); uint64_t Offset = 0; - if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) - : sizeof(Elf32_Word)) != - ELFCOMPRESS_ZLIB) - return createError("unsupported compression type"); + auto ChType = Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) + : sizeof(Elf32_Word)); + switch (ChType) { + case ELFCOMPRESS_ZLIB: + CompressionType = DebugCompressionType::Zlib; + break; + case ELFCOMPRESS_ZSTD: + CompressionType = DebugCompressionType::Zstd; + break; + default: + return createError("unsupported compression type (" + Twine(ChType) + ")"); + } + if (const char *Reason = llvm::compression::getReasonIfUnsupported( + compression::formatFor(CompressionType))) + return createError(Reason); // Skip Elf64_Chdr::ch_reserved field. if (Is64Bit) @@ -55,8 +62,8 @@ Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, return Error::success(); } -Error Decompressor::decompress(MutableArrayRef<uint8_t> Buffer) { - size_t Size = Buffer.size(); - return compression::zlib::uncompress(arrayRefFromStringRef(SectionData), - Buffer.data(), Size); +Error Decompressor::decompress(MutableArrayRef<uint8_t> Output) { + return compression::decompress(CompressionType, + arrayRefFromStringRef(SectionData), + Output.data(), Output.size()); } diff --git a/contrib/llvm-project/llvm/lib/Object/ELF.cpp b/contrib/llvm-project/llvm/lib/Object/ELF.cpp index 0d5aa91c1348..81c9a097170d 100644 --- a/contrib/llvm-project/llvm/lib/Object/ELF.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ELF.cpp @@ -173,6 +173,13 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, break; } break; + case ELF::EM_XTENSA: + switch (Type) { +#include "llvm/BinaryFormat/ELFRelocs/Xtensa.def" + default: + break; + } + break; default: break; } @@ -223,6 +230,8 @@ uint32_t llvm::object::getELFRelativeRelocationType(uint32_t Machine) { break; case ELF::EM_BPF: break; + case ELF::EM_LOONGARCH: + return ELF::R_LARCH_RELATIVE; default: break; } @@ -540,9 +549,8 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { for (const Elf_Phdr &Phdr : *ProgramHeadersOrError) { if (Phdr.p_type == ELF::PT_DYNAMIC) { - Dyn = makeArrayRef( - reinterpret_cast<const Elf_Dyn *>(base() + Phdr.p_offset), - Phdr.p_filesz / sizeof(Elf_Dyn)); + Dyn = ArrayRef(reinterpret_cast<const Elf_Dyn *>(base() + Phdr.p_offset), + Phdr.p_filesz / sizeof(Elf_Dyn)); break; } } @@ -667,7 +675,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const { Version = Data.getU8(Cur); if (!Cur) break; - if (Version > 1) + if (Version > 2) return createError("unsupported SHT_LLVM_BB_ADDR_MAP version: " + Twine(static_cast<int>(Version))); Data.getU8(Cur); // Feature byte @@ -676,8 +684,9 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const { uint32_t NumBlocks = ReadULEB128AsUInt32(); std::vector<BBAddrMap::BBEntry> BBEntries; uint32_t PrevBBEndOffset = 0; - for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks); - ++BlockID) { + for (uint32_t BlockIndex = 0; + !ULEBSizeErr && Cur && (BlockIndex < NumBlocks); ++BlockIndex) { + uint32_t ID = Version >= 2 ? ReadULEB128AsUInt32() : BlockIndex; uint32_t Offset = ReadULEB128AsUInt32(); uint32_t Size = ReadULEB128AsUInt32(); uint32_t Metadata = ReadULEB128AsUInt32(); @@ -686,7 +695,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const { Offset += PrevBBEndOffset; PrevBBEndOffset = Offset + Size; } - BBEntries.push_back({Offset, Size, Metadata}); + BBEntries.push_back({ID, Offset, Size, Metadata}); } FunctionEntries.push_back({Address, std::move(BBEntries)}); } diff --git a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp index 1f342e55e77f..ebc57bd04be7 100644 --- a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp @@ -25,10 +25,12 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" +#include "llvm/Support/RISCVISAInfo.h" #include <algorithm> #include <cstddef> #include <cstdint> #include <memory> +#include <optional> #include <string> #include <utility> @@ -165,14 +167,14 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { // both ARMv7-M and R have to support thumb hardware div bool isV7 = false; - Optional<unsigned> Attr = + std::optional<unsigned> Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); if (Attr) - isV7 = Attr.value() == ARMBuildAttrs::v7; + isV7 = *Attr == ARMBuildAttrs::v7; Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { case ARMBuildAttrs::ApplicationProfile: Features.AddFeature("aclass"); break; @@ -191,7 +193,7 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { Attr = Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -206,7 +208,7 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { Attr = Attributes.getAttributeValue(ARMBuildAttrs::FP_arch); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -230,7 +232,7 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { Attr = Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -249,7 +251,7 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { Attr = Attributes.getAttributeValue(ARMBuildAttrs::MVE_arch); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { default: break; case ARMBuildAttrs::Not_Allowed: @@ -268,7 +270,7 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { Attr = Attributes.getAttributeValue(ARMBuildAttrs::DIV_use); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { default: break; case ARMBuildAttrs::DisallowDIV: @@ -285,7 +287,7 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { return Features; } -SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { +Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const { SubtargetFeatures Features; unsigned PlatformFlags = getPlatformFlags(); @@ -293,55 +295,56 @@ SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const { Features.AddFeature("c"); } - // Add features according to the ELF attribute section. - // If there are any unrecognized features, ignore them. RISCVAttributeParser Attributes; if (Error E = getBuildAttributes(Attributes)) { - // TODO Propagate Error. - consumeError(std::move(E)); - return Features; // Keep "c" feature if there is one in PlatformFlags. + return std::move(E); } - Optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); + std::optional<StringRef> Attr = + Attributes.getAttributeString(RISCVAttrs::ARCH); if (Attr) { - // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)* - // Version string pattern is (major)p(minor). Major and minor are optional. - // For example, a version number could be 2p0, 2, or p92. - StringRef Arch = *Attr; - if (Arch.consume_front("rv32")) + // Suppress version checking for experimental extensions to prevent erroring + // when getting any unknown version of experimental extension. + auto ParseResult = RISCVISAInfo::parseArchString( + *Attr, /*EnableExperimentalExtension=*/true, + /*ExperimentalExtensionVersionCheck=*/false, + /*IgnoreUnknown=*/true); + if (!ParseResult) + return ParseResult.takeError(); + auto &ISAInfo = *ParseResult; + + if (ISAInfo->getXLen() == 32) Features.AddFeature("64bit", false); - else if (Arch.consume_front("rv64")) + else if (ISAInfo->getXLen() == 64) Features.AddFeature("64bit"); + else + llvm_unreachable("XLEN should be 32 or 64."); - while (!Arch.empty()) { - switch (Arch[0]) { - default: - break; // Ignore unexpected features. - case 'i': - Features.AddFeature("e", false); - break; - case 'd': - Features.AddFeature("f"); // D-ext will imply F-ext. - LLVM_FALLTHROUGH; - case 'e': - case 'm': - case 'a': - case 'f': - case 'c': - Features.AddFeature(Arch.take_front()); - break; - } - - // FIXME: Handle version numbers. - Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; }); - Arch = Arch.drop_while([](char c) { return c == '_'; }); - } + Features.addFeaturesVector(ISAInfo->toFeatureVector()); + } + + return Features; +} + +SubtargetFeatures ELFObjectFileBase::getLoongArchFeatures() const { + SubtargetFeatures Features; + + switch (getPlatformFlags() & ELF::EF_LOONGARCH_ABI_MODIFIER_MASK) { + case ELF::EF_LOONGARCH_ABI_SOFT_FLOAT: + break; + case ELF::EF_LOONGARCH_ABI_DOUBLE_FLOAT: + Features.AddFeature("d"); + // D implies F according to LoongArch ISA spec. + [[fallthrough]]; + case ELF::EF_LOONGARCH_ABI_SINGLE_FLOAT: + Features.AddFeature("f"); + break; } return Features; } -SubtargetFeatures ELFObjectFileBase::getFeatures() const { +Expected<SubtargetFeatures> ELFObjectFileBase::getFeatures() const { switch (getEMachine()) { case ELF::EM_MIPS: return getMIPSFeatures(); @@ -349,19 +352,21 @@ SubtargetFeatures ELFObjectFileBase::getFeatures() const { return getARMFeatures(); case ELF::EM_RISCV: return getRISCVFeatures(); + case ELF::EM_LOONGARCH: + return getLoongArchFeatures(); default: return SubtargetFeatures(); } } -Optional<StringRef> ELFObjectFileBase::tryGetCPUName() const { +std::optional<StringRef> ELFObjectFileBase::tryGetCPUName() const { switch (getEMachine()) { case ELF::EM_AMDGPU: return getAMDGPUCPUName(); case ELF::EM_PPC64: return StringRef("future"); default: - return None; + return std::nullopt; } } @@ -521,10 +526,10 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { else Triple = "arm"; - Optional<unsigned> Attr = + std::optional<unsigned> Attr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); if (Attr) { - switch (Attr.value()) { + switch (*Attr) { case ARMBuildAttrs::v4: Triple += "v4"; break; @@ -553,10 +558,10 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { Triple += "v6k"; break; case ARMBuildAttrs::v7: { - Optional<unsigned> ArchProfileAttr = + std::optional<unsigned> ArchProfileAttr = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile); if (ArchProfileAttr && - ArchProfileAttr.value() == ARMBuildAttrs::MicroControllerProfile) + *ArchProfileAttr == ARMBuildAttrs::MicroControllerProfile) Triple += "v7m"; else Triple += "v7"; @@ -597,7 +602,7 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { TheTriple.setArchName(Triple); } -std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> +std::vector<std::pair<std::optional<DataRefImpl>, uint64_t>> ELFObjectFileBase::getPltAddresses() const { std::string Err; const auto Triple = makeTriple(); @@ -624,7 +629,7 @@ ELFObjectFileBase::getPltAddresses() const { T->createMCInstrAnalysis(MII.get())); if (!MIA) return {}; - Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None; + std::optional<SectionRef> Plt, RelaPlt, GotPlt; for (const SectionRef &Section : sections()) { Expected<StringRef> NameOrErr = Section.getName(); if (!NameOrErr) { @@ -656,7 +661,7 @@ ELFObjectFileBase::getPltAddresses() const { GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); // Find the relocations in the dynamic relocation table that point to // locations in the GOT for which we know the corresponding PLT entry. - std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> Result; + std::vector<std::pair<std::optional<DataRefImpl>, uint64_t>> Result; for (const auto &Relocation : RelaPlt->relocations()) { if (Relocation.getType() != JumpSlotReloc) continue; @@ -664,7 +669,7 @@ ELFObjectFileBase::getPltAddresses() const { if (PltEntryIter != GotToPlt.end()) { symbol_iterator Sym = Relocation.getSymbol(); if (Sym == symbol_end()) - Result.emplace_back(None, PltEntryIter->second); + Result.emplace_back(std::nullopt, PltEntryIter->second); else Result.emplace_back(Sym->getRawDataRefImpl(), PltEntryIter->second); } @@ -673,9 +678,8 @@ ELFObjectFileBase::getPltAddresses() const { } template <class ELFT> -Expected<std::vector<BBAddrMap>> -readBBAddrMapImpl(const ELFFile<ELFT> &EF, - Optional<unsigned> TextSectionIndex) { +Expected<std::vector<BBAddrMap>> static readBBAddrMapImpl( + const ELFFile<ELFT> &EF, std::optional<unsigned> TextSectionIndex) { using Elf_Shdr = typename ELFT::Shdr; std::vector<BBAddrMap> BBAddrMaps; const auto &Sections = cantFail(EF.sections()); @@ -722,7 +726,7 @@ readDynsymVersionsImpl(const ELFFile<ELFT> &EF, if (!VerSec) return std::vector<VersionEntry>(); - Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr = + Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr = EF.loadVersionMap(VerNeedSec, VerDefSec); if (!MapOrErr) return MapOrErr.takeError(); @@ -771,8 +775,8 @@ ELFObjectFileBase::readDynsymVersions() const { Symbols); } -Expected<std::vector<BBAddrMap>> -ELFObjectFileBase::readBBAddrMap(Optional<unsigned> TextSectionIndex) const { +Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap( + std::optional<unsigned> TextSectionIndex) const { if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this)) return readBBAddrMapImpl(Obj->getELFFile(), TextSectionIndex); if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this)) diff --git a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp index 5a7ecdb1fc25..54ee000b302f 100644 --- a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp +++ b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp @@ -289,7 +289,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, inconvertibleErrorCode()); Uncommon().CommonSize = GV->getParent()->getDataLayout().getTypeAllocSize(GV->getValueType()); - Uncommon().CommonAlign = GVar->getAlignment(); + Uncommon().CommonAlign = GVar->getAlign() ? GVar->getAlign()->value() : 0; } const GlobalObject *GO = GV->getAliaseeObject(); diff --git a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp index 2f463a1bd458..9c0b85cf7416 100644 --- a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/bit.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/BinaryFormat/Swift.h" #include "llvm/Object/Error.h" @@ -1385,6 +1385,11 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, *this, Load, I, &DyldChainedFixupsLoadCmd, "LC_DYLD_CHAINED_FIXUPS", Elements, "chained fixups"))) return; + } else if (Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) { + if ((Err = checkLinkeditDataCommand( + *this, Load, I, &DyldExportsTrieLoadCmd, "LC_DYLD_EXPORTS_TRIE", + Elements, "exports trie"))) + return; } else if (Load.C.cmd == MachO::LC_UUID) { if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " @@ -1875,9 +1880,13 @@ Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { Result |= SymbolRef::SF_Undefined; } - if (!(MachOType & MachO::N_PEXT)) + if (MachOType & MachO::N_PEXT) + Result |= SymbolRef::SF_Hidden; + else Result |= SymbolRef::SF_Exported; - } + + } else if (MachOType & MachO::N_PEXT) + Result |= SymbolRef::SF_Hidden; if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) Result |= SymbolRef::SF_Weak; @@ -2072,6 +2081,19 @@ ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj, Segment.fileoff, Segment.fileoff + Segment.filesize)); return {}; } + +template <typename LoadCommandType> +ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj, + MachOObjectFile::LoadCommandInfo LoadCmd) { + auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr); + if (!SegmentOrErr) { + consumeError(SegmentOrErr.takeError()); + return {}; + } + auto &Segment = SegmentOrErr.get(); + return arrayRefFromStringRef( + Obj.getData().slice(Segment.fileoff, Segment.fileoff + Segment.filesize)); +} } // namespace ArrayRef<uint8_t> @@ -2096,6 +2118,28 @@ MachOObjectFile::getSegmentContents(StringRef SegmentName) const { return {}; } +ArrayRef<uint8_t> +MachOObjectFile::getSegmentContents(size_t SegmentIndex) const { + size_t Idx = 0; + for (auto LoadCmd : load_commands()) { + switch (LoadCmd.C.cmd) { + case MachO::LC_SEGMENT: + if (Idx == SegmentIndex) + return ::getSegmentContents<MachO::segment_command>(*this, LoadCmd); + ++Idx; + break; + case MachO::LC_SEGMENT_64: + if (Idx == SegmentIndex) + return ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd); + ++Idx; + break; + default: + continue; + } + } + return {}; +} + unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { return Sec.getRawDataRefImpl().d.a; } @@ -2293,7 +2337,7 @@ void MachOObjectFile::getRelocationTypeName( "ARM64_RELOC_ADDEND" }; - if (RType >= array_lengthof(Table)) + if (RType >= std::size(Table)) res = "Unknown"; else res = Table[RType]; @@ -3055,7 +3099,7 @@ void ExportEntry::pushNode(uint64_t offset) { } if(ExportStart + ExportInfoSize != State.Current) { *E = malformedError( - "inconsistant export info size: 0x" + + "inconsistent export info size: 0x" + Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" + Twine::utohexstr(State.Current - ExportStart) + " in export trie data at node: 0x" + Twine::utohexstr(offset)); @@ -3189,7 +3233,13 @@ MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie, } iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const { - return exports(Err, getDyldInfoExportsTrie(), this); + ArrayRef<uint8_t> Trie; + if (DyldInfoLoadCmd) + Trie = getDyldInfoExportsTrie(); + else if (DyldExportsTrieLoadCmd) + Trie = getDyldExportsTrie(); + + return exports(Err, Trie, this); } MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E, @@ -3256,6 +3306,8 @@ void MachOAbstractFixupEntry::moveToFirst() { void MachOAbstractFixupEntry::moveToEnd() { Done = true; } +void MachOAbstractFixupEntry::moveNext() {} + MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E, const MachOObjectFile *O, bool Parse) @@ -3263,17 +3315,54 @@ MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E, ErrorAsOutParameter e(E); if (!Parse) return; - if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) + + if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) { FixupTargets = *FixupTargetsOrErr; - else { + } else { *E = FixupTargetsOrErr.takeError(); return; } + + if (auto SegmentsOrErr = O->getChainedFixupsSegments()) { + Segments = std::move(SegmentsOrErr->second); + } else { + *E = SegmentsOrErr.takeError(); + return; + } +} + +void MachOChainedFixupEntry::findNextPageWithFixups() { + auto FindInSegment = [this]() { + const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex]; + while (PageIndex < SegInfo.PageStarts.size() && + SegInfo.PageStarts[PageIndex] == MachO::DYLD_CHAINED_PTR_START_NONE) + ++PageIndex; + return PageIndex < SegInfo.PageStarts.size(); + }; + + while (InfoSegIndex < Segments.size()) { + if (FindInSegment()) { + PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex]; + SegmentData = O->getSegmentContents(Segments[InfoSegIndex].SegIdx); + return; + } + + InfoSegIndex++; + PageIndex = 0; + } } void MachOChainedFixupEntry::moveToFirst() { MachOAbstractFixupEntry::moveToFirst(); - FixupIndex = 0; + if (Segments.empty()) { + Done = true; + return; + } + + InfoSegIndex = 0; + PageIndex = 0; + + findNextPageWithFixups(); moveNext(); } @@ -3281,15 +3370,104 @@ void MachOChainedFixupEntry::moveToEnd() { MachOAbstractFixupEntry::moveToEnd(); } -void MachOChainedFixupEntry::moveNext() { Done = true; } +void MachOChainedFixupEntry::moveNext() { + ErrorAsOutParameter ErrAsOutParam(E); + + if (InfoSegIndex == Segments.size()) { + Done = true; + return; + } + + const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex]; + SegmentIndex = SegInfo.SegIdx; + SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset; + + // FIXME: Handle other pointer formats. + uint16_t PointerFormat = SegInfo.Header.pointer_format; + if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 && + PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) { + *E = createError("segment " + Twine(SegmentIndex) + + " has unsupported chained fixup pointer_format " + + Twine(PointerFormat)); + moveToEnd(); + return; + } + + Ordinal = 0; + Flags = 0; + Addend = 0; + PointerValue = 0; + SymbolName = {}; + + if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) { + *E = malformedError("fixup in segment " + Twine(SegmentIndex) + + " at offset " + Twine(SegmentOffset) + + " extends past segment's end"); + moveToEnd(); + return; + } + + static_assert(sizeof(RawValue) == sizeof(MachO::dyld_chained_import_addend)); + memcpy(&RawValue, SegmentData.data() + SegmentOffset, sizeof(RawValue)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(RawValue); + + // The bit extraction below assumes little-endian fixup entries. + assert(O->isLittleEndian() && "big-endian object should have been rejected " + "by getDyldChainedFixupTargets()"); + auto Field = [this](uint8_t Right, uint8_t Count) { + return (RawValue >> Right) & ((1ULL << Count) - 1); + }; + + // The `bind` field (most significant bit) of the encoded fixup determines + // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase. + bool IsBind = Field(63, 1); + Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase; + uint32_t Next = Field(51, 12); + if (IsBind) { + uint32_t ImportOrdinal = Field(0, 24); + uint8_t InlineAddend = Field(24, 8); + + if (ImportOrdinal >= FixupTargets.size()) { + *E = malformedError("fixup in segment " + Twine(SegmentIndex) + + " at offset " + Twine(SegmentOffset) + + " has out-of range import ordinal " + + Twine(ImportOrdinal)); + moveToEnd(); + return; + } + + ChainedFixupTarget &Target = FixupTargets[ImportOrdinal]; + Ordinal = Target.libOrdinal(); + Addend = InlineAddend ? InlineAddend : Target.addend(); + Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0; + SymbolName = Target.symbolName(); + } else { + uint64_t Target = Field(0, 36); + uint64_t High8 = Field(36, 8); + + PointerValue = Target | (High8 << 56); + if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET) + PointerValue += textAddress(); + } + + // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET). + if (Next != 0) { + PageOffset += 4 * Next; + } else { + ++PageIndex; + findNextPageWithFixups(); + } +} bool MachOChainedFixupEntry::operator==( const MachOChainedFixupEntry &Other) const { - if (Done == Other.Done) - return true; - if ((FixupIndex == Other.FixupIndex)) + if (Done && Other.Done) return true; - return false; + if (Done != Other.Done) + return false; + return InfoSegIndex == Other.InfoSegIndex && PageIndex == Other.PageIndex && + PageOffset == Other.PageOffset; } MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O, @@ -4301,6 +4479,9 @@ iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) { } iterator_range<fixup_iterator> MachOObjectFile::fixupTable(Error &Err) { + if (BindRebaseSectionTable == nullptr) + BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(this); + MachOChainedFixupEntry Start(&Err, this, true); Start.moveToFirst(); @@ -4336,7 +4517,7 @@ MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); const section_base *Base = reinterpret_cast<const section_base *>(Sections[Sec.d.a]); - return makeArrayRef(Base->sectname); + return ArrayRef(Base->sectname); } ArrayRef<char> @@ -4344,7 +4525,7 @@ MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); const section_base *Base = reinterpret_cast<const section_base *>(Sections[Sec.d.a]); - return makeArrayRef(Base->segname); + return ArrayRef(Base->segname); } bool @@ -4711,76 +4892,105 @@ MachOObjectFile::getLinkOptHintsLoadCommand() const { ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { if (!DyldInfoLoadCmd) - return None; + return std::nullopt; auto DyldInfoOrErr = getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); if (!DyldInfoOrErr) - return None; + return std::nullopt; MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off)); - return makeArrayRef(Ptr, DyldInfo.rebase_size); + return ArrayRef(Ptr, DyldInfo.rebase_size); } ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { if (!DyldInfoLoadCmd) - return None; + return std::nullopt; auto DyldInfoOrErr = getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); if (!DyldInfoOrErr) - return None; + return std::nullopt; MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off)); - return makeArrayRef(Ptr, DyldInfo.bind_size); + return ArrayRef(Ptr, DyldInfo.bind_size); } ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { if (!DyldInfoLoadCmd) - return None; + return std::nullopt; auto DyldInfoOrErr = getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); if (!DyldInfoOrErr) - return None; + return std::nullopt; MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off)); - return makeArrayRef(Ptr, DyldInfo.weak_bind_size); + return ArrayRef(Ptr, DyldInfo.weak_bind_size); } ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { if (!DyldInfoLoadCmd) - return None; + return std::nullopt; auto DyldInfoOrErr = - getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); + getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); if (!DyldInfoOrErr) - return None; + return std::nullopt; MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off)); - return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); + return ArrayRef(Ptr, DyldInfo.lazy_bind_size); } -Expected<Optional<MachO::dyld_chained_fixups_header>> -MachOObjectFile::getChainedFixupsHeader() const { +ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { + if (!DyldInfoLoadCmd) + return std::nullopt; + + auto DyldInfoOrErr = + getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); + if (!DyldInfoOrErr) + return std::nullopt; + MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); + const uint8_t *Ptr = + reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off)); + return ArrayRef(Ptr, DyldInfo.export_size); +} + +Expected<std::optional<MachO::linkedit_data_command>> +MachOObjectFile::getChainedFixupsLoadCommand() const { // Load the dyld chained fixups load command. if (!DyldChainedFixupsLoadCmd) - return llvm::None; + return std::nullopt; auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>( *this, DyldChainedFixupsLoadCmd); if (!DyldChainedFixupsOrErr) return DyldChainedFixupsOrErr.takeError(); - MachO::linkedit_data_command DyldChainedFixups = DyldChainedFixupsOrErr.get(); + const MachO::linkedit_data_command &DyldChainedFixups = + *DyldChainedFixupsOrErr; // If the load command is present but the data offset has been zeroed out, - // as is the case for dylib stubs, return None (no error). + // as is the case for dylib stubs, return std::nullopt (no error). + if (!DyldChainedFixups.dataoff) + return std::nullopt; + return DyldChainedFixups; +} + +Expected<std::optional<MachO::dyld_chained_fixups_header>> +MachOObjectFile::getChainedFixupsHeader() const { + auto CFOrErr = getChainedFixupsLoadCommand(); + if (!CFOrErr) + return CFOrErr.takeError(); + if (!CFOrErr->has_value()) + return std::nullopt; + + const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr; + uint64_t CFHeaderOffset = DyldChainedFixups.dataoff; - if (CFHeaderOffset == 0) - return DyldChainedFixupsOrErr.takeError(); + uint64_t CFSize = DyldChainedFixups.datasize; // Load the dyld chained fixups header. const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset); @@ -4808,7 +5018,7 @@ MachOObjectFile::getChainedFixupsHeader() const { Twine(CFHeader.starts_offset) + " overlaps with chained fixups header"); } - uint32_t EndOffset = DyldChainedFixups.dataoff + DyldChainedFixups.datasize; + uint32_t EndOffset = CFHeaderOffset + CFSize; if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) > EndOffset) { return malformedError(Twine("bad chained fixups: image starts end ") + @@ -4820,29 +5030,225 @@ MachOObjectFile::getChainedFixupsHeader() const { return CFHeader; } +Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>> +MachOObjectFile::getChainedFixupsSegments() const { + auto CFOrErr = getChainedFixupsLoadCommand(); + if (!CFOrErr) + return CFOrErr.takeError(); + + std::vector<ChainedFixupsSegment> Segments; + if (!CFOrErr->has_value()) + return std::make_pair(0, Segments); + + const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr; + + auto HeaderOrErr = getChainedFixupsHeader(); + if (!HeaderOrErr) + return HeaderOrErr.takeError(); + if (!HeaderOrErr->has_value()) + return std::make_pair(0, Segments); + const MachO::dyld_chained_fixups_header &Header = **HeaderOrErr; + + const char *Contents = getPtr(*this, DyldChainedFixups.dataoff); + + auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>( + *this, Contents + Header.starts_offset); + if (!ImageStartsOrErr) + return ImageStartsOrErr.takeError(); + const MachO::dyld_chained_starts_in_image &ImageStarts = *ImageStartsOrErr; + + const char *SegOffsPtr = + Contents + Header.starts_offset + + offsetof(MachO::dyld_chained_starts_in_image, seg_info_offset); + const char *SegOffsEnd = + SegOffsPtr + ImageStarts.seg_count * sizeof(uint32_t); + if (SegOffsEnd > Contents + DyldChainedFixups.datasize) + return malformedError( + "bad chained fixups: seg_info_offset extends past end"); + + const char *LastSegEnd = nullptr; + for (size_t I = 0, N = ImageStarts.seg_count; I < N; ++I) { + auto OffOrErr = + getStructOrErr<uint32_t>(*this, SegOffsPtr + I * sizeof(uint32_t)); + if (!OffOrErr) + return OffOrErr.takeError(); + // seg_info_offset == 0 means there is no associated starts_in_segment + // entry. + if (!*OffOrErr) + continue; + + auto Fail = [&](Twine Message) { + return malformedError("bad chained fixups: segment info" + Twine(I) + + " at offset " + Twine(*OffOrErr) + Message); + }; + + const char *SegPtr = Contents + Header.starts_offset + *OffOrErr; + if (LastSegEnd && SegPtr < LastSegEnd) + return Fail(" overlaps with previous segment info"); + + auto SegOrErr = + getStructOrErr<MachO::dyld_chained_starts_in_segment>(*this, SegPtr); + if (!SegOrErr) + return SegOrErr.takeError(); + const MachO::dyld_chained_starts_in_segment &Seg = *SegOrErr; + + LastSegEnd = SegPtr + Seg.size; + if (Seg.pointer_format < 1 || Seg.pointer_format > 12) + return Fail(" has unknown pointer format: " + Twine(Seg.pointer_format)); + + const char *PageStart = + SegPtr + offsetof(MachO::dyld_chained_starts_in_segment, page_start); + const char *PageEnd = PageStart + Seg.page_count * sizeof(uint16_t); + if (PageEnd > SegPtr + Seg.size) + return Fail(" : page_starts extend past seg_info size"); + + // FIXME: This does not account for multiple offsets on a single page + // (DYLD_CHAINED_PTR_START_MULTI; 32-bit only). + std::vector<uint16_t> PageStarts; + for (size_t PageIdx = 0; PageIdx < Seg.page_count; ++PageIdx) { + uint16_t Start; + memcpy(&Start, PageStart + PageIdx * sizeof(uint16_t), sizeof(uint16_t)); + if (isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(Start); + PageStarts.push_back(Start); + } + + Segments.emplace_back(I, *OffOrErr, Seg, std::move(PageStarts)); + } + + return std::make_pair(ImageStarts.seg_count, Segments); +} + +// The special library ordinals have a negative value, but they are encoded in +// an unsigned bitfield, so we need to sign extend the value. +template <typename T> static int getEncodedOrdinal(T Value) { + if (Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE) || + Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) || + Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP)) + return SignExtend32<sizeof(T) * CHAR_BIT>(Value); + return Value; +} + +template <typename T, unsigned N> +static std::array<T, N> getArray(const MachOObjectFile &O, const void *Ptr) { + std::array<T, N> RawValue; + memcpy(RawValue.data(), Ptr, N * sizeof(T)); + if (O.isLittleEndian() != sys::IsLittleEndianHost) + for (auto &Element : RawValue) + sys::swapByteOrder(Element); + return RawValue; +} + Expected<std::vector<ChainedFixupTarget>> MachOObjectFile::getDyldChainedFixupTargets() const { + auto CFOrErr = getChainedFixupsLoadCommand(); + if (!CFOrErr) + return CFOrErr.takeError(); + + std::vector<ChainedFixupTarget> Targets; + if (!CFOrErr->has_value()) + return Targets; + + const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr; + auto CFHeaderOrErr = getChainedFixupsHeader(); if (!CFHeaderOrErr) return CFHeaderOrErr.takeError(); - std::vector<ChainedFixupTarget> Targets; if (!(*CFHeaderOrErr)) return Targets; - return Targets; + const MachO::dyld_chained_fixups_header &Header = **CFHeaderOrErr; + + size_t ImportSize = 0; + if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT) + ImportSize = sizeof(MachO::dyld_chained_import); + else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND) + ImportSize = sizeof(MachO::dyld_chained_import_addend); + else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) + ImportSize = sizeof(MachO::dyld_chained_import_addend64); + else + return malformedError("bad chained fixups: unknown imports format: " + + Twine(Header.imports_format)); + + const char *Contents = getPtr(*this, DyldChainedFixups.dataoff); + const char *Imports = Contents + Header.imports_offset; + size_t ImportsEndOffset = + Header.imports_offset + ImportSize * Header.imports_count; + const char *ImportsEnd = Contents + ImportsEndOffset; + const char *Symbols = Contents + Header.symbols_offset; + const char *SymbolsEnd = Contents + DyldChainedFixups.datasize; + + if (ImportsEnd > Symbols) + return malformedError("bad chained fixups: imports end " + + Twine(ImportsEndOffset) + " extends past end " + + Twine(DyldChainedFixups.datasize)); + + if (ImportsEnd > Symbols) + return malformedError("bad chained fixups: imports end " + + Twine(ImportsEndOffset) + " overlaps with symbols"); + + // We use bit manipulation to extract data from the bitfields. This is correct + // for both LE and BE hosts, but we assume that the object is little-endian. + if (!isLittleEndian()) + return createError("parsing big-endian chained fixups is not implemented"); + for (const char *ImportPtr = Imports; ImportPtr < ImportsEnd; + ImportPtr += ImportSize) { + int LibOrdinal; + bool WeakImport; + uint32_t NameOffset; + uint64_t Addend; + if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT) { + static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import)); + auto RawValue = getArray<uint32_t, 1>(*this, ImportPtr); + + LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF); + WeakImport = (RawValue[0] >> 8) & 1; + NameOffset = RawValue[0] >> 9; + Addend = 0; + } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND) { + static_assert(sizeof(uint64_t) == + sizeof(MachO::dyld_chained_import_addend)); + auto RawValue = getArray<uint32_t, 2>(*this, ImportPtr); + + LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF); + WeakImport = (RawValue[0] >> 8) & 1; + NameOffset = RawValue[0] >> 9; + Addend = bit_cast<int32_t>(RawValue[1]); + } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) { + static_assert(2 * sizeof(uint64_t) == + sizeof(MachO::dyld_chained_import_addend64)); + auto RawValue = getArray<uint64_t, 2>(*this, ImportPtr); + + LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF); + NameOffset = (RawValue[0] >> 16) & 1; + WeakImport = RawValue[0] >> 17; + Addend = RawValue[1]; + } else { + llvm_unreachable("Import format should have been checked"); + } + + const char *Str = Symbols + NameOffset; + if (Str >= SymbolsEnd) + return malformedError("bad chained fixups: symbol offset " + + Twine(NameOffset) + " extends past end " + + Twine(DyldChainedFixups.datasize)); + Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport); + } + + return std::move(Targets); } -ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { - if (!DyldInfoLoadCmd) - return None; +ArrayRef<uint8_t> MachOObjectFile::getDyldExportsTrie() const { + if (!DyldExportsTrieLoadCmd) + return std::nullopt; - auto DyldInfoOrErr = - getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); - if (!DyldInfoOrErr) - return None; - MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get(); + auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>( + *this, DyldExportsTrieLoadCmd); + if (!DyldExportsTrieOrError) + return std::nullopt; + MachO::linkedit_data_command DyldExportsTrie = DyldExportsTrieOrError.get(); const uint8_t *Ptr = - reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off)); - return makeArrayRef(Ptr, DyldInfo.export_size); + reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie.dataoff)); + return ArrayRef(Ptr, DyldExportsTrie.datasize); } SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const { @@ -4862,10 +5268,10 @@ SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const { ArrayRef<uint8_t> MachOObjectFile::getUuid() const { if (!UuidLoadCmd) - return None; + return std::nullopt; // Returning a pointer is fine as uuid doesn't need endian swapping. const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); - return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); + return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); } StringRef MachOObjectFile::getStringTableData() const { diff --git a/contrib/llvm-project/llvm/lib/Object/Minidump.cpp b/contrib/llvm-project/llvm/lib/Object/Minidump.cpp index 3e932fe7be28..6febff89ac51 100644 --- a/contrib/llvm-project/llvm/lib/Object/Minidump.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Minidump.cpp @@ -14,12 +14,12 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::minidump; -Optional<ArrayRef<uint8_t>> +std::optional<ArrayRef<uint8_t>> MinidumpFile::getRawStream(minidump::StreamType Type) const { auto It = StreamMap.find(Type); if (It != StreamMap.end()) return getRawStream(Streams[It->second]); - return None; + return std::nullopt; } Expected<std::string> MinidumpFile::getString(size_t Offset) const { @@ -55,7 +55,8 @@ Expected<std::string> MinidumpFile::getString(size_t Offset) const { Expected<iterator_range<MinidumpFile::MemoryInfoIterator>> MinidumpFile::getMemoryInfoList() const { - Optional<ArrayRef<uint8_t>> Stream = getRawStream(StreamType::MemoryInfoList); + std::optional<ArrayRef<uint8_t>> Stream = + getRawStream(StreamType::MemoryInfoList); if (!Stream) return createError("No such stream"); auto ExpectedHeader = @@ -73,7 +74,7 @@ MinidumpFile::getMemoryInfoList() const { template <typename T> Expected<ArrayRef<T>> MinidumpFile::getListStream(StreamType Type) const { - Optional<ArrayRef<uint8_t>> Stream = getRawStream(Type); + std::optional<ArrayRef<uint8_t>> Stream = getRawStream(Type); if (!Stream) return createError("No such stream"); auto ExpectedSize = getDataSliceAs<support::ulittle32_t>(*Stream, 0, 1); diff --git a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp index 1be8f11751be..56a1d09097d4 100644 --- a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp @@ -96,6 +96,11 @@ bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const { bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; } +bool ObjectFile::hasDebugInfo() const { + return any_of(sections(), + [](SectionRef Sec) { return Sec.isDebugSection(); }); +} + Expected<section_iterator> ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); @@ -169,6 +174,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type, case file_magic::macho_dynamically_linked_shared_lib_stub: case file_magic::macho_dsym_companion: case file_magic::macho_kext_bundle: + case file_magic::macho_file_set: return createMachOObjectFile(Object); case file_magic::coff_object: case file_magic::coff_import_library: diff --git a/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp b/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp index 21946ec2d6fb..d8cdcdc21d39 100644 --- a/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp +++ b/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp @@ -10,14 +10,166 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/Magic.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" #include "llvm/MC/StringTableBuilder.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ArchiveWriter.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/Error.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/SourceMgr.h" using namespace llvm; using namespace llvm::object; +namespace { + +/// Attempts to extract all the embedded device images contained inside the +/// buffer \p Contents. The buffer is expected to contain a valid offloading +/// binary format. +Error extractOffloadFiles(MemoryBufferRef Contents, + SmallVectorImpl<OffloadFile> &Binaries) { + uint64_t Offset = 0; + // There could be multiple offloading binaries stored at this section. + while (Offset < Contents.getBuffer().size()) { + std::unique_ptr<MemoryBuffer> Buffer = + MemoryBuffer::getMemBuffer(Contents.getBuffer().drop_front(Offset), "", + /*RequiresNullTerminator*/ false); + if (!isAddrAligned(Align(OffloadBinary::getAlignment()), + Buffer->getBufferStart())) + Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), + Buffer->getBufferIdentifier()); + auto BinaryOrErr = OffloadBinary::create(*Buffer); + if (!BinaryOrErr) + return BinaryOrErr.takeError(); + OffloadBinary &Binary = **BinaryOrErr; + + // Create a new owned binary with a copy of the original memory. + std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy( + Binary.getData().take_front(Binary.getSize()), + Contents.getBufferIdentifier()); + auto NewBinaryOrErr = OffloadBinary::create(*BufferCopy); + if (!NewBinaryOrErr) + return NewBinaryOrErr.takeError(); + Binaries.emplace_back(std::move(*NewBinaryOrErr), std::move(BufferCopy)); + + Offset += Binary.getSize(); + } + + return Error::success(); +} + +// Extract offloading binaries from an Object file \p Obj. +Error extractFromObject(const ObjectFile &Obj, + SmallVectorImpl<OffloadFile> &Binaries) { + assert((Obj.isELF() || Obj.isCOFF()) && "Invalid file type"); + + for (SectionRef Sec : Obj.sections()) { + // ELF files contain a section with the LLVM_OFFLOADING type. + if (Obj.isELF() && + static_cast<ELFSectionRef>(Sec).getType() != ELF::SHT_LLVM_OFFLOADING) + continue; + + // COFF has no section types so we rely on the name of the section. + if (Obj.isCOFF()) { + Expected<StringRef> NameOrErr = Sec.getName(); + if (!NameOrErr) + return NameOrErr.takeError(); + + if (!NameOrErr->equals(".llvm.offloading")) + continue; + } + + Expected<StringRef> Buffer = Sec.getContents(); + if (!Buffer) + return Buffer.takeError(); + + MemoryBufferRef Contents(*Buffer, Obj.getFileName()); + if (Error Err = extractOffloadFiles(Contents, Binaries)) + return Err; + } + + return Error::success(); +} + +Error extractFromBitcode(MemoryBufferRef Buffer, + SmallVectorImpl<OffloadFile> &Binaries) { + LLVMContext Context; + SMDiagnostic Err; + std::unique_ptr<Module> M = getLazyIRModule( + MemoryBuffer::getMemBuffer(Buffer, /*RequiresNullTerminator=*/false), Err, + Context); + if (!M) + return createStringError(inconvertibleErrorCode(), + "Failed to create module"); + + // Extract offloading data from globals referenced by the + // `llvm.embedded.object` metadata with the `.llvm.offloading` section. + auto *MD = M->getNamedMetadata("llvm.embedded.objects"); + if (!MD) + return Error::success(); + + for (const MDNode *Op : MD->operands()) { + if (Op->getNumOperands() < 2) + continue; + + MDString *SectionID = dyn_cast<MDString>(Op->getOperand(1)); + if (!SectionID || SectionID->getString() != ".llvm.offloading") + continue; + + GlobalVariable *GV = + mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand(0)); + if (!GV) + continue; + + auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer()); + if (!CDS) + continue; + + MemoryBufferRef Contents(CDS->getAsString(), M->getName()); + if (Error Err = extractOffloadFiles(Contents, Binaries)) + return Err; + } + + return Error::success(); +} + +Error extractFromArchive(const Archive &Library, + SmallVectorImpl<OffloadFile> &Binaries) { + // Try to extract device code from each file stored in the static archive. + Error Err = Error::success(); + for (auto Child : Library.children(Err)) { + auto ChildBufferOrErr = Child.getMemoryBufferRef(); + if (!ChildBufferOrErr) + return ChildBufferOrErr.takeError(); + std::unique_ptr<MemoryBuffer> ChildBuffer = + MemoryBuffer::getMemBuffer(*ChildBufferOrErr, false); + + // Check if the buffer has the required alignment. + if (!isAddrAligned(Align(OffloadBinary::getAlignment()), + ChildBuffer->getBufferStart())) + ChildBuffer = MemoryBuffer::getMemBufferCopy( + ChildBufferOrErr->getBuffer(), + ChildBufferOrErr->getBufferIdentifier()); + + if (Error Err = extractOffloadBinaries(*ChildBuffer, Binaries)) + return Err; + } + + if (Err) + return Err; + return Error::success(); +} + +} // namespace + Expected<std::unique_ptr<OffloadBinary>> OffloadBinary::create(MemoryBufferRef Buf) { if (Buf.getBufferSize() < sizeof(Header) + sizeof(Entry)) @@ -115,6 +267,36 @@ OffloadBinary::write(const OffloadingImage &OffloadingData) { return MemoryBuffer::getMemBufferCopy(OS.str()); } +Error object::extractOffloadBinaries(MemoryBufferRef Buffer, + SmallVectorImpl<OffloadFile> &Binaries) { + file_magic Type = identify_magic(Buffer.getBuffer()); + switch (Type) { + case file_magic::bitcode: + return extractFromBitcode(Buffer, Binaries); + case file_magic::elf_relocatable: + case file_magic::elf_executable: + case file_magic::elf_shared_object: + case file_magic::coff_object: { + Expected<std::unique_ptr<ObjectFile>> ObjFile = + ObjectFile::createObjectFile(Buffer, Type); + if (!ObjFile) + return ObjFile.takeError(); + return extractFromObject(*ObjFile->get(), Binaries); + } + case file_magic::archive: { + Expected<std::unique_ptr<llvm::object::Archive>> LibFile = + object::Archive::create(Buffer); + if (!LibFile) + return LibFile.takeError(); + return extractFromArchive(*LibFile->get(), Binaries); + } + case file_magic::offload_binary: + return extractOffloadFiles(Buffer, Binaries); + default: + return Error::success(); + } +} + OffloadKind object::getOffloadKind(StringRef Name) { return llvm::StringSwitch<OffloadKind>(Name) .Case("openmp", OFK_OpenMP) diff --git a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp index 2d07d34bbf97..2548dd6c84d2 100644 --- a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp +++ b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp @@ -106,13 +106,13 @@ bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol, } void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, + uint64_t Size, Align ByteAlignment, SMLoc Loc) { markDefined(*Symbol); } void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { + Align ByteAlignment) { markDefined(*Symbol); } diff --git a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h index 5c6541e5052d..a568739d3763 100644 --- a/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h +++ b/contrib/llvm-project/llvm/lib/Object/RecordStreamer.h @@ -50,9 +50,9 @@ public: void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; void emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment, SMLoc Loc = SMLoc()) override; + Align ByteAlignment, SMLoc Loc = SMLoc()) override; void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override; + Align ByteAlignment) override; // Ignore COFF-specific directives; we do not need any information from them, // but the default implementation of these methods crashes, so we override diff --git a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp index e14301663df3..13a7a9851137 100644 --- a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp +++ b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp @@ -433,11 +433,14 @@ static bool supportsRISCV(uint64_t Type) { case ELF::R_RISCV_32_PCREL: case ELF::R_RISCV_64: case ELF::R_RISCV_SET6: + case ELF::R_RISCV_SET8: case ELF::R_RISCV_SUB6: case ELF::R_RISCV_ADD8: case ELF::R_RISCV_SUB8: + case ELF::R_RISCV_SET16: case ELF::R_RISCV_ADD16: case ELF::R_RISCV_SUB16: + case ELF::R_RISCV_SET32: case ELF::R_RISCV_ADD32: case ELF::R_RISCV_SUB32: case ELF::R_RISCV_ADD64: @@ -465,14 +468,20 @@ static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S, return (A & 0xC0) | ((S + RA) & 0x3F); case ELF::R_RISCV_SUB6: return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F); + case ELF::R_RISCV_SET8: + return (S + RA) & 0xFF; case ELF::R_RISCV_ADD8: return (A + (S + RA)) & 0xFF; case ELF::R_RISCV_SUB8: return (A - (S + RA)) & 0xFF; + case ELF::R_RISCV_SET16: + return (S + RA) & 0xFFFF; case ELF::R_RISCV_ADD16: return (A + (S + RA)) & 0xFFFF; case ELF::R_RISCV_SUB16: return (A - (S + RA)) & 0xFFFF; + case ELF::R_RISCV_SET32: + return (S + RA) & 0xFFFFFFFF; case ELF::R_RISCV_ADD32: return (A + (S + RA)) & 0xFFFFFFFF; case ELF::R_RISCV_SUB32: @@ -511,6 +520,58 @@ static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S, } } +static bool supportsLoongArch(uint64_t Type) { + switch (Type) { + case ELF::R_LARCH_NONE: + case ELF::R_LARCH_32: + case ELF::R_LARCH_32_PCREL: + case ELF::R_LARCH_64: + case ELF::R_LARCH_ADD8: + case ELF::R_LARCH_SUB8: + case ELF::R_LARCH_ADD16: + case ELF::R_LARCH_SUB16: + case ELF::R_LARCH_ADD32: + case ELF::R_LARCH_SUB32: + case ELF::R_LARCH_ADD64: + case ELF::R_LARCH_SUB64: + return true; + default: + return false; + } +} + +static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S, + uint64_t LocData, int64_t Addend) { + switch (Type) { + case ELF::R_LARCH_NONE: + return LocData; + case ELF::R_LARCH_32: + return (S + Addend) & 0xFFFFFFFF; + case ELF::R_LARCH_32_PCREL: + return (S + Addend - Offset) & 0xFFFFFFFF; + case ELF::R_LARCH_64: + return S + Addend; + case ELF::R_LARCH_ADD8: + return (LocData + (S + Addend)) & 0xFF; + case ELF::R_LARCH_SUB8: + return (LocData - (S + Addend)) & 0xFF; + case ELF::R_LARCH_ADD16: + return (LocData + (S + Addend)) & 0xFFFF; + case ELF::R_LARCH_SUB16: + return (LocData - (S + Addend)) & 0xFFFF; + case ELF::R_LARCH_ADD32: + return (LocData + (S + Addend)) & 0xFFFFFFFF; + case ELF::R_LARCH_SUB32: + return (LocData - (S + Addend)) & 0xFFFFFFFF; + case ELF::R_LARCH_ADD64: + return (LocData + (S + Addend)); + case ELF::R_LARCH_SUB64: + return (LocData - (S + Addend)); + default: + llvm_unreachable("Invalid relocation type"); + } +} + static bool supportsCOFFX86(uint64_t Type) { switch (Type) { case COFF::IMAGE_REL_I386_SECREL: @@ -711,6 +772,8 @@ getRelocationResolver(const ObjectFile &Obj) { case Triple::bpfel: case Triple::bpfeb: return {supportsBPF, resolveBPF}; + case Triple::loongarch64: + return {supportsLoongArch, resolveLoongArch}; case Triple::mips64el: case Triple::mips64: return {supportsMips64, resolveMips64}; @@ -747,6 +810,8 @@ getRelocationResolver(const ObjectFile &Obj) { return {supportsAVR, resolveAVR}; case Triple::lanai: return {supportsLanai, resolveLanai}; + case Triple::loongarch32: + return {supportsLoongArch, resolveLoongArch}; case Triple::mipsel: case Triple::mips: return {supportsMips32, resolveMips32}; diff --git a/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp b/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp index 05f47cfbf2ff..e87ecb149109 100644 --- a/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp @@ -63,6 +63,7 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type, case file_magic::macho_dynamically_linked_shared_lib_stub: case file_magic::macho_dsym_companion: case file_magic::macho_kext_bundle: + case file_magic::macho_file_set: case file_magic::pecoff_executable: case file_magic::xcoff_object_32: case file_magic::xcoff_object_64: @@ -113,6 +114,7 @@ bool SymbolicFile::isSymbolicFile(file_magic Type, const LLVMContext *Context) { case file_magic::macho_dynamically_linked_shared_lib_stub: case file_magic::macho_dsym_companion: case file_magic::macho_kext_bundle: + case file_magic::macho_file_set: case file_magic::pecoff_executable: case file_magic::xcoff_object_32: case file_magic::xcoff_object_64: diff --git a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp index d00359c6deef..1e98de7cd42e 100644 --- a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp @@ -640,9 +640,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Info.Name = Import.Field; } Signature = &Signatures[Import.SigIndex]; - if (!Import.Module.empty()) { - Info.ImportModule = Import.Module; - } + Info.ImportModule = Import.Module; } break; @@ -672,9 +670,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Info.Name = Import.Field; } GlobalType = &Import.Global; - if (!Import.Module.empty()) { - Info.ImportModule = Import.Module; - } + Info.ImportModule = Import.Module; } break; @@ -704,9 +700,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Info.Name = Import.Field; } TableType = &Import.Table; - if (!Import.Module.empty()) { - Info.ImportModule = Import.Module; - } + Info.ImportModule = Import.Module; } break; @@ -769,9 +763,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Info.Name = Import.Field; } Signature = &Signatures[Import.SigIndex]; - if (!Import.Module.empty()) { - Info.ImportModule = Import.Module; - } + Info.ImportModule = Import.Module; } break; } @@ -1841,7 +1833,7 @@ Triple::ArchType WasmObjectFile::getArch() const { return HasMemory64 ? Triple::wasm64 : Triple::wasm32; } -SubtargetFeatures WasmObjectFile::getFeatures() const { +Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const { return SubtargetFeatures(); } diff --git a/contrib/llvm-project/llvm/lib/Object/WindowsMachineFlag.cpp b/contrib/llvm-project/llvm/lib/Object/WindowsMachineFlag.cpp index f7f2b20ae1a2..8335ea745548 100644 --- a/contrib/llvm-project/llvm/lib/Object/WindowsMachineFlag.cpp +++ b/contrib/llvm-project/llvm/lib/Object/WindowsMachineFlag.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -25,6 +26,7 @@ COFF::MachineTypes llvm::getMachineType(StringRef S) { .Cases("x86", "i386", COFF::IMAGE_FILE_MACHINE_I386) .Case("arm", COFF::IMAGE_FILE_MACHINE_ARMNT) .Case("arm64", COFF::IMAGE_FILE_MACHINE_ARM64) + .Case("arm64ec", COFF::IMAGE_FILE_MACHINE_ARM64EC) .Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN); } @@ -34,6 +36,8 @@ StringRef llvm::machineToStr(COFF::MachineTypes MT) { return "arm"; case COFF::IMAGE_FILE_MACHINE_ARM64: return "arm64"; + case COFF::IMAGE_FILE_MACHINE_ARM64EC: + return "arm64ec"; case COFF::IMAGE_FILE_MACHINE_AMD64: return "x64"; case COFF::IMAGE_FILE_MACHINE_I386: diff --git a/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp b/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp index d50f149629c3..089a3fa0f91f 100644 --- a/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp +++ b/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp @@ -173,7 +173,7 @@ static bool convertUTF16LEToUTF8String(ArrayRef<UTF16> Src, std::string &Out) { EndianCorrectedSrc.resize(Src.size() + 1); llvm::copy(Src, EndianCorrectedSrc.begin() + 1); EndianCorrectedSrc[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED; - return convertUTF16ToUTF8String(makeArrayRef(EndianCorrectedSrc), Out); + return convertUTF16ToUTF8String(ArrayRef(EndianCorrectedSrc), Out); } static std::string makeDuplicateResourceError( @@ -938,7 +938,7 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { RelocationAddresses.resize(Data.size()); // Now write all the resource data entries. - for (auto DataNodes : DataEntriesTreeOrder) { + for (const auto *DataNodes : DataEntriesTreeOrder) { auto *Entry = reinterpret_cast<coff_resource_data_entry *>(BufferStart + CurrentOffset); RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset; @@ -989,6 +989,7 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() { Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB; break; case COFF::IMAGE_FILE_MACHINE_ARM64: + case COFF::IMAGE_FILE_MACHINE_ARM64EC: Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB; break; default: diff --git a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp index ff39fe1794c0..68baefcd6eaa 100644 --- a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp @@ -86,6 +86,37 @@ uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const { return (Info & XR_BIASED_LENGTH_MASK) + 1; } +template struct ExceptionSectionEntry<support::ubig32_t>; +template struct ExceptionSectionEntry<support::ubig64_t>; + +template <typename T> +Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader, + uint64_t Offset) { + if (LoaderSecHeader->LengthOfStrTbl > Offset) + return (reinterpret_cast<const char *>(LoaderSecHeader) + + LoaderSecHeader->OffsetToStrTbl + Offset); + + return createError("entry with offset 0x" + Twine::utohexstr(Offset) + + " in the loader section's string table with size 0x" + + Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) + + " is invalid"); +} + +Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName( + const LoaderSectionHeader32 *LoaderSecHeader32) const { + const NameOffsetInStrTbl *NameInStrTbl = + reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName); + if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) + return generateXCOFFFixedNameStringRef(SymbolName); + + return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset); +} + +Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName( + const LoaderSectionHeader64 *LoaderSecHeader64) const { + return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset); +} + uintptr_t XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, uint32_t Distance) { @@ -383,7 +414,7 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { Twine::utohexstr(OffsetToRaw) + " and size 0x" + Twine::utohexstr(SectionSize) + " goes past the end of the file"); - return makeArrayRef(ContentStart,SectionSize); + return ArrayRef(ContentStart, SectionSize); } uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { @@ -392,41 +423,58 @@ uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { return Result; } -Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const { - uint64_t OffsetToLoaderSection = 0; - uint64_t SizeOfLoaderSection = 0; +uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const { + if (is64Bit()) + return toSection64(Sec)->FileOffsetToRawData; - if (is64Bit()) { - for (const auto &Sec64 : sections64()) - if (Sec64.getSectionType() == XCOFF::STYP_LOADER) { - OffsetToLoaderSection = Sec64.FileOffsetToRawData; - SizeOfLoaderSection = Sec64.SectionSize; - break; - } - } else { - for (const auto &Sec32 : sections32()) - if (Sec32.getSectionType() == XCOFF::STYP_LOADER) { - OffsetToLoaderSection = Sec32.FileOffsetToRawData; - SizeOfLoaderSection = Sec32.SectionSize; - break; - } - } + return toSection32(Sec)->FileOffsetToRawData; +} + +Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData( + XCOFF::SectionTypeFlags SectType) const { + DataRefImpl DRI = getSectionByType(SectType); - // No loader section is not an error. - if (!SizeOfLoaderSection) + if (DRI.p == 0) // No section is not an error. return 0; - uintptr_t LoderSectionStart = - reinterpret_cast<uintptr_t>(base() + OffsetToLoaderSection); - if (Error E = - Binary::checkOffset(Data, LoderSectionStart, SizeOfLoaderSection)) - return createError(toString(std::move(E)) + - ": loader section with offset 0x" + - Twine::utohexstr(OffsetToLoaderSection) + - " and size 0x" + Twine::utohexstr(SizeOfLoaderSection) + + uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI); + uint64_t SizeOfSection = getSectionSize(DRI); + + uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset); + if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) { + SmallString<32> UnknownType; + Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">") + .toVector(UnknownType); + const char *SectionName = UnknownType.c_str(); + + switch (SectType) { +#define ECASE(Value, String) \ + case XCOFF::Value: \ + SectionName = String; \ + break + + ECASE(STYP_PAD, "pad"); + ECASE(STYP_DWARF, "dwarf"); + ECASE(STYP_TEXT, "text"); + ECASE(STYP_DATA, "data"); + ECASE(STYP_BSS, "bss"); + ECASE(STYP_EXCEPT, "expect"); + ECASE(STYP_INFO, "info"); + ECASE(STYP_TDATA, "tdata"); + ECASE(STYP_TBSS, "tbss"); + ECASE(STYP_LOADER, "loader"); + ECASE(STYP_DEBUG, "debug"); + ECASE(STYP_TYPCHK, "typchk"); + ECASE(STYP_OVRFLO, "ovrflo"); +#undef ECASE + } + return createError(toString(std::move(E)) + ": " + SectionName + + " section with offset 0x" + + Twine::utohexstr(SectionOffset) + " and size 0x" + + Twine::utohexstr(SizeOfSection) + " goes past the end of the file"); - - return LoderSectionStart; + } + return SectionStart; } bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { @@ -664,7 +712,7 @@ Triple::ArchType XCOFFObjectFile::getArch() const { return is64Bit() ? Triple::ppc64 : Triple::ppc; } -SubtargetFeatures XCOFFObjectFile::getFeatures() const { +Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const { return SubtargetFeatures(); } @@ -738,6 +786,22 @@ Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { return DRI; } +DataRefImpl +XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const { + DataRefImpl DRI; + auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t { + for (const auto &Sec : Sections) + if (Sec.getSectionType() == SectType) + return reinterpret_cast<uintptr_t>(&Sec); + return uintptr_t(0); + }; + if (is64Bit()) + DRI.p = GetSectionAddr(sections64()); + else + DRI.p = GetSectionAddr(sections32()); + return DRI; +} + Expected<StringRef> XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { const int16_t SectionNum = SymEntPtr.getSectionNumber(); @@ -960,6 +1024,31 @@ Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); } +template <typename ExceptEnt> +Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const { + assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) || + (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))); + + Expected<uintptr_t> ExceptionSectOrErr = + getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT); + if (!ExceptionSectOrErr) + return ExceptionSectOrErr.takeError(); + + DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT); + if (DRI.p == 0) + return ArrayRef<ExceptEnt>(); + + ExceptEnt *ExceptEntStart = + reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr); + return ArrayRef<ExceptEnt>( + ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt)); +} + +template Expected<ArrayRef<ExceptionSectionEntry32>> +XCOFFObjectFile::getExceptionEntries() const; +template Expected<ArrayRef<ExceptionSectionEntry64>> +XCOFFObjectFile::getExceptionEntries() const; + Expected<XCOFFStringTable> XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { // If there is a string table, then the buffer must contain at least 4 bytes @@ -997,7 +1086,8 @@ XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { // This function returns the import file table. Each entry in the import file // table consists of: "path_name\0base_name\0archive_member_name\0". Expected<StringRef> XCOFFObjectFile::getImportFileTable() const { - Expected<uintptr_t> LoaderSectionAddrOrError = getLoaderSectionAddress(); + Expected<uintptr_t> LoaderSectionAddrOrError = + getSectionFileOffsetToRawData(XCOFF::STYP_LOADER); if (!LoaderSectionAddrOrError) return LoaderSectionAddrOrError.takeError(); |