aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Object
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object')
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Archive.cpp12
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Binary.cpp1
-rw-r--r--contrib/llvm-project/llvm/lib/Object/BuildID.cpp93
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp9
-rw-r--r--contrib/llvm-project/llvm/lib/Object/DXContainer.cpp95
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Decompressor.cpp35
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ELF.cpp23
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp126
-rw-r--r--contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp508
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Minidump.cpp9
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp182
-rw-r--r--contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Object/RecordStreamer.h4
-rw-r--r--contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp65
-rw-r--r--contrib/llvm-project/llvm/lib/Object/SymbolicFile.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WindowsMachineFlag.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp5
-rw-r--r--contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp156
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();