aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h40
-rw-r--r--include/llvm/Object/ArchiveWriter.h10
-rw-r--r--include/llvm/Object/Binary.h22
-rw-r--r--include/llvm/Object/COFF.h20
-rw-r--r--include/llvm/Object/COFFImportFile.h24
-rw-r--r--include/llvm/Object/COFFModuleDefinition.h7
-rw-r--r--include/llvm/Object/CVDebugRecord.h7
-rw-r--r--include/llvm/Object/Decompressor.h7
-rw-r--r--include/llvm/Object/ELF.h158
-rw-r--r--include/llvm/Object/ELFObjectFile.h133
-rw-r--r--include/llvm/Object/ELFTypes.h9
-rw-r--r--include/llvm/Object/Error.h7
-rw-r--r--include/llvm/Object/IRObjectFile.h10
-rw-r--r--include/llvm/Object/IRSymtab.h25
-rw-r--r--include/llvm/Object/MachO.h76
-rw-r--r--include/llvm/Object/MachOUniversal.h7
-rw-r--r--include/llvm/Object/Minidump.h165
-rw-r--r--include/llvm/Object/ModuleSymbolTable.h7
-rw-r--r--include/llvm/Object/ObjectFile.h90
-rw-r--r--include/llvm/Object/RelocVisitor.h351
-rw-r--r--include/llvm/Object/RelocationResolver.h42
-rw-r--r--include/llvm/Object/StackMapParser.h50
-rw-r--r--include/llvm/Object/SymbolSize.h7
-rw-r--r--include/llvm/Object/SymbolicFile.h14
-rw-r--r--include/llvm/Object/Wasm.h80
-rw-r--r--include/llvm/Object/WasmTraits.h7
-rw-r--r--include/llvm/Object/WindowsMachineFlag.h33
-rw-r--r--include/llvm/Object/WindowsResource.h47
-rw-r--r--include/llvm/Object/XCOFFObjectFile.h268
29 files changed, 1033 insertions, 690 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 9ef1e4875191f..c40278a4f923b 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -1,9 +1,8 @@
//===- Archive.h - ar archive file format -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -16,6 +15,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/fallible_iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Chrono.h"
@@ -143,44 +143,38 @@ public:
getAsBinary(LLVMContext *Context = nullptr) const;
};
- class child_iterator {
+ class ChildFallibleIterator {
Child C;
- Error *E = nullptr;
public:
- child_iterator() : C(Child(nullptr, nullptr, nullptr)) {}
- child_iterator(const Child &C, Error *E) : C(C), E(E) {}
+ ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {}
+ ChildFallibleIterator(const Child &C) : C(C) {}
const Child *operator->() const { return &C; }
const Child &operator*() const { return C; }
- bool operator==(const child_iterator &other) const {
+ bool operator==(const ChildFallibleIterator &other) const {
// Ignore errors here: If an error occurred during increment then getNext
// will have been set to child_end(), and the following comparison should
// do the right thing.
return C == other.C;
}
- bool operator!=(const child_iterator &other) const {
+ bool operator!=(const ChildFallibleIterator &other) const {
return !(*this == other);
}
- // Code in loops with child_iterators must check for errors on each loop
- // iteration. And if there is an error break out of the loop.
- child_iterator &operator++() { // Preincrement
- assert(E && "Can't increment iterator with no Error attached");
- ErrorAsOutParameter ErrAsOutParam(E);
- if (auto ChildOrErr = C.getNext())
- C = *ChildOrErr;
- else {
- C = C.getParent()->child_end().C;
- *E = ChildOrErr.takeError();
- E = nullptr;
- }
- return *this;
+ Error inc() {
+ auto NextChild = C.getNext();
+ if (!NextChild)
+ return NextChild.takeError();
+ C = std::move(*NextChild);
+ return Error::success();
}
};
+ using child_iterator = fallible_iterator<ChildFallibleIterator>;
+
class Symbol {
const Archive *Parent;
uint32_t SymbolIndex;
diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h
index 495b943d04c00..9e6daf2da36e9 100644
--- a/include/llvm/Object/ArchiveWriter.h
+++ b/include/llvm/Object/ArchiveWriter.h
@@ -1,9 +1,8 @@
//===- ArchiveWriter.h - ar archive file format writer ----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -27,7 +26,6 @@ struct NewArchiveMember {
sys::TimePoint<std::chrono::seconds> ModTime;
unsigned UID = 0, GID = 0, Perms = 0644;
- bool IsNew = false;
NewArchiveMember() = default;
NewArchiveMember(MemoryBufferRef BufRef);
@@ -38,6 +36,8 @@ struct NewArchiveMember {
bool Deterministic);
};
+Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To);
+
Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
bool WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 99745e24b8c86..3c3e977baff47 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -1,9 +1,8 @@
//===- Binary.h - A generic binary file -------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -14,6 +13,7 @@
#ifndef LLVM_OBJECT_BINARY_H
#define LLVM_OBJECT_BINARY_H
+#include "llvm-c/Types.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/Error.h"
@@ -42,7 +42,9 @@ protected:
ID_Archive,
ID_MachOUniversalBinary,
ID_COFFImportFile,
- ID_IR, // LLVM IR
+ ID_IR, // LLVM IR
+
+ ID_Minidump,
ID_WinRes, // Windows resource (.res) file.
@@ -50,6 +52,9 @@ protected:
ID_StartObjects,
ID_COFF,
+ ID_XCOFF32, // AIX XCOFF 32-bit
+ ID_XCOFF64, // AIX XCOFF 64-bit
+
ID_ELF32L, // ELF 32-bit, little endian
ID_ELF32B, // ELF 32-bit, big endian
ID_ELF64L, // ELF 64-bit, little endian
@@ -118,6 +123,8 @@ public:
return TypeID == ID_COFF;
}
+ bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; }
+
bool isWasm() const { return TypeID == ID_Wasm; }
bool isCOFFImportFile() const {
@@ -128,6 +135,8 @@ public:
return TypeID == ID_IR;
}
+ bool isMinidump() const { return TypeID == ID_Minidump; }
+
bool isLittleEndian() const {
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
@@ -156,6 +165,9 @@ public:
}
};
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef)
+
/// Create a Binary from Source, autodetecting the file type.
///
/// @param Source The data to create the Binary from.
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index b753d261a0fc8..c53cbc46c7476 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -1,9 +1,8 @@
//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -898,13 +897,12 @@ protected:
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
- std::error_code getSectionName(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
- std::error_code getSectionContents(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<ArrayRef<uint8_t>>
+ getSectionContents(DataRefImpl Sec) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
@@ -1034,10 +1032,10 @@ public:
ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const;
- std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
+ Expected<StringRef> getSectionName(const coff_section *Sec) const;
uint64_t getSectionSize(const coff_section *Sec) const;
- std::error_code getSectionContents(const coff_section *Sec,
- ArrayRef<uint8_t> &Res) const;
+ Error getSectionContents(const coff_section *Sec,
+ ArrayRef<uint8_t> &Res) const;
uint64_t getImageBase() const;
std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h
index 0a4556ad88845..5aa8364111180 100644
--- a/include/llvm/Object/COFFImportFile.h
+++ b/include/llvm/Object/COFFImportFile.h
@@ -1,9 +1,8 @@
//===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -37,12 +36,11 @@ public:
void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; }
- std::error_code printSymbolName(raw_ostream &OS,
- DataRefImpl Symb) const override {
+ Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override {
if (Symb.p == 0)
OS << "__imp_";
OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header));
- return std::error_code();
+ return Error::success();
}
uint32_t getSymbolFlags(DataRefImpl Symb) const override {
@@ -71,9 +69,21 @@ private:
};
struct COFFShortExport {
+ /// The name of the export as specified in the .def file or on the command
+ /// line, i.e. "foo" in "/EXPORT:foo", and "bar" in "/EXPORT:foo=bar". This
+ /// may lack mangling, such as underscore prefixing and stdcall suffixing.
std::string Name;
+
+ /// The external, exported name. Only non-empty when export renaming is in
+ /// effect, i.e. "foo" in "/EXPORT:foo=bar".
std::string ExtName;
+
+ /// The real, mangled symbol name from the object file. Given
+ /// "/export:foo=bar", this could be "_bar@8" if bar is stdcall.
std::string SymbolName;
+
+ /// Creates a weak alias. This is the name of the weak aliasee. In a .def
+ /// file, this is "baz" in "EXPORTS\nfoo = bar == baz".
std::string AliasTarget;
uint16_t Ordinal = 0;
diff --git a/include/llvm/Object/COFFModuleDefinition.h b/include/llvm/Object/COFFModuleDefinition.h
index be139a2833b0b..ab52259fea1a3 100644
--- a/include/llvm/Object/COFFModuleDefinition.h
+++ b/include/llvm/Object/COFFModuleDefinition.h
@@ -1,9 +1,8 @@
//===--- COFFModuleDefinition.h ---------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/llvm/Object/CVDebugRecord.h b/include/llvm/Object/CVDebugRecord.h
index faad72c0df29f..d41c7391f7019 100644
--- a/include/llvm/Object/CVDebugRecord.h
+++ b/include/llvm/Object/CVDebugRecord.h
@@ -1,9 +1,8 @@
//===- CVDebugRecord.h ------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/Object/Decompressor.h b/include/llvm/Object/Decompressor.h
index 2a77d2ffbf687..cc918481b308f 100644
--- a/include/llvm/Object/Decompressor.h
+++ b/include/llvm/Object/Decompressor.h
@@ -1,9 +1,8 @@
//===-- Decompressor.h ------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===/
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index bcdc190cc7dcc..cf8e4529bad96 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -1,9 +1,8 @@
//===- ELF.h - ELF object file implementation -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -45,10 +44,26 @@ getElfArchType(StringRef Object) {
(uint8_t)Object[ELF::EI_DATA]);
}
-static inline Error createError(StringRef Err) {
+static inline Error createError(const Twine &Err) {
return make_error<StringError>(Err, object_error::parse_failed);
}
+template <class ELFT> class ELFFile;
+
+template <class ELFT>
+std::string getSecIndexForError(const ELFFile<ELFT> *Obj,
+ const typename ELFT::Shdr *Sec) {
+ auto TableOrErr = Obj->sections();
+ if (TableOrErr)
+ return "[index " + std::to_string(Sec - &TableOrErr->front()) + "]";
+ // To make this helper be more convenient for error reporting purposes we
+ // drop the error. But really it should never be triggered. Before this point,
+ // our code should have called 'sections()' and reported a proper error on
+ // failure.
+ llvm::consumeError(TableOrErr.takeError());
+ return "[unknown index]";
+}
+
template <class ELFT>
class ELFFile {
public:
@@ -80,9 +95,7 @@ public:
using Elf_Relr_Range = typename ELFT::RelrRange;
using Elf_Phdr_Range = typename ELFT::PhdrRange;
- const uint8_t *base() const {
- return reinterpret_cast<const uint8_t *>(Buf.data());
- }
+ const uint8_t *base() const { return Buf.bytes_begin(); }
size_t getBufSize() const { return Buf.size(); }
@@ -115,8 +128,8 @@ public:
SmallVectorImpl<char> &Result) const;
uint32_t getRelativeRelocationType() const;
- const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const;
- const char *getDynamicTagAsString(uint64_t Type) const;
+ std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const;
+ std::string getDynamicTagAsString(uint64_t Type) const;
/// Get the symbol for a given relocation.
Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
@@ -165,11 +178,16 @@ public:
/// Iterate over program header table.
Expected<Elf_Phdr_Range> program_headers() const {
if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
- return createError("invalid e_phentsize");
+ return createError("invalid e_phentsize: " +
+ Twine(getHeader()->e_phentsize));
if (getHeader()->e_phoff +
(getHeader()->e_phnum * getHeader()->e_phentsize) >
getBufSize())
- return createError("program headers longer than binary");
+ return createError("program headers are longer than binary of size " +
+ Twine(getBufSize()) + ": e_phoff = 0x" +
+ Twine::utohexstr(getHeader()->e_phoff) +
+ ", e_phnum = " + Twine(getHeader()->e_phnum) +
+ ", e_phentsize = " + Twine(getHeader()->e_phentsize));
auto *Begin =
reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff);
return makeArrayRef(Begin, Begin + getHeader()->e_phnum);
@@ -183,12 +201,12 @@ public:
/// \param Err [out] an error to support fallible iteration, which should
/// be checked after iteration ends.
Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const {
- if (Phdr.p_type != ELF::PT_NOTE) {
- Err = createError("attempt to iterate notes of non-note program header");
- return Elf_Note_Iterator(Err);
- }
+ assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE");
+ ErrorAsOutParameter ErrAsOutParam(&Err);
if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) {
- Err = createError("invalid program header offset/size");
+ Err = createError("PT_NOTE header has invalid offset (0x" +
+ Twine::utohexstr(Phdr.p_offset) + ") or size (0x" +
+ Twine::utohexstr(Phdr.p_filesz) + ")");
return Elf_Note_Iterator(Err);
}
return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err);
@@ -202,12 +220,13 @@ public:
/// \param Err [out] an error to support fallible iteration, which should
/// be checked after iteration ends.
Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const {
- if (Shdr.sh_type != ELF::SHT_NOTE) {
- Err = createError("attempt to iterate notes of non-note section");
- return Elf_Note_Iterator(Err);
- }
+ assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE");
+ ErrorAsOutParameter ErrAsOutParam(&Err);
if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) {
- Err = createError("invalid section offset/size");
+ Err = createError("SHT_NOTE section " + getSecIndexForError(this, &Shdr) +
+ " has invalid offset (0x" +
+ Twine::utohexstr(Shdr.sh_offset) + ") or size (0x" +
+ Twine::utohexstr(Shdr.sh_size) + ")");
return Elf_Note_Iterator(Err);
}
return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err);
@@ -274,7 +293,7 @@ template <class ELFT>
inline Expected<const typename ELFT::Shdr *>
getSection(typename ELFT::ShdrRange Sections, uint32_t Index) {
if (Index >= Sections.size())
- return createError("invalid section index");
+ return createError("invalid section index: " + Twine(Index));
return &Sections[Index];
}
@@ -286,7 +305,10 @@ getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym,
assert(Sym->st_shndx == ELF::SHN_XINDEX);
unsigned Index = Sym - FirstSym;
if (Index >= ShndxTable.size())
- return createError("index past the end of the symbol table");
+ return createError(
+ "extended symbol index (" + Twine(Index) +
+ ") is past the end of the SHT_SYMTAB_SHNDX section of size " +
+ Twine(ShndxTable.size()));
// The size of the table was checked in getSHNDXTable.
return ShndxTable[Index];
@@ -333,20 +355,18 @@ ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols,
}
template <class ELFT>
-inline Expected<const typename ELFT::Sym *>
-getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) {
- if (Index >= Symbols.size())
- return createError("invalid symbol index");
- return &Symbols[Index];
-}
-
-template <class ELFT>
Expected<const typename ELFT::Sym *>
ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const {
- auto SymtabOrErr = symbols(Sec);
- if (!SymtabOrErr)
- return SymtabOrErr.takeError();
- return object::getSymbol<ELFT>(*SymtabOrErr, Index);
+ auto SymsOrErr = symbols(Sec);
+ if (!SymsOrErr)
+ return SymsOrErr.takeError();
+
+ Elf_Sym_Range Symbols = *SymsOrErr;
+ if (Index >= Symbols.size())
+ return createError("unable to get symbol from section " +
+ getSecIndexForError(this, Sec) +
+ ": invalid symbol index (" + Twine(Index) + ")");
+ return &Symbols[Index];
}
template <class ELFT>
@@ -354,18 +374,26 @@ template <typename T>
Expected<ArrayRef<T>>
ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const {
if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1)
- return createError("invalid sh_entsize");
+ return createError("section " + getSecIndexForError(this, Sec) +
+ " has an invalid sh_entsize: " + Twine(Sec->sh_entsize));
uintX_t Offset = Sec->sh_offset;
uintX_t Size = Sec->sh_size;
if (Size % sizeof(T))
- return createError("size is not a multiple of sh_entsize");
+ return createError("section " + getSecIndexForError(this, Sec) +
+ " has an invalid sh_size (" + Twine(Size) +
+ ") which is not a multiple of its sh_entsize (" +
+ Twine(Sec->sh_entsize) + ")");
if ((std::numeric_limits<uintX_t>::max() - Offset < Size) ||
Offset + Size > Buf.size())
- return createError("invalid section offset");
+ return createError("section " + getSecIndexForError(this, Sec) +
+ " has a sh_offset (0x" + Twine::utohexstr(Offset) +
+ ") + sh_size (0x" + Twine(Size) +
+ ") that cannot be represented");
if (Offset % alignof(T))
+ // TODO: this error is untested.
return createError("unaligned data");
const T *Start = reinterpret_cast<const T *>(base() + Offset);
@@ -438,8 +466,10 @@ ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const {
if (!Index) // no section string table.
return "";
+ // TODO: Test a case when the sh_link of the section with index 0 is broken.
if (Index >= Sections.size())
- return createError("invalid section index");
+ return createError("section header string table index " + Twine(Index) +
+ " does not exist");
return getStringTable(&Sections[Index]);
}
@@ -448,7 +478,9 @@ template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
template <class ELFT>
Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
if (sizeof(Elf_Ehdr) > Object.size())
- return createError("Invalid buffer");
+ return createError("invalid buffer: the size (" + Twine(Object.size()) +
+ ") is smaller than an ELF header (" +
+ Twine(sizeof(Elf_Ehdr)) + ")");
return ELFFile(Object);
}
@@ -459,16 +491,18 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
return ArrayRef<Elf_Shdr>();
if (getHeader()->e_shentsize != sizeof(Elf_Shdr))
- return createError(
- "invalid section header entry size (e_shentsize) in ELF header");
+ return createError("invalid e_shentsize in ELF header: " +
+ Twine(getHeader()->e_shentsize));
const uint64_t FileSize = Buf.size();
-
if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
- return createError("section header table goes past the end of the file");
+ return createError(
+ "section header table goes past the end of the file: e_shoff = 0x" +
+ Twine::utohexstr(SectionTableOffset));
// Invalid address alignment of section headers
if (SectionTableOffset & (alignof(Elf_Shdr) - 1))
+ // TODO: this error is untested.
return createError("invalid alignment of section headers");
const Elf_Shdr *First =
@@ -479,6 +513,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
NumSections = First->sh_size;
if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
+ // TODO: this error is untested.
return createError("section table goes past the end of file");
const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
@@ -505,10 +540,14 @@ template <typename T>
Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section,
uint32_t Entry) const {
if (sizeof(T) != Section->sh_entsize)
+ // TODO: this error is untested.
return createError("invalid sh_entsize");
size_t Pos = Section->sh_offset + Entry * sizeof(T);
if (Pos + sizeof(T) > Buf.size())
- return createError("invalid section offset");
+ return createError("unable to access section " +
+ getSecIndexForError(this, Section) + " data at 0x" +
+ Twine::utohexstr(Pos) +
+ ": offset goes past the end of file");
return reinterpret_cast<const T *>(base() + Pos);
}
@@ -534,6 +573,7 @@ ELFFile<ELFT>::getSection(const StringRef SectionName) const {
if (*SecNameOrErr == SectionName)
return &Sec;
}
+ // TODO: this error is untested.
return createError("invalid section name");
}
@@ -541,15 +581,24 @@ template <class ELFT>
Expected<StringRef>
ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
if (Section->sh_type != ELF::SHT_STRTAB)
- return createError("invalid sh_type for string table, expected SHT_STRTAB");
+ return createError("invalid sh_type for string table section " +
+ getSecIndexForError(this, Section) +
+ ": expected SHT_STRTAB, but got " +
+ object::getELFSectionTypeName(getHeader()->e_machine,
+ Section->sh_type));
auto V = getSectionContentsAsArray<char>(Section);
if (!V)
return V.takeError();
ArrayRef<char> Data = *V;
if (Data.empty())
+ // TODO: this error is untested.
return createError("empty string table");
if (Data.back() != '\0')
- return createError("string table non-null terminated");
+ return createError(object::getELFSectionTypeName(getHeader()->e_machine,
+ Section->sh_type) +
+ " string table section " +
+ getSecIndexForError(this, Section) +
+ " is non-null terminated");
return StringRef(Data.begin(), Data.size());
}
@@ -577,9 +626,13 @@ ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section,
const Elf_Shdr &SymTable = **SymTableOrErr;
if (SymTable.sh_type != ELF::SHT_SYMTAB &&
SymTable.sh_type != ELF::SHT_DYNSYM)
+ // TODO: this error is untested.
return createError("invalid sh_type");
if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
- return createError("invalid section contents size");
+ return createError("SHT_SYMTAB_SHNDX section has sh_size (" +
+ Twine(SymTable.sh_size) +
+ ") which is not equal to the number of symbols (" +
+ Twine(V.size()) + ")");
return V;
}
@@ -598,6 +651,7 @@ ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec,
Elf_Shdr_Range Sections) const {
if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)
+ // TODO: this error is untested.
return createError(
"invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");
auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link);
@@ -625,7 +679,11 @@ Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section,
if (Offset == 0)
return StringRef();
if (Offset >= DotShstrtab.size())
- return createError("invalid string offset");
+ return createError("a section " + getSecIndexForError(this, Section) +
+ " has an invalid sh_name (0x" +
+ Twine::utohexstr(Offset) +
+ ") offset which goes past the end of the "
+ "section name string table");
return StringRef(DotShstrtab.data() + Offset);
}
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 0f620681cd99a..86c015efd704e 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -1,9 +1,8 @@
//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -42,6 +41,9 @@
namespace llvm {
namespace object {
+constexpr int NumElfSymbolTypes = 8;
+extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes];
+
class elf_symbol_iterator;
class ELFObjectFileBase : public ObjectFile {
@@ -52,8 +54,8 @@ class ELFObjectFileBase : public ObjectFile {
protected:
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
- virtual uint16_t getEMachine() const = 0;
virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0;
+ virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0;
virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0;
virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0;
@@ -62,6 +64,7 @@ protected:
virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0;
virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
+ virtual Error getBuildAttributes(ARMAttributeParser &Attributes) const = 0;
public:
using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>;
@@ -87,6 +90,8 @@ public:
virtual uint16_t getEType() const = 0;
+ virtual uint16_t getEMachine() const = 0;
+
std::vector<std::pair<DataRefImpl, uint64_t>> getPltAddresses() const;
};
@@ -142,6 +147,10 @@ public:
return getObject()->getSymbolSize(getRawDataRefImpl());
}
+ uint8_t getBinding() const {
+ return getObject()->getSymbolBinding(getRawDataRefImpl());
+ }
+
uint8_t getOther() const {
return getObject()->getSymbolOther(getRawDataRefImpl());
}
@@ -149,6 +158,16 @@ public:
uint8_t getELFType() const {
return getObject()->getSymbolELFType(getRawDataRefImpl());
}
+
+ StringRef getELFTypeName() const {
+ uint8_t Type = getELFType();
+ for (auto &EE : ElfSymbolTypes) {
+ if (EE.Value == Type) {
+ return EE.AltName;
+ }
+ }
+ return "";
+ }
};
class elf_symbol_iterator : public symbol_iterator {
@@ -239,6 +258,7 @@ protected:
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ uint8_t getSymbolBinding(DataRefImpl Symb) const override;
uint8_t getSymbolOther(DataRefImpl Symb) const override;
uint8_t getSymbolELFType(DataRefImpl Symb) const override;
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
@@ -247,13 +267,12 @@ protected:
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
void moveSectionNext(DataRefImpl &Sec) const override;
- std::error_code getSectionName(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
- std::error_code getSectionContents(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<ArrayRef<uint8_t>>
+ getSectionContents(DataRefImpl Sec) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
@@ -341,6 +360,28 @@ protected:
(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED));
}
+ Error getBuildAttributes(ARMAttributeParser &Attributes) const override {
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return SectionsOrErr.takeError();
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) {
+ auto ErrorOrContents = EF.getSectionContents(&Sec);
+ if (!ErrorOrContents)
+ return ErrorOrContents.takeError();
+
+ auto Contents = ErrorOrContents.get();
+ if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
+ return Error::success();
+
+ Attributes.Parse(Contents, ELFT::TargetEndianness == support::little);
+ break;
+ }
+ }
+ return Error::success();
+ }
+
// This flag is used for classof, to distinguish ELFObjectFile from
// its subclass. If more subclasses will be created, this flag will
// have to become an enum.
@@ -382,28 +423,6 @@ public:
unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; }
- std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override {
- auto SectionsOrErr = EF.sections();
- if (!SectionsOrErr)
- return errorToErrorCode(SectionsOrErr.takeError());
-
- for (const Elf_Shdr &Sec : *SectionsOrErr) {
- if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) {
- auto ErrorOrContents = EF.getSectionContents(&Sec);
- if (!ErrorOrContents)
- return errorToErrorCode(ErrorOrContents.takeError());
-
- auto Contents = ErrorOrContents.get();
- if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
- return std::error_code();
-
- Attributes.Parse(Contents, ELFT::TargetEndianness == support::little);
- break;
- }
- }
- return std::error_code();
- }
-
const ELFFile<ELFT> *getELFFile() const { return &EF; }
bool isDyldType() const { return isDyldELFObject; }
@@ -441,7 +460,16 @@ Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
auto SymStrTabOrErr = EF.getStringTable(StringTableSec);
if (!SymStrTabOrErr)
return SymStrTabOrErr.takeError();
- return ESym->getName(*SymStrTabOrErr);
+ Expected<StringRef> Name = ESym->getName(*SymStrTabOrErr);
+
+ // If the symbol name is empty use the section name.
+ if ((!Name || Name->empty()) && ESym->getType() == ELF::STT_SECTION) {
+ StringRef SecName;
+ Expected<section_iterator> Sec = getSymbolSection(Sym);
+ if (Sec && !(*Sec)->getName(SecName))
+ return SecName;
+ }
+ return Name;
}
template <class ELFT>
@@ -533,6 +561,11 @@ uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
}
template <class ELFT>
+uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const {
+ return getSymbol(Symb)->getBinding();
+}
+
+template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const {
return getSymbol(Symb)->st_other;
}
@@ -654,13 +687,8 @@ void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const {
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
- StringRef &Result) const {
- auto Name = EF.getSectionName(&*getSection(Sec));
- if (!Name)
- return errorToErrorCode(Name.takeError());
- Result = *Name;
- return std::error_code();
+Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const {
+ return EF.getSectionName(&*getSection(Sec));
}
template <class ELFT>
@@ -685,16 +713,15 @@ uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const {
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
- StringRef &Result) const {
+Expected<ArrayRef<uint8_t>>
+ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const {
const Elf_Shdr *EShdr = getSection(Sec);
if (std::error_code EC =
checkOffset(getMemoryBufferRef(),
(uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size))
- return EC;
- Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
- return std::error_code();
+ return errorCodeToError(EC);
+ return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset,
+ EShdr->sh_size);
}
template <class ELFT>
@@ -750,7 +777,7 @@ ELFObjectFile<ELFT>::dynamic_relocation_sections() const {
}
}
for (const Elf_Shdr &Sec : *SectionsOrErr) {
- if (is_contained(Offsets, Sec.sh_offset))
+ if (is_contained(Offsets, Sec.sh_addr))
Res.emplace_back(toDRI(&Sec), this);
}
return Res;
@@ -925,15 +952,13 @@ ELFObjectFile<ELFT>::create(MemoryBufferRef Object) {
for (const Elf_Shdr &Sec : *SectionsOrErr) {
switch (Sec.sh_type) {
case ELF::SHT_DYNSYM: {
- if (DotDynSymSec)
- return createError("More than one dynamic symbol table!");
- DotDynSymSec = &Sec;
+ if (!DotDynSymSec)
+ DotDynSymSec = &Sec;
break;
}
case ELF::SHT_SYMTAB: {
- if (DotSymtabSec)
- return createError("More than one static symbol table!");
- DotSymtabSec = &Sec;
+ if (!DotSymtabSec)
+ DotSymtabSec = &Sec;
break;
}
case ELF::SHT_SYMTAB_SHNDX: {
@@ -967,7 +992,9 @@ ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other)
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const {
- DataRefImpl Sym = toDRI(DotSymtabSec, 0);
+ DataRefImpl Sym =
+ toDRI(DotSymtabSec,
+ DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0);
return basic_symbol_iterator(SymbolRef(Sym, this));
}
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index ec3c8e7bae465..5552208b1f8a7 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -1,9 +1,8 @@
//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -593,9 +592,9 @@ class Elf_Note_Impl {
template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl;
+public:
Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {}
-public:
/// Get the note's name, excluding the terminating null byte.
StringRef getName() const {
if (!Nhdr.n_namesz)
diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h
index a15f8b9236eb2..b7bbf06fc86de 100644
--- a/include/llvm/Object/Error.h
+++ b/include/llvm/Object/Error.h
@@ -1,9 +1,8 @@
//===- Error.h - system_error extensions for Object -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h
index 993359b766a17..08b92f1bae50b 100644
--- a/include/llvm/Object/IRObjectFile.h
+++ b/include/llvm/Object/IRObjectFile.h
@@ -1,9 +1,8 @@
//===- IRObjectFile.h - LLVM IR object file implementation ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -38,8 +37,7 @@ class IRObjectFile : public SymbolicFile {
public:
~IRObjectFile() override;
void moveSymbolNext(DataRefImpl &Symb) const override;
- std::error_code printSymbolName(raw_ostream &OS,
- DataRefImpl Symb) const override;
+ Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
diff --git a/include/llvm/Object/IRSymtab.h b/include/llvm/Object/IRSymtab.h
index 5f6a024cd1329..0bbfc932493c6 100644
--- a/include/llvm/Object/IRSymtab.h
+++ b/include/llvm/Object/IRSymtab.h
@@ -1,9 +1,8 @@
//===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -126,12 +125,13 @@ struct Uncommon {
Str SectionName;
};
+
struct Header {
/// Version number of the symtab format. This number should be incremented
/// when the format changes, but it does not need to be incremented if a
/// change to LLVM would cause it to create a different symbol table.
Word Version;
- enum { kCurrentVersion = 1 };
+ enum { kCurrentVersion = 2 };
/// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION).
/// Consumers should rebuild the symbol table from IR if the producer's
@@ -148,6 +148,9 @@ struct Header {
/// COFF-specific: linker directives.
Str COFFLinkerOpts;
+
+ /// Dependent Library Specifiers
+ Range<Str> DependentLibraries;
};
} // end namespace storage
@@ -232,6 +235,7 @@ class Reader {
ArrayRef<storage::Comdat> Comdats;
ArrayRef<storage::Symbol> Symbols;
ArrayRef<storage::Uncommon> Uncommons;
+ ArrayRef<storage::Str> DependentLibraries;
StringRef str(storage::Str S) const { return S.get(Strtab); }
@@ -252,6 +256,7 @@ public:
Comdats = range(header().Comdats);
Symbols = range(header().Symbols);
Uncommons = range(header().Uncommons);
+ DependentLibraries = range(header().DependentLibraries);
}
using symbol_range = iterator_range<object::content_iterator<SymbolRef>>;
@@ -284,6 +289,16 @@ public:
/// COFF-specific: returns linker options specified in the input file.
StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); }
+
+ /// Returns dependent library specifiers
+ std::vector<StringRef> getDependentLibraries() const {
+ std::vector<StringRef> Specifiers;
+ Specifiers.reserve(DependentLibraries.size());
+ for (auto S : DependentLibraries) {
+ Specifiers.push_back(str(S));
+ }
+ return Specifiers;
+ }
};
/// Ephemeral symbols produced by Reader::symbols() and
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index c2f4f40629349..ca9512f21706d 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -1,9 +1,8 @@
//===- MachO.h - MachO object file implementation ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -134,11 +133,9 @@ public:
BindRebaseSegInfo(const MachOObjectFile *Obj);
// Used to check a Mach-O Bind or Rebase entry for errors when iterating.
- const char *checkSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
- bool endInvalid);
- const char *checkCountAndSkip(uint32_t Count, uint32_t Skip,
- uint8_t PointerSize, int32_t SegIndex,
- uint64_t SegOffset);
+ const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
+ uint8_t PointerSize, uint32_t Count=1,
+ uint32_t Skip=0);
// Used with valid SegIndex/SegOffset values from checked entries.
StringRef segmentName(int32_t SegIndex);
StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
@@ -296,13 +293,12 @@ public:
unsigned getSectionID(SectionRef Sec) const;
void moveSectionNext(DataRefImpl &Sec) const override;
- std::error_code getSectionName(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
- std::error_code getSectionContents(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<ArrayRef<uint8_t>>
+ getSectionContents(DataRefImpl Sec) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
Expected<SectionRef> getSection(unsigned SectionIndex) const;
Expected<SectionRef> getSection(StringRef SectionName) const;
@@ -413,36 +409,32 @@ public:
bool is64,
MachOBindEntry::Kind);
- /// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
- /// validate a MachOBindEntry.
- const char *BindEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
- bool endInvalid) const {
- return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
- endInvalid);
- }
- /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
- /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode.
- const char *BindEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
- uint8_t PointerSize, int32_t SegIndex,
- uint64_t SegOffset) const {
- return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
- SegIndex, SegOffset);
+ // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
+ // that fully contains a pointer at that location. Multiple fixups in a bind
+ // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
+ // be tested via the Count and Skip parameters.
+ //
+ // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry.
+ const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
+ uint8_t PointerSize, uint32_t Count=1,
+ uint32_t Skip=0) const {
+ return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
+ PointerSize, Count, Skip);
}
- /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to
- /// validate a MachORebaseEntry.
- const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
- bool endInvalid) const {
- return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
- endInvalid);
- }
- /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
- /// the REBASE_OPCODE_DO_*_TIMES* opcodes.
- const char *RebaseEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
- uint8_t PointerSize, int32_t SegIndex,
- uint64_t SegOffset) const {
- return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
- SegIndex, SegOffset);
+ // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
+ // that fully contains a pointer at that location. Multiple fixups in a rebase
+ // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the
+ // Count and Skip parameters.
+ //
+ // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry
+ const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex,
+ uint64_t SegOffset,
+ uint8_t PointerSize,
+ uint32_t Count=1,
+ uint32_t Skip=0) const {
+ return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
+ PointerSize, Count, Skip);
}
/// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
@@ -579,6 +571,7 @@ public:
const char **McpuDefault = nullptr,
const char **ArchFlag = nullptr);
static bool isValidArch(StringRef ArchFlag);
+ static ArrayRef<StringRef> getValidArchs();
static Triple getHostArch();
bool isRelocatableObject() const override;
@@ -616,6 +609,7 @@ public:
case MachO::PLATFORM_TVOS: return "tvos";
case MachO::PLATFORM_WATCHOS: return "watchos";
case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
+ case MachO::PLATFORM_MACCATALYST: return "macCatalyst";
case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index 9e70b0bc30c04..5bf724f2c8b2e 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -1,9 +1,8 @@
//===- MachOUniversal.h - Mach-O universal binaries -------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/llvm/Object/Minidump.h b/include/llvm/Object/Minidump.h
new file mode 100644
index 0000000000000..470008d552e73
--- /dev/null
+++ b/include/llvm/Object/Minidump.h
@@ -0,0 +1,165 @@
+//===- Minidump.h - Minidump object file implementation ---------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_MINIDUMP_H
+#define LLVM_OBJECT_MINIDUMP_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Minidump.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace object {
+
+/// A class providing access to the contents of a minidump file.
+class MinidumpFile : public Binary {
+public:
+ /// Construct a new MinidumpFile object from the given memory buffer. Returns
+ /// an error if this file cannot be identified as a minidump file, or if its
+ /// contents are badly corrupted (i.e. we cannot read the stream directory).
+ static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source);
+
+ static bool classof(const Binary *B) { return B->isMinidump(); }
+
+ /// Returns the contents of the minidump header.
+ const minidump::Header &header() const { return Header; }
+
+ /// Returns the list of streams (stream directory entries) in this file.
+ ArrayRef<minidump::Directory> streams() const { return Streams; }
+
+ /// Returns the raw contents of the stream given by the directory entry.
+ ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const {
+ return getData().slice(Stream.Location.RVA, Stream.Location.DataSize);
+ }
+
+ /// Returns the raw contents of the stream of the given type, or None if the
+ /// file does not contain a stream of this type.
+ Optional<ArrayRef<uint8_t>> getRawStream(minidump::StreamType Type) const;
+
+ /// Returns the raw contents of an object given by the LocationDescriptor. An
+ /// error is returned if the descriptor points outside of the minidump file.
+ Expected<ArrayRef<uint8_t>>
+ getRawData(minidump::LocationDescriptor Desc) const {
+ return getDataSlice(getData(), Desc.RVA, Desc.DataSize);
+ }
+
+ /// Returns the minidump string at the given offset. An error is returned if
+ /// we fail to parse the string, or the string is invalid UTF16.
+ Expected<std::string> getString(size_t Offset) const;
+
+ /// Returns the contents of the SystemInfo stream, cast to the appropriate
+ /// type. An error is returned if the file does not contain this stream, or
+ /// the stream is smaller than the size of the SystemInfo structure. The
+ /// internal consistency of the stream is not checked in any way.
+ Expected<const minidump::SystemInfo &> getSystemInfo() const {
+ return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo);
+ }
+
+ /// Returns the module list embedded in the ModuleList stream. An error is
+ /// returned if the file does not contain this stream, or if the stream is
+ /// not large enough to contain the number of modules declared in the stream
+ /// header. The consistency of the Module entries themselves is not checked in
+ /// any way.
+ Expected<ArrayRef<minidump::Module>> getModuleList() const {
+ return getListStream<minidump::Module>(minidump::StreamType::ModuleList);
+ }
+
+ /// Returns the thread list embedded in the ThreadList stream. An error is
+ /// returned if the file does not contain this stream, or if the stream is
+ /// not large enough to contain the number of threads declared in the stream
+ /// header. The consistency of the Thread entries themselves is not checked in
+ /// any way.
+ Expected<ArrayRef<minidump::Thread>> getThreadList() const {
+ return getListStream<minidump::Thread>(minidump::StreamType::ThreadList);
+ }
+
+ /// Returns the list of memory ranges embedded in the MemoryList stream. An
+ /// error is returned if the file does not contain this stream, or if the
+ /// stream is not large enough to contain the number of memory descriptors
+ /// declared in the stream header. The consistency of the MemoryDescriptor
+ /// entries themselves is not checked in any way.
+ Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const {
+ return getListStream<minidump::MemoryDescriptor>(
+ minidump::StreamType::MemoryList);
+ }
+
+private:
+ static Error createError(StringRef Str) {
+ return make_error<GenericBinaryError>(Str, object_error::parse_failed);
+ }
+
+ static Error createEOFError() {
+ return make_error<GenericBinaryError>("Unexpected EOF",
+ object_error::unexpected_eof);
+ }
+
+ /// Return a slice of the given data array, with bounds checking.
+ static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data,
+ size_t Offset, size_t Size);
+
+ /// Return the slice of the given data array as an array of objects of the
+ /// given type. The function checks that the input array is large enough to
+ /// contain the correct number of objects of the given type.
+ template <typename T>
+ static Expected<ArrayRef<T>> getDataSliceAs(ArrayRef<uint8_t> Data,
+ size_t Offset, size_t Count);
+
+ MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header,
+ ArrayRef<minidump::Directory> Streams,
+ DenseMap<minidump::StreamType, std::size_t> StreamMap)
+ : Binary(ID_Minidump, Source), Header(Header), Streams(Streams),
+ StreamMap(std::move(StreamMap)) {}
+
+ ArrayRef<uint8_t> getData() const {
+ return arrayRefFromStringRef(Data.getBuffer());
+ }
+
+ /// Return the stream of the given type, cast to the appropriate type. Checks
+ /// that the stream is large enough to hold an object of this type.
+ template <typename T>
+ Expected<const T &> getStream(minidump::StreamType Stream) const;
+
+ /// Return the contents of a stream which contains a list of fixed-size items,
+ /// prefixed by the list size.
+ template <typename T>
+ Expected<ArrayRef<T>> getListStream(minidump::StreamType Stream) const;
+
+ const minidump::Header &Header;
+ ArrayRef<minidump::Directory> Streams;
+ DenseMap<minidump::StreamType, std::size_t> StreamMap;
+};
+
+template <typename T>
+Expected<const T &> MinidumpFile::getStream(minidump::StreamType Stream) const {
+ if (auto OptionalStream = getRawStream(Stream)) {
+ if (OptionalStream->size() >= sizeof(T))
+ return *reinterpret_cast<const T *>(OptionalStream->data());
+ return createEOFError();
+ }
+ return createError("No such stream");
+}
+
+template <typename T>
+Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data,
+ size_t Offset,
+ size_t Count) {
+ // Check for overflow.
+ if (Count > std::numeric_limits<size_t>::max() / sizeof(T))
+ return createEOFError();
+ auto ExpectedArray = getDataSlice(Data, Offset, sizeof(T) * Count);
+ if (!ExpectedArray)
+ return ExpectedArray.takeError();
+ return ArrayRef<T>(reinterpret_cast<const T *>(ExpectedArray->data()), Count);
+}
+
+} // end namespace object
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_MINIDUMP_H
diff --git a/include/llvm/Object/ModuleSymbolTable.h b/include/llvm/Object/ModuleSymbolTable.h
index c3cbc27998e5a..4c582fbcda811 100644
--- a/include/llvm/Object/ModuleSymbolTable.h
+++ b/include/llvm/Object/ModuleSymbolTable.h
@@ -1,9 +1,8 @@
//===- ModuleSymbolTable.h - symbol table for in-memory IR ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 036c99cb6baff..483a3486bd724 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -1,9 +1,8 @@
//===- ObjectFile.h - File format independent object file -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -14,6 +13,7 @@
#ifndef LLVM_OBJECT_OBJECTFILE_H
#define LLVM_OBJECT_OBJECTFILE_H
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator_range.h"
@@ -98,7 +98,7 @@ public:
uint64_t getAddress() const;
uint64_t getIndex() const;
uint64_t getSize() const;
- std::error_code getContents(StringRef &Result) const;
+ Expected<StringRef> getContents() const;
/// Get the alignment of this section as the actual value (not log 2).
uint64_t getAlignment() const;
@@ -136,6 +136,30 @@ public:
const ObjectFile *getObject() const;
};
+struct SectionedAddress {
+ // TODO: constructors could be removed when C++14 would be adopted.
+ SectionedAddress() {}
+ SectionedAddress(uint64_t Addr, uint64_t SectIdx)
+ : Address(Addr), SectionIndex(SectIdx) {}
+
+ const static uint64_t UndefSection = UINT64_MAX;
+
+ uint64_t Address = 0;
+ uint64_t SectionIndex = UndefSection;
+};
+
+inline bool operator<(const SectionedAddress &LHS,
+ const SectionedAddress &RHS) {
+ return std::tie(LHS.SectionIndex, LHS.Address) <
+ std::tie(RHS.SectionIndex, RHS.Address);
+}
+
+inline bool operator==(const SectionedAddress &LHS,
+ const SectionedAddress &RHS) {
+ return std::tie(LHS.SectionIndex, LHS.Address) ==
+ std::tie(RHS.SectionIndex, RHS.Address);
+}
+
/// This is a value type class that represents a single symbol in the list of
/// symbols in the object file.
class SymbolRef : public BasicSymbolRef {
@@ -220,7 +244,7 @@ protected:
friend class SymbolRef;
virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
- std::error_code printSymbolName(raw_ostream &OS,
+ Error printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0;
@@ -234,13 +258,12 @@ protected:
friend class SectionRef;
virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
- virtual std::error_code getSectionName(DataRefImpl Sec,
- StringRef &Res) const = 0;
+ virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
- virtual std::error_code getSectionContents(DataRefImpl Sec,
- StringRef &Res) const = 0;
+ virtual Expected<ArrayRef<uint8_t>>
+ getSectionContents(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
virtual bool isSectionText(DataRefImpl Sec) const = 0;
@@ -308,11 +331,6 @@ public:
/// Create a triple from the data in this object file.
Triple makeTriple() const;
- virtual std::error_code
- getBuildAttributes(ARMAttributeParser &Attributes) const {
- return std::error_code();
- }
-
/// Maps a debug section name to a standard DWARF section name.
virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; }
@@ -341,6 +359,9 @@ public:
createCOFFObjectFile(MemoryBufferRef Object);
static Expected<std::unique_ptr<ObjectFile>>
+ createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
+
+ static Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Object);
static Expected<std::unique_ptr<MachOObjectFile>>
@@ -396,14 +417,16 @@ inline SectionRef::SectionRef(DataRefImpl SectionP,
, OwningObject(Owner) {}
inline bool SectionRef::operator==(const SectionRef &Other) const {
- return SectionPimpl == Other.SectionPimpl;
+ return OwningObject == Other.OwningObject &&
+ SectionPimpl == Other.SectionPimpl;
}
inline bool SectionRef::operator!=(const SectionRef &Other) const {
- return SectionPimpl != Other.SectionPimpl;
+ return !(*this == Other);
}
inline bool SectionRef::operator<(const SectionRef &Other) const {
+ assert(OwningObject == Other.OwningObject);
return SectionPimpl < Other.SectionPimpl;
}
@@ -412,7 +435,11 @@ inline void SectionRef::moveNext() {
}
inline std::error_code SectionRef::getName(StringRef &Result) const {
- return OwningObject->getSectionName(SectionPimpl, Result);
+ Expected<StringRef> NameOrErr = OwningObject->getSectionName(SectionPimpl);
+ if (!NameOrErr)
+ return errorToErrorCode(NameOrErr.takeError());
+ Result = *NameOrErr;
+ return std::error_code();
}
inline uint64_t SectionRef::getAddress() const {
@@ -427,8 +454,12 @@ inline uint64_t SectionRef::getSize() const {
return OwningObject->getSectionSize(SectionPimpl);
}
-inline std::error_code SectionRef::getContents(StringRef &Result) const {
- return OwningObject->getSectionContents(SectionPimpl, Result);
+inline Expected<StringRef> SectionRef::getContents() const {
+ Expected<ArrayRef<uint8_t>> Res =
+ OwningObject->getSectionContents(SectionPimpl);
+ if (!Res)
+ return Res.takeError();
+ return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size());
}
inline uint64_t SectionRef::getAlignment() const {
@@ -531,6 +562,25 @@ inline const ObjectFile *RelocationRef::getObject() const {
} // end namespace object
+template <> struct DenseMapInfo<object::SectionRef> {
+ static bool isEqual(const object::SectionRef &A,
+ const object::SectionRef &B) {
+ return A == B;
+ }
+ static object::SectionRef getEmptyKey() {
+ return object::SectionRef({}, nullptr);
+ }
+ static object::SectionRef getTombstoneKey() {
+ object::DataRefImpl TS;
+ TS.p = (uintptr_t)-1;
+ return object::SectionRef(TS, nullptr);
+ }
+ static unsigned getHashValue(const object::SectionRef &Sec) {
+ object::DataRefImpl Raw = Sec.getRawDataRefImpl();
+ return hash_combine(Raw.p, Raw.d.a, Raw.d.b);
+ }
+};
+
} // end namespace llvm
#endif // LLVM_OBJECT_OBJECTFILE_H
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
deleted file mode 100644
index 9a978de2e5996..0000000000000
--- a/include/llvm/Object/RelocVisitor.h
+++ /dev/null
@@ -1,351 +0,0 @@
-//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides a wrapper around all the different types of relocations
-// in different file formats, such that a client can handle them in a unified
-// manner by only implementing a minimal number of functions.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_OBJECT_RELOCVISITOR_H
-#define LLVM_OBJECT_RELOCVISITOR_H
-
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Object/Wasm.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <cstdint>
-#include <system_error>
-
-namespace llvm {
-namespace object {
-
-/// Base class for object file relocation visitors.
-class RelocVisitor {
-public:
- explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
-
- // TODO: Should handle multiple applied relocations via either passing in the
- // previously computed value or just count paired relocations as a single
- // visit.
- uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
- if (isa<ELFObjectFileBase>(ObjToVisit))
- return visitELF(Rel, R, Value);
- if (isa<COFFObjectFile>(ObjToVisit))
- return visitCOFF(Rel, R, Value);
- if (isa<MachOObjectFile>(ObjToVisit))
- return visitMachO(Rel, R, Value);
- if (isa<WasmObjectFile>(ObjToVisit))
- return visitWasm(Rel, R, Value);
-
- HasError = true;
- return 0;
- }
-
- bool error() { return HasError; }
-
-private:
- const ObjectFile &ObjToVisit;
- bool HasError = false;
-
- uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
- switch (ObjToVisit.getArch()) {
- case Triple::x86_64:
- return visitX86_64(Rel, R, Value);
- case Triple::aarch64:
- case Triple::aarch64_be:
- return visitAarch64(Rel, R, Value);
- case Triple::bpfel:
- case Triple::bpfeb:
- return visitBpf(Rel, R, Value);
- case Triple::mips64el:
- case Triple::mips64:
- return visitMips64(Rel, R, Value);
- case Triple::ppc64le:
- case Triple::ppc64:
- return visitPPC64(Rel, R, Value);
- case Triple::systemz:
- return visitSystemz(Rel, R, Value);
- case Triple::sparcv9:
- return visitSparc64(Rel, R, Value);
- case Triple::amdgcn:
- return visitAmdgpu(Rel, R, Value);
- default:
- HasError = true;
- return 0;
- }
- }
-
- // 32-bit object file
- assert(ObjToVisit.getBytesInAddress() == 4 &&
- "Invalid word size in object file");
-
- switch (ObjToVisit.getArch()) {
- case Triple::x86:
- return visitX86(Rel, R, Value);
- case Triple::ppc:
- return visitPPC32(Rel, R, Value);
- case Triple::arm:
- case Triple::armeb:
- return visitARM(Rel, R, Value);
- case Triple::lanai:
- return visitLanai(Rel, R, Value);
- case Triple::mipsel:
- case Triple::mips:
- return visitMips32(Rel, R, Value);
- case Triple::sparc:
- return visitSparc32(Rel, R, Value);
- case Triple::hexagon:
- return visitHexagon(Rel, R, Value);
- default:
- HasError = true;
- return 0;
- }
- }
-
- int64_t getELFAddend(RelocationRef R) {
- Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
- handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
- report_fatal_error(EI.message());
- });
- return *AddendOrErr;
- }
-
- uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_X86_64_NONE:
- return 0;
- case ELF::R_X86_64_64:
- case ELF::R_X86_64_DTPOFF32:
- case ELF::R_X86_64_DTPOFF64:
- return Value + getELFAddend(R);
- case ELF::R_X86_64_PC32:
- return Value + getELFAddend(R) - R.getOffset();
- case ELF::R_X86_64_32:
- case ELF::R_X86_64_32S:
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_AARCH64_ABS32: {
- int64_t Res = Value + getELFAddend(R);
- if (Res < INT32_MIN || Res > UINT32_MAX)
- HasError = true;
- return static_cast<uint32_t>(Res);
- }
- case ELF::R_AARCH64_ABS64:
- return Value + getELFAddend(R);
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_BPF_64_32:
- return Value & 0xFFFFFFFF;
- case ELF::R_BPF_64_64:
- return Value;
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_MIPS_32:
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- case ELF::R_MIPS_64:
- return Value + getELFAddend(R);
- case ELF::R_MIPS_TLS_DTPREL64:
- return Value + getELFAddend(R) - 0x8000;
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_PPC64_ADDR32:
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- case ELF::R_PPC64_ADDR64:
- return Value + getELFAddend(R);
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_390_32: {
- int64_t Res = Value + getELFAddend(R);
- if (Res < INT32_MIN || Res > UINT32_MAX)
- HasError = true;
- return static_cast<uint32_t>(Res);
- }
- case ELF::R_390_64:
- return Value + getELFAddend(R);
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_SPARC_32:
- case ELF::R_SPARC_64:
- case ELF::R_SPARC_UA32:
- case ELF::R_SPARC_UA64:
- return Value + getELFAddend(R);
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_AMDGPU_ABS32:
- case ELF::R_AMDGPU_ABS64:
- return Value + getELFAddend(R);
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (Rel) {
- case ELF::R_386_NONE:
- return 0;
- case ELF::R_386_32:
- return Value;
- case ELF::R_386_PC32:
- return Value - R.getOffset();
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (Rel == ELF::R_PPC_ADDR32)
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- HasError = true;
- return 0;
- }
-
- uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (Rel == ELF::R_ARM_ABS32) {
- if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
- HasError = true;
- return static_cast<uint32_t>(Value);
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (Rel == ELF::R_LANAI_32)
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- HasError = true;
- return 0;
- }
-
- uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
- // FIXME: Take in account implicit addends to get correct results.
- if (Rel == ELF::R_MIPS_32)
- return Value & 0xFFFFFFFF;
- if (Rel == ELF::R_MIPS_TLS_DTPREL32)
- return Value & 0xFFFFFFFF;
- HasError = true;
- return 0;
- }
-
- uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
- return Value + getELFAddend(R);
- HasError = true;
- return 0;
- }
-
- uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (Rel == ELF::R_HEX_32)
- return Value + getELFAddend(R);
- HasError = true;
- return 0;
- }
-
- uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
- switch (ObjToVisit.getArch()) {
- case Triple::x86:
- switch (Rel) {
- case COFF::IMAGE_REL_I386_SECREL:
- case COFF::IMAGE_REL_I386_DIR32:
- return static_cast<uint32_t>(Value);
- }
- break;
- case Triple::x86_64:
- switch (Rel) {
- case COFF::IMAGE_REL_AMD64_SECREL:
- return static_cast<uint32_t>(Value);
- case COFF::IMAGE_REL_AMD64_ADDR64:
- return Value;
- }
- break;
- default:
- break;
- }
- HasError = true;
- return 0;
- }
-
- uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (ObjToVisit.getArch() == Triple::x86_64 &&
- Rel == MachO::X86_64_RELOC_UNSIGNED)
- return Value;
- HasError = true;
- return 0;
- }
-
- uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
- if (ObjToVisit.getArch() == Triple::wasm32) {
- switch (Rel) {
- case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
- case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
- case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
- case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
- case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
- case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
- // For wasm section, its offset at 0 -- ignoring Value
- return 0;
- }
- }
- HasError = true;
- return 0;
- }
-};
-
-} // end namespace object
-} // end namespace llvm
-
-#endif // LLVM_OBJECT_RELOCVISITOR_H
diff --git a/include/llvm/Object/RelocationResolver.h b/include/llvm/Object/RelocationResolver.h
new file mode 100644
index 0000000000000..1246dcc5ec739
--- /dev/null
+++ b/include/llvm/Object/RelocationResolver.h
@@ -0,0 +1,42 @@
+//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a wrapper around all the different types of relocations
+// in different file formats, such that a client can handle them in a unified
+// manner by only implementing a minimal number of functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_RELOCVISITOR_H
+#define LLVM_OBJECT_RELOCVISITOR_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstdint>
+#include <system_error>
+
+namespace llvm {
+namespace object {
+
+using RelocationResolver = uint64_t (*)(RelocationRef R, uint64_t S, uint64_t A);
+
+std::pair<bool (*)(uint64_t), RelocationResolver>
+getRelocationResolver(const ObjectFile &Obj);
+
+} // end namespace object
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_RELOCVISITOR_H
diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h
index 557db5afa8256..ed44efbf80b96 100644
--- a/include/llvm/Object/StackMapParser.h
+++ b/include/llvm/Object/StackMapParser.h
@@ -1,9 +1,8 @@
//===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -20,8 +19,9 @@
namespace llvm {
+/// A parser for the latest stackmap format. At the moment, latest=V2.
template <support::endianness Endianness>
-class StackMapV2Parser {
+class StackMapParser {
public:
template <typename AccessorT>
class AccessorIterator {
@@ -50,7 +50,7 @@ public:
/// Accessor for function records.
class FunctionAccessor {
- friend class StackMapV2Parser;
+ friend class StackMapParser;
public:
/// Get the function address.
@@ -82,7 +82,7 @@ public:
/// Accessor for constants.
class ConstantAccessor {
- friend class StackMapV2Parser;
+ friend class StackMapParser;
public:
/// Return the value of this constant.
@@ -106,7 +106,7 @@ public:
/// Accessor for location records.
class LocationAccessor {
- friend class StackMapV2Parser;
+ friend class StackMapParser;
friend class RecordAccessor;
public:
@@ -115,6 +115,12 @@ public:
return LocationKind(P[KindOffset]);
}
+ /// Get the Size for this location.
+ unsigned getSizeInBytes() const {
+ return read<uint16_t>(P + SizeOffset);
+
+ }
+
/// Get the Dwarf register number for this location.
uint16_t getDwarfRegNum() const {
return read<uint16_t>(P + DwarfRegNumOffset);
@@ -149,16 +155,17 @@ public:
}
static const int KindOffset = 0;
- static const int DwarfRegNumOffset = KindOffset + sizeof(uint16_t);
- static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint16_t);
- static const int LocationAccessorSize = sizeof(uint64_t);
+ static const int SizeOffset = KindOffset + sizeof(uint16_t);
+ static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t);
+ static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t);
+ static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t);
const uint8_t *P;
};
/// Accessor for stackmap live-out fields.
class LiveOutAccessor {
- friend class StackMapV2Parser;
+ friend class StackMapParser;
friend class RecordAccessor;
public:
@@ -189,7 +196,7 @@ public:
/// Accessor for stackmap records.
class RecordAccessor {
- friend class StackMapV2Parser;
+ friend class StackMapParser;
public:
using location_iterator = AccessorIterator<LocationAccessor>;
@@ -264,8 +271,9 @@ public:
RecordAccessor(const uint8_t *P) : P(P) {}
unsigned getNumLiveOutsOffset() const {
- return LocationListOffset + LocationSize * getNumLocations() +
- sizeof(uint16_t);
+ unsigned LocOffset =
+ ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7;
+ return LocOffset + sizeof(uint16_t);
}
unsigned getSizeInBytes() const {
@@ -285,7 +293,7 @@ public:
InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
static const unsigned LocationListOffset =
NumLocationsOffset + sizeof(uint16_t);
- static const unsigned LocationSize = sizeof(uint64_t);
+ static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t);
static const unsigned LiveOutSize = sizeof(uint32_t);
const uint8_t *P;
@@ -293,12 +301,12 @@ public:
/// Construct a parser for a version-2 stackmap. StackMap data will be read
/// from the given array.
- StackMapV2Parser(ArrayRef<uint8_t> StackMapSection)
+ StackMapParser(ArrayRef<uint8_t> StackMapSection)
: StackMapSection(StackMapSection) {
ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
- assert(StackMapSection[0] == 2 &&
- "StackMapV2Parser can only parse version 2 stackmaps");
+ assert(StackMapSection[0] == 3 &&
+ "StackMapParser can only parse version 3 stackmaps");
unsigned CurrentRecordOffset =
ConstantsListOffset + getNumConstants() * ConstantSize;
@@ -314,8 +322,8 @@ public:
using constant_iterator = AccessorIterator<ConstantAccessor>;
using record_iterator = AccessorIterator<RecordAccessor>;
- /// Get the version number of this stackmap. (Always returns 2).
- unsigned getVersion() const { return 2; }
+ /// Get the version number of this stackmap. (Always returns 3).
+ unsigned getVersion() const { return 3; }
/// Get the number of functions in the stack map.
uint32_t getNumFunctions() const {
diff --git a/include/llvm/Object/SymbolSize.h b/include/llvm/Object/SymbolSize.h
index 1a1dc87529430..085623e35907d 100644
--- a/include/llvm/Object/SymbolSize.h
+++ b/include/llvm/Object/SymbolSize.h
@@ -1,9 +1,8 @@
//===- SymbolSize.h ---------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index 5b9549bc34492..1398fa134c81c 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -1,9 +1,8 @@
//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -127,7 +126,7 @@ public:
void moveNext();
- std::error_code printName(raw_ostream &OS) const;
+ Error printName(raw_ostream &OS) const;
/// Get symbol flags (bitwise OR of SymbolRef::Flags)
uint32_t getFlags() const;
@@ -146,8 +145,7 @@ public:
// virtual interface.
virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
- virtual std::error_code printSymbolName(raw_ostream &OS,
- DataRefImpl Symb) const = 0;
+ virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0;
virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0;
@@ -194,7 +192,7 @@ inline void BasicSymbolRef::moveNext() {
return OwningObject->moveSymbolNext(SymbolPimpl);
}
-inline std::error_code BasicSymbolRef::printName(raw_ostream &OS) const {
+inline Error BasicSymbolRef::printName(raw_ostream &OS) const {
return OwningObject->printSymbolName(OS, SymbolPimpl);
}
diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h
index ed857652a0486..e130ea32ed21b 100644
--- a/include/llvm/Object/Wasm.h
+++ b/include/llvm/Object/Wasm.h
@@ -1,9 +1,8 @@
-//===- WasmObjectFile.h - Wasm object file implementation -------*- C++ -*-===//
+//===- Wasm.h - Wasm object file implementation -----------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -130,6 +129,10 @@ public:
static bool classof(const Binary *v) { return v->isWasm(); }
const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
+ const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
+ ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const {
+ return TargetFeatures;
+ }
ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
ArrayRef<wasm::WasmImport> imports() const { return Imports; }
@@ -149,7 +152,6 @@ public:
uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
uint32_t getNumImportedEvents() const { return NumImportedEvents; }
-
void moveSymbolNext(DataRefImpl &Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
@@ -169,13 +171,12 @@ public:
// Overrides from SectionRef.
void moveSectionNext(DataRefImpl &Sec) const override;
- std::error_code getSectionName(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
- std::error_code getSectionContents(DataRefImpl Sec,
- StringRef &Res) const override;
+ Expected<ArrayRef<uint8_t>>
+ getSectionContents(DataRefImpl Sec) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
@@ -222,13 +223,13 @@ private:
bool isValidDataSymbol(uint32_t Index) const;
bool isValidSectionSymbol(uint32_t Index) const;
wasm::WasmFunction &getDefinedFunction(uint32_t Index);
+ const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
wasm::WasmEvent &getDefinedEvent(uint32_t Index);
const WasmSection &getWasmSection(DataRefImpl Ref) const;
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
- const uint8_t *getPtr(size_t Offset) const;
Error parseSection(WasmSection &Sec);
Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
@@ -245,6 +246,7 @@ private:
Error parseElemSection(ReadContext &Ctx);
Error parseCodeSection(ReadContext &Ctx);
Error parseDataSection(ReadContext &Ctx);
+ Error parseDataCountSection(ReadContext &Ctx);
// Custom section types
Error parseDylinkSection(ReadContext &Ctx);
@@ -252,11 +254,15 @@ private:
Error parseLinkingSection(ReadContext &Ctx);
Error parseLinkingSectionSymtab(ReadContext &Ctx);
Error parseLinkingSectionComdat(ReadContext &Ctx);
+ Error parseProducersSection(ReadContext &Ctx);
+ Error parseTargetFeaturesSection(ReadContext &Ctx);
Error parseRelocSection(StringRef Name, ReadContext &Ctx);
wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
wasm::WasmDylinkInfo DylinkInfo;
+ wasm::WasmProducerInfo ProducerInfo;
+ std::vector<wasm::WasmFeatureEntry> TargetFeatures;
std::vector<wasm::WasmSignature> Signatures;
std::vector<uint32_t> FunctionTypes;
std::vector<wasm::WasmTable> Tables;
@@ -267,6 +273,7 @@ private:
std::vector<wasm::WasmExport> Exports;
std::vector<wasm::WasmElemSegment> ElemSegments;
std::vector<WasmSegment> DataSegments;
+ llvm::Optional<size_t> DataCount;
std::vector<wasm::WasmFunction> Functions;
std::vector<WasmSymbol> Symbols;
std::vector<wasm::WasmFunctionName> DebugNames;
@@ -287,40 +294,51 @@ class WasmSectionOrderChecker {
public:
// We define orders for all core wasm sections and known custom sections.
enum : int {
+ // Sentinel, must be zero
+ WASM_SEC_ORDER_NONE = 0,
+
// Core sections
- // The order of standard sections is precisely given by the spec.
- WASM_SEC_ORDER_TYPE = 1,
- WASM_SEC_ORDER_IMPORT = 2,
- WASM_SEC_ORDER_FUNCTION = 3,
- WASM_SEC_ORDER_TABLE = 4,
- WASM_SEC_ORDER_MEMORY = 5,
- WASM_SEC_ORDER_GLOBAL = 6,
- WASM_SEC_ORDER_EVENT = 7,
- WASM_SEC_ORDER_EXPORT = 8,
- WASM_SEC_ORDER_START = 9,
- WASM_SEC_ORDER_ELEM = 10,
- WASM_SEC_ORDER_DATACOUNT = 11,
- WASM_SEC_ORDER_CODE = 12,
- WASM_SEC_ORDER_DATA = 13,
+ WASM_SEC_ORDER_TYPE,
+ WASM_SEC_ORDER_IMPORT,
+ WASM_SEC_ORDER_FUNCTION,
+ WASM_SEC_ORDER_TABLE,
+ WASM_SEC_ORDER_MEMORY,
+ WASM_SEC_ORDER_GLOBAL,
+ WASM_SEC_ORDER_EVENT,
+ WASM_SEC_ORDER_EXPORT,
+ WASM_SEC_ORDER_START,
+ WASM_SEC_ORDER_ELEM,
+ WASM_SEC_ORDER_DATACOUNT,
+ WASM_SEC_ORDER_CODE,
+ WASM_SEC_ORDER_DATA,
// Custom sections
// "dylink" should be the very first section in the module
- WASM_SEC_ORDER_DYLINK = 0,
+ WASM_SEC_ORDER_DYLINK,
// "linking" section requires DATA section in order to validate data symbols
- WASM_SEC_ORDER_LINKING = 100,
+ WASM_SEC_ORDER_LINKING,
// Must come after "linking" section in order to validate reloc indexes.
- WASM_SEC_ORDER_RELOC = 101,
+ WASM_SEC_ORDER_RELOC,
// "name" section must appear after DATA. Comes after "linking" to allow
// symbol table to set default function name.
- WASM_SEC_ORDER_NAME = 102,
+ WASM_SEC_ORDER_NAME,
// "producers" section must appear after "name" section.
- WASM_SEC_ORDER_PRODUCERS = 103
+ WASM_SEC_ORDER_PRODUCERS,
+ // "target_features" section must appear after producers section
+ WASM_SEC_ORDER_TARGET_FEATURES,
+
+ // Must be last
+ WASM_NUM_SEC_ORDERS
+
};
+ // Sections that may or may not be present, but cannot be predecessors
+ static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS];
+
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
private:
- int LastOrder = -1; // Lastly seen known section's order
+ bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already
// Returns -1 for unknown sections.
int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
diff --git a/include/llvm/Object/WasmTraits.h b/include/llvm/Object/WasmTraits.h
index 049d72f79e417..3eee8e71b1876 100644
--- a/include/llvm/Object/WasmTraits.h
+++ b/include/llvm/Object/WasmTraits.h
@@ -1,9 +1,8 @@
//===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/llvm/Object/WindowsMachineFlag.h b/include/llvm/Object/WindowsMachineFlag.h
new file mode 100644
index 0000000000000..acc6afc0329cb
--- /dev/null
+++ b/include/llvm/Object/WindowsMachineFlag.h
@@ -0,0 +1,33 @@
+//===- WindowsMachineFlag.h -------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Functions for implementing the /machine: flag.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H
+#define LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H
+
+namespace llvm {
+
+class StringRef;
+namespace COFF {
+enum MachineTypes : unsigned;
+}
+
+// Returns a user-readable string for ARMNT, ARM64, AMD64, I386.
+// Other MachineTypes values must not be passed in.
+StringRef machineToStr(COFF::MachineTypes MT);
+
+// Maps /machine: arguments to a MachineTypes value.
+// Only returns ARMNT, ARM64, AMD64, I386, or IMAGE_FILE_MACHINE_UNKNOWN.
+COFF::MachineTypes getMachineType(StringRef S);
+
+}
+
+#endif
diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h
index a077c82871bfc..356dcb03abba0 100644
--- a/include/llvm/Object/WindowsResource.h
+++ b/include/llvm/Object/WindowsResource.h
@@ -1,9 +1,8 @@
//===-- WindowsResource.h ---------------------------------------*- C++-*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===---------------------------------------------------------------------===//
//
@@ -38,11 +37,14 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/ScopedPrinter.h"
#include <map>
namespace llvm {
+
+class raw_ostream;
+class ScopedPrinter;
+
namespace object {
class WindowsResource;
@@ -118,6 +120,7 @@ private:
const WindowsResource *Owner);
BinaryStreamReader Reader;
+ const WindowsResource *Owner;
bool IsStringType;
ArrayRef<UTF16> Type;
uint16_t TypeID;
@@ -149,7 +152,7 @@ class WindowsResourceParser {
public:
class TreeNode;
WindowsResourceParser();
- Error parse(WindowsResource *WR);
+ Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
void printTree(raw_ostream &OS) const;
const TreeNode &getTree() const { return Root; }
const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
@@ -185,21 +188,25 @@ public:
static std::unique_ptr<TreeNode> createIDNode();
static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
uint16_t MinorVersion,
- uint32_t Characteristics);
+ uint32_t Characteristics,
+ uint32_t Origin);
explicit TreeNode(bool IsStringNode);
TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
- uint32_t Characteristics);
+ uint32_t Characteristics, uint32_t Origin);
- void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString,
- bool &IsNewNameString);
+ bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
+ bool &IsNewTypeString, bool &IsNewNameString,
+ TreeNode *&Result);
TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString);
TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString);
- TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
- TreeNode &addChild(uint32_t ID, bool IsDataNode = false,
- uint16_t MajorVersion = 0, uint16_t MinorVersion = 0,
- uint32_t Characteristics = 0);
- TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
+ bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
+ TreeNode *&Result);
+ bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
+ uint32_t Characteristics, uint32_t Origin,
+ TreeNode *&Result);
+ TreeNode &addIDChild(uint32_t ID);
+ TreeNode &addNameChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
bool IsDataNode = false;
uint32_t StringIndex;
@@ -209,18 +216,26 @@ public:
uint16_t MajorVersion = 0;
uint16_t MinorVersion = 0;
uint32_t Characteristics = 0;
+
+ // The .res file that defined this TreeNode, for diagnostics.
+ // Index into InputFilenames.
+ uint32_t Origin;
};
private:
TreeNode Root;
std::vector<std::vector<uint8_t>> Data;
std::vector<std::vector<UTF16>> StringTable;
+
+ std::vector<std::string> InputFilenames;
};
Expected<std::unique_ptr<MemoryBuffer>>
writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
- const WindowsResourceParser &Parser);
+ const WindowsResourceParser &Parser,
+ uint32_t TimeDateStamp);
+void printResourceTypeName(uint16_t TypeID, raw_ostream &OS);
} // namespace object
} // namespace llvm
diff --git a/include/llvm/Object/XCOFFObjectFile.h b/include/llvm/Object/XCOFFObjectFile.h
new file mode 100644
index 0000000000000..cdee7129a2abd
--- /dev/null
+++ b/include/llvm/Object/XCOFFObjectFile.h
@@ -0,0 +1,268 @@
+//===- XCOFFObjectFile.h - XCOFF object file implementation -----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the XCOFFObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H
+#define LLVM_OBJECT_XCOFFOBJECTFILE_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <system_error>
+
+namespace llvm {
+namespace object {
+
+struct XCOFFFileHeader32 {
+ support::ubig16_t Magic;
+ support::ubig16_t NumberOfSections;
+
+ // Unix time value, value of 0 indicates no timestamp.
+ // Negative values are reserved.
+ support::big32_t TimeStamp;
+
+ support::ubig32_t SymbolTableOffset; // File offset to symbol table.
+ support::big32_t NumberOfSymTableEntries;
+ support::ubig16_t AuxHeaderSize;
+ support::ubig16_t Flags;
+};
+
+struct XCOFFFileHeader64 {
+ support::ubig16_t Magic;
+ support::ubig16_t NumberOfSections;
+
+ // Unix time value, value of 0 indicates no timestamp.
+ // Negative values are reserved.
+ support::big32_t TimeStamp;
+
+ support::ubig64_t SymbolTableOffset; // File offset to symbol table.
+ support::ubig16_t AuxHeaderSize;
+ support::ubig16_t Flags;
+ support::ubig32_t NumberOfSymTableEntries;
+};
+
+struct XCOFFSectionHeader32 {
+ char Name[XCOFF::SectionNameSize];
+ support::ubig32_t PhysicalAddress;
+ support::ubig32_t VirtualAddress;
+ support::ubig32_t SectionSize;
+ support::ubig32_t FileOffsetToRawData;
+ support::ubig32_t FileOffsetToRelocationInfo;
+ support::ubig32_t FileOffsetToLineNumberInfo;
+ support::ubig16_t NumberOfRelocations;
+ support::ubig16_t NumberOfLineNumbers;
+ support::big32_t Flags;
+
+ StringRef getName() const;
+};
+
+struct XCOFFSectionHeader64 {
+ char Name[XCOFF::SectionNameSize];
+ support::ubig64_t PhysicalAddress;
+ support::ubig64_t VirtualAddress;
+ support::ubig64_t SectionSize;
+ support::big64_t FileOffsetToRawData;
+ support::big64_t FileOffsetToRelocationInfo;
+ support::big64_t FileOffsetToLineNumberInfo;
+ support::ubig32_t NumberOfRelocations;
+ support::ubig32_t NumberOfLineNumbers;
+ support::big32_t Flags;
+ char Padding[4];
+
+ StringRef getName() const;
+};
+
+struct XCOFFSymbolEntry {
+ enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
+ typedef struct {
+ support::big32_t Magic; // Zero indicates name in string table.
+ support::ubig32_t Offset;
+ } NameInStrTblType;
+
+ typedef struct {
+ uint8_t LanguageId;
+ uint8_t CpuTypeId;
+ } CFileLanguageIdAndTypeIdType;
+
+ union {
+ char SymbolName[XCOFF::SymbolNameSize];
+ NameInStrTblType NameInStrTbl;
+ };
+
+ support::ubig32_t Value; // Symbol value; storage class-dependent.
+ support::big16_t SectionNumber;
+
+ union {
+ support::ubig16_t SymbolType;
+ CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
+ };
+
+ XCOFF::StorageClass StorageClass;
+ uint8_t NumberOfAuxEntries;
+};
+
+struct XCOFFStringTable {
+ uint32_t Size;
+ const char *Data;
+};
+
+class XCOFFObjectFile : public ObjectFile {
+private:
+ const void *FileHeader = nullptr;
+ const void *SectionHeaderTable = nullptr;
+
+ const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
+ XCOFFStringTable StringTable = {0, nullptr};
+
+ const XCOFFFileHeader32 *fileHeader32() const;
+ const XCOFFFileHeader64 *fileHeader64() const;
+
+ const XCOFFSectionHeader32 *sectionHeaderTable32() const;
+ const XCOFFSectionHeader64 *sectionHeaderTable64() const;
+
+ size_t getFileHeaderSize() const;
+ size_t getSectionHeaderSize() const;
+
+ const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
+ const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
+ void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
+ uintptr_t getSectionHeaderTableAddress() const;
+
+ // This returns a pointer to the start of the storage for the name field of
+ // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
+ // null-terminated.
+ const char *getSectionNameInternal(DataRefImpl Sec) const;
+
+ int32_t getSectionFlags(DataRefImpl Sec) const;
+
+ static bool isReservedSectionNumber(int16_t SectionNumber);
+ Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
+
+ // Constructor and "create" factory function. The constructor is only a thin
+ // wrapper around the base constructor. The "create" function fills out the
+ // XCOFF-specific information and performs the error checking along the way.
+ XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
+ static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
+ MemoryBufferRef MBR);
+
+ // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
+ // and an XCOFFStringTable if parsing succeeded.
+ static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
+ uint64_t Offset);
+
+ // Make a friend so it can call the private 'create' function.
+ friend Expected<std::unique_ptr<ObjectFile>>
+ ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
+
+public:
+ // Interface inherited from base classes.
+ void moveSymbolNext(DataRefImpl &Symb) const override;
+ uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ basic_symbol_iterator symbol_begin() const override;
+ basic_symbol_iterator symbol_end() const override;
+
+ Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
+ Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+ uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
+ uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
+ Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
+ Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+
+ void moveSectionNext(DataRefImpl &Sec) const override;
+ Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
+ uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionIndex(DataRefImpl Sec) const override;
+ uint64_t getSectionSize(DataRefImpl Sec) const override;
+ Expected<ArrayRef<uint8_t>>
+ getSectionContents(DataRefImpl Sec) const override;
+ uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
+ bool isSectionText(DataRefImpl Sec) const override;
+ bool isSectionData(DataRefImpl Sec) const override;
+ bool isSectionBSS(DataRefImpl Sec) const override;
+
+ bool isSectionVirtual(DataRefImpl Sec) const override;
+ relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
+ relocation_iterator section_rel_end(DataRefImpl Sec) const override;
+
+ void moveRelocationNext(DataRefImpl &Rel) const override;
+ uint64_t getRelocationOffset(DataRefImpl Rel) const override;
+ symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
+ uint64_t getRelocationType(DataRefImpl Rel) const override;
+ void getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const override;
+
+ section_iterator section_begin() const override;
+ section_iterator section_end() const override;
+ uint8_t getBytesInAddress() const override;
+ StringRef getFileFormatName() const override;
+ Triple::ArchType getArch() const override;
+ SubtargetFeatures getFeatures() const override;
+ Expected<uint64_t> getStartAddress() const override;
+ bool isRelocatableObject() const override;
+
+ // Below here is the non-inherited interface.
+ bool is64Bit() const;
+
+ const XCOFFSymbolEntry *getPointerToSymbolTable() const {
+ assert(!is64Bit() && "Symbol table handling not supported yet.");
+ return SymbolTblPtr;
+ }
+
+ Expected<StringRef>
+ getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
+
+ const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
+
+ // File header related interfaces.
+ uint16_t getMagic() const;
+ uint16_t getNumberOfSections() const;
+ int32_t getTimeStamp() const;
+
+ // Symbol table offset and entry count are handled differently between
+ // XCOFF32 and XCOFF64.
+ uint32_t getSymbolTableOffset32() const;
+ uint64_t getSymbolTableOffset64() const;
+
+ // Note that this value is signed and might return a negative value. Negative
+ // values are reserved for future use.
+ int32_t getRawNumberOfSymbolTableEntries32() const;
+
+ // The sanitized value appropriate to use as an index into the symbol table.
+ uint32_t getLogicalNumberOfSymbolTableEntries32() const;
+
+ uint32_t getNumberOfSymbolTableEntries64() const;
+
+ uint16_t getOptionalHeaderSize() const;
+ uint16_t getFlags() const;
+
+ // Section header table related interfaces.
+ ArrayRef<XCOFFSectionHeader32> sections32() const;
+ ArrayRef<XCOFFSectionHeader64> sections64() const;
+}; // XCOFFObjectFile
+
+} // namespace object
+} // namespace llvm
+
+#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H