Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/Object/Archive.h b/linux-x64/clang/include/llvm/Object/Archive.h
index c40278a..c3f36bd 100644
--- a/linux-x64/clang/include/llvm/Object/Archive.h
+++ b/linux-x64/clang/include/llvm/Object/Archive.h
@@ -48,8 +48,7 @@
/// Get the name looking up long names.
Expected<StringRef> getName(uint64_t Size) const;
- /// Members are not larger than 4GB.
- Expected<uint32_t> getSize() const;
+ Expected<uint64_t> getSize() const;
Expected<sys::fs::perms> getAccessMode() const;
Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const;
@@ -136,6 +135,7 @@
Expected<StringRef> getBuffer() const;
uint64_t getChildOffset() const;
+ uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }
Expected<MemoryBufferRef> getMemoryBufferRef() const;
@@ -221,6 +221,9 @@
Archive(MemoryBufferRef Source, Error &Err);
static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
+ /// Size field is 10 decimal digits long
+ static const uint64_t MaxMemberSize = 9999999999;
+
enum Kind {
K_GNU,
K_GNU64,
diff --git a/linux-x64/clang/include/llvm/Object/ArchiveWriter.h b/linux-x64/clang/include/llvm/Object/ArchiveWriter.h
index 9e6daf2..7eaf13e 100644
--- a/linux-x64/clang/include/llvm/Object/ArchiveWriter.h
+++ b/linux-x64/clang/include/llvm/Object/ArchiveWriter.h
@@ -13,10 +13,7 @@
#ifndef LLVM_OBJECT_ARCHIVEWRITER_H
#define LLVM_OBJECT_ARCHIVEWRITER_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Archive.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
namespace llvm {
@@ -42,6 +39,12 @@
bool WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr);
+
+// writeArchiveToBuffer is similar to writeArchive but returns the Archive in a
+// buffer instead of writing it out to a file.
+Expected<std::unique_ptr<MemoryBuffer>>
+writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab,
+ object::Archive::Kind Kind, bool Deterministic, bool Thin);
}
#endif
diff --git a/linux-x64/clang/include/llvm/Object/Binary.h b/linux-x64/clang/include/llvm/Object/Binary.h
index 3c3e977..dd98e11 100644
--- a/linux-x64/clang/include/llvm/Object/Binary.h
+++ b/linux-x64/clang/include/llvm/Object/Binary.h
@@ -42,7 +42,9 @@
ID_Archive,
ID_MachOUniversalBinary,
ID_COFFImportFile,
- ID_IR, // LLVM IR
+ ID_IR, // LLVM IR
+ ID_TapiUniversal, // Text-based Dynamic Library Stub file.
+ ID_TapiFile, // Text-based Dynamic Library Stub file.
ID_Minidump,
@@ -89,6 +91,8 @@
Binary(const Binary &other) = delete;
virtual ~Binary();
+ virtual Error initContent() { return Error::success(); };
+
StringRef getData() const;
StringRef getFileName() const;
MemoryBufferRef getMemoryBufferRef() const;
@@ -101,16 +105,18 @@
return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
}
- bool isSymbolic() const { return isIR() || isObject() || isCOFFImportFile(); }
-
- bool isArchive() const {
- return TypeID == ID_Archive;
+ bool isSymbolic() const {
+ return isIR() || isObject() || isCOFFImportFile() || isTapiFile();
}
+ bool isArchive() const { return TypeID == ID_Archive; }
+
bool isMachOUniversalBinary() const {
return TypeID == ID_MachOUniversalBinary;
}
+ bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; }
+
bool isELF() const {
return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
}
@@ -137,6 +143,8 @@
bool isMinidump() const { return TypeID == ID_Minidump; }
+ bool isTapiFile() const { return TypeID == ID_TapiFile; }
+
bool isLittleEndian() const {
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
@@ -154,14 +162,14 @@
return Triple::UnknownObjectFormat;
}
- static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
- const uint64_t Size) {
+ static Error checkOffset(MemoryBufferRef M, uintptr_t Addr,
+ const uint64_t Size) {
if (Addr + Size < Addr || Addr + Size < Size ||
- Addr + Size > uintptr_t(M.getBufferEnd()) ||
- Addr < uintptr_t(M.getBufferStart())) {
- return object_error::unexpected_eof;
+ Addr + Size > reinterpret_cast<uintptr_t>(M.getBufferEnd()) ||
+ Addr < reinterpret_cast<uintptr_t>(M.getBufferStart())) {
+ return errorCodeToError(object_error::unexpected_eof);
}
- return std::error_code();
+ return Error::success();
}
};
@@ -172,7 +180,8 @@
///
/// @param Source The data to create the Binary from.
Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
- LLVMContext *Context = nullptr);
+ LLVMContext *Context = nullptr,
+ bool InitContent = true);
template <typename T> class OwningBinary {
std::unique_ptr<T> Bin;
@@ -222,7 +231,9 @@
return Bin.get();
}
-Expected<OwningBinary<Binary>> createBinary(StringRef Path);
+Expected<OwningBinary<Binary>> createBinary(StringRef Path,
+ LLVMContext *Context = nullptr,
+ bool InitContent = true);
} // end namespace object
diff --git a/linux-x64/clang/include/llvm/Object/COFF.h b/linux-x64/clang/include/llvm/Object/COFF.h
index c53cbc4..e7cf1b5 100644
--- a/linux-x64/clang/include/llvm/Object/COFF.h
+++ b/linux-x64/clang/include/llvm/Object/COFF.h
@@ -314,7 +314,10 @@
return CS16 ? CS16->Name.Offset : CS32->Name.Offset;
}
- uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; }
+ uint32_t getValue() const {
+ assert(isSet() && "COFFSymbolRef points to nothing!");
+ return CS16 ? CS16->Value : CS32->Value;
+ }
int32_t getSectionNumber() const {
assert(isSet() && "COFFSymbolRef points to nothing!");
@@ -573,11 +576,22 @@
uint32_t getAlignment() const {
// Bit [20:24] contains section alignment.
- uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
+ uint32_t Shift = (Characteristics & COFF::IMAGE_SCN_ALIGN_MASK) >> 20;
if (Shift > 0)
return 1U << (Shift - 1);
return 0;
}
+
+ void setAlignment(uint32_t Align) {
+ uint32_t AlignBits = 0;
+ if (Align) {
+ assert(llvm::isPowerOf2_32(Align) && "alignment is not a power of 2");
+ assert(llvm::Log2_32(Align) <= 13 && "alignment requested is too large");
+ AlignBits = (llvm::Log2_32(Align) + 1) << 20;
+ }
+ Characteristics =
+ (Characteristics & ~COFF::IMAGE_SCN_ALIGN_MASK) | AlignBits;
+ }
};
using coff_tls_directory32 = coff_tls_directory<support::little32_t>;
@@ -761,6 +775,8 @@
class COFFObjectFile : public ObjectFile {
private:
+ COFFObjectFile(MemoryBufferRef Object);
+
friend class ImportDirectoryEntryRef;
friend class ExportDirectoryEntryRef;
const coff_file_header *COFFHeader;
@@ -781,25 +797,34 @@
const coff_base_reloc_block_header *BaseRelocEnd;
const debug_directory *DebugDirectoryBegin;
const debug_directory *DebugDirectoryEnd;
+ const coff_tls_directory32 *TLSDirectory32;
+ const coff_tls_directory64 *TLSDirectory64;
// Either coff_load_configuration32 or coff_load_configuration64.
const void *LoadConfig = nullptr;
- std::error_code getString(uint32_t offset, StringRef &Res) const;
+ Expected<StringRef> getString(uint32_t offset) const;
template <typename coff_symbol_type>
const coff_symbol_type *toSymb(DataRefImpl Symb) const;
const coff_section *toSec(DataRefImpl Sec) const;
const coff_relocation *toRel(DataRefImpl Rel) const;
- std::error_code initSymbolTablePtr();
- std::error_code initImportTablePtr();
- std::error_code initDelayImportTablePtr();
- std::error_code initExportTablePtr();
- std::error_code initBaseRelocPtr();
- std::error_code initDebugDirectoryPtr();
- std::error_code initLoadConfigPtr();
+ // Finish initializing the object and return success or an error.
+ Error initialize();
+
+ Error initSymbolTablePtr();
+ Error initImportTablePtr();
+ Error initDelayImportTablePtr();
+ Error initExportTablePtr();
+ Error initBaseRelocPtr();
+ Error initDebugDirectoryPtr();
+ Error initTLSDirectoryPtr();
+ Error initLoadConfigPtr();
public:
+ static Expected<std::unique_ptr<COFFObjectFile>>
+ create(MemoryBufferRef Object);
+
uintptr_t getSymbolTable() const {
if (SymbolTable16)
return reinterpret_cast<uintptr_t>(SymbolTable16);
@@ -875,6 +900,8 @@
return getRawNumberOfSymbols();
}
+ uint32_t getStringTableSize() const { return StringTableSize; }
+
const coff_load_configuration32 *getLoadConfig32() const {
assert(!is64());
return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig);
@@ -893,7 +920,7 @@
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
- uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ Expected<uint32_t> getSymbolFlags(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;
@@ -909,6 +936,7 @@
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
+ bool isDebugSection(StringRef SectionName) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
@@ -920,8 +948,6 @@
SmallVectorImpl<char> &Result) const override;
public:
- COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
-
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
section_iterator section_begin() const override;
@@ -964,59 +990,50 @@
return make_range(debug_directory_begin(), debug_directory_end());
}
+ const coff_tls_directory32 *getTLSDirectory32() const {
+ return TLSDirectory32;
+ }
+ const coff_tls_directory64 *getTLSDirectory64() const {
+ return TLSDirectory64;
+ }
+
const dos_header *getDOSHeader() const {
if (!PE32Header && !PE32PlusHeader)
return nullptr;
return reinterpret_cast<const dos_header *>(base());
}
- std::error_code getCOFFHeader(const coff_file_header *&Res) const;
- std::error_code
- getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const;
- std::error_code getPE32Header(const pe32_header *&Res) const;
- std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
- std::error_code getDataDirectory(uint32_t index,
- const data_directory *&Res) const;
- std::error_code getSection(int32_t index, const coff_section *&Res) const;
- std::error_code getSection(StringRef SectionName,
- const coff_section *&Res) const;
- template <typename coff_symbol_type>
- std::error_code getSymbol(uint32_t Index,
- const coff_symbol_type *&Res) const {
- if (Index >= getNumberOfSymbols())
- return object_error::parse_failed;
-
- Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
- return std::error_code();
+ const coff_file_header *getCOFFHeader() const { return COFFHeader; }
+ const coff_bigobj_file_header *getCOFFBigObjHeader() const {
+ return COFFBigObjHeader;
}
+ const pe32_header *getPE32Header() const { return PE32Header; }
+ const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; }
+
+ const data_directory *getDataDirectory(uint32_t index) const;
+ Expected<const coff_section *> getSection(int32_t index) const;
+
Expected<COFFSymbolRef> getSymbol(uint32_t index) const {
- if (SymbolTable16) {
- const coff_symbol16 *Symb = nullptr;
- if (std::error_code EC = getSymbol(index, Symb))
- return errorCodeToError(EC);
- return COFFSymbolRef(Symb);
- }
- if (SymbolTable32) {
- const coff_symbol32 *Symb = nullptr;
- if (std::error_code EC = getSymbol(index, Symb))
- return errorCodeToError(EC);
- return COFFSymbolRef(Symb);
- }
+ if (index >= getNumberOfSymbols())
+ return errorCodeToError(object_error::parse_failed);
+ if (SymbolTable16)
+ return COFFSymbolRef(SymbolTable16 + index);
+ if (SymbolTable32)
+ return COFFSymbolRef(SymbolTable32 + index);
return errorCodeToError(object_error::parse_failed);
}
template <typename T>
- std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
+ Error getAuxSymbol(uint32_t index, const T *&Res) const {
Expected<COFFSymbolRef> S = getSymbol(index);
if (Error E = S.takeError())
- return errorToErrorCode(std::move(E));
+ return E;
Res = reinterpret_cast<const T *>(S->getRawPtr());
- return std::error_code();
+ return Error::success();
}
- std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
- std::error_code getSymbolName(const coff_symbol_generic *Symbol,
- StringRef &Res) const;
+ Expected<StringRef> getSymbolName(COFFSymbolRef Symbol) const;
+ Expected<StringRef> getSymbolName(const coff_symbol_generic *Symbol) const;
ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
@@ -1038,29 +1055,29 @@
ArrayRef<uint8_t> &Res) const;
uint64_t getImageBase() const;
- std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
- std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
+ Error getVaPtr(uint64_t VA, uintptr_t &Res) const;
+ Error getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
/// Given an RVA base and size, returns a valid array of bytes or an error
/// code if the RVA and size is not contained completely within a valid
/// section.
- std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
- ArrayRef<uint8_t> &Contents) const;
+ Error getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
+ ArrayRef<uint8_t> &Contents) const;
- std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
+ Error getHintName(uint32_t Rva, uint16_t &Hint,
StringRef &Name) const;
/// Get PDB information out of a codeview debug directory entry.
- std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
- const codeview::DebugInfo *&Info,
- StringRef &PDBFileName) const;
+ Error getDebugPDBInfo(const debug_directory *DebugDir,
+ const codeview::DebugInfo *&Info,
+ StringRef &PDBFileName) const;
/// Get PDB information from an executable. If the information is not present,
/// Info will be set to nullptr and PDBFileName will be empty. An error is
/// returned only on corrupt object files. Convenience accessor that can be
/// used if the debug directory is not already handy.
- std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info,
- StringRef &PDBFileName) const;
+ Error getDebugPDBInfo(const codeview::DebugInfo *&Info,
+ StringRef &PDBFileName) const;
bool isRelocatableObject() const override;
bool is64() const { return PE32PlusHeader; }
@@ -1089,11 +1106,11 @@
imported_symbol_iterator lookup_table_end() const;
iterator_range<imported_symbol_iterator> lookup_table_symbols() const;
- std::error_code getName(StringRef &Result) const;
- std::error_code getImportLookupTableRVA(uint32_t &Result) const;
- std::error_code getImportAddressTableRVA(uint32_t &Result) const;
+ Error getName(StringRef &Result) const;
+ Error getImportLookupTableRVA(uint32_t &Result) const;
+ Error getImportAddressTableRVA(uint32_t &Result) const;
- std::error_code
+ Error
getImportTableEntry(const coff_import_directory_table_entry *&Result) const;
private:
@@ -1116,10 +1133,10 @@
imported_symbol_iterator imported_symbol_end() const;
iterator_range<imported_symbol_iterator> imported_symbols() const;
- std::error_code getName(StringRef &Result) const;
- std::error_code getDelayImportTable(
+ Error getName(StringRef &Result) const;
+ Error getDelayImportTable(
const delay_import_directory_table_entry *&Result) const;
- std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const;
+ Error getImportAddress(int AddrIndex, uint64_t &Result) const;
private:
const delay_import_directory_table_entry *Table;
@@ -1138,14 +1155,14 @@
bool operator==(const ExportDirectoryEntryRef &Other) const;
void moveNext();
- std::error_code getDllName(StringRef &Result) const;
- std::error_code getOrdinalBase(uint32_t &Result) const;
- std::error_code getOrdinal(uint32_t &Result) const;
- std::error_code getExportRVA(uint32_t &Result) const;
- std::error_code getSymbolName(StringRef &Result) const;
+ Error getDllName(StringRef &Result) const;
+ Error getOrdinalBase(uint32_t &Result) const;
+ Error getOrdinal(uint32_t &Result) const;
+ Error getExportRVA(uint32_t &Result) const;
+ Error getSymbolName(StringRef &Result) const;
- std::error_code isForwarder(bool &Result) const;
- std::error_code getForwardTo(StringRef &Result) const;
+ Error isForwarder(bool &Result) const;
+ Error getForwardTo(StringRef &Result) const;
private:
const export_directory_table_entry *ExportTable;
@@ -1166,10 +1183,10 @@
bool operator==(const ImportedSymbolRef &Other) const;
void moveNext();
- std::error_code getSymbolName(StringRef &Result) const;
- std::error_code isOrdinal(bool &Result) const;
- std::error_code getOrdinal(uint16_t &Result) const;
- std::error_code getHintNameRVA(uint32_t &Result) const;
+ Error getSymbolName(StringRef &Result) const;
+ Error isOrdinal(bool &Result) const;
+ Error getOrdinal(uint16_t &Result) const;
+ Error getHintNameRVA(uint32_t &Result) const;
private:
const import_lookup_table_entry32 *Entry32;
@@ -1188,8 +1205,8 @@
bool operator==(const BaseRelocRef &Other) const;
void moveNext();
- std::error_code getType(uint8_t &Type) const;
- std::error_code getRVA(uint32_t &Result) const;
+ Error getType(uint8_t &Type) const;
+ Error getRVA(uint32_t &Result) const;
private:
const coff_base_reloc_block_header *Header;
@@ -1201,16 +1218,34 @@
ResourceSectionRef() = default;
explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
+ Error load(const COFFObjectFile *O);
+ Error load(const COFFObjectFile *O, const SectionRef &S);
+
Expected<ArrayRef<UTF16>>
getEntryNameString(const coff_resource_dir_entry &Entry);
Expected<const coff_resource_dir_table &>
getEntrySubDir(const coff_resource_dir_entry &Entry);
+ Expected<const coff_resource_data_entry &>
+ getEntryData(const coff_resource_dir_entry &Entry);
Expected<const coff_resource_dir_table &> getBaseTable();
+ Expected<const coff_resource_dir_entry &>
+ getTableEntry(const coff_resource_dir_table &Table, uint32_t Index);
+
+ Expected<StringRef> getContents(const coff_resource_data_entry &Entry);
private:
BinaryByteStream BBS;
+ SectionRef Section;
+ const COFFObjectFile *Obj;
+
+ std::vector<const coff_relocation *> Relocs;
+
Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
+ Expected<const coff_resource_dir_entry &>
+ getTableEntryAtOffset(uint32_t Offset);
+ Expected<const coff_resource_data_entry &>
+ getDataEntryAtOffset(uint32_t Offset);
Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
};
diff --git a/linux-x64/clang/include/llvm/Object/COFFImportFile.h b/linux-x64/clang/include/llvm/Object/COFFImportFile.h
index 5aa8364..f38bd89 100644
--- a/linux-x64/clang/include/llvm/Object/COFFImportFile.h
+++ b/linux-x64/clang/include/llvm/Object/COFFImportFile.h
@@ -43,7 +43,7 @@
return Error::success();
}
- uint32_t getSymbolFlags(DataRefImpl Symb) const override {
+ Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override {
return SymbolRef::SF_Global;
}
diff --git a/linux-x64/clang/include/llvm/Object/ELF.h b/linux-x64/clang/include/llvm/Object/ELF.h
index cab2974..86359ff 100644
--- a/linux-x64/clang/include/llvm/Object/ELF.h
+++ b/linux-x64/clang/include/llvm/Object/ELF.h
@@ -48,14 +48,51 @@
return make_error<StringError>(Err, object_error::parse_failed);
}
+enum PPCInstrMasks : uint64_t {
+ PADDI_R12_NO_DISP = 0x0610000039800000,
+ PLD_R12_NO_DISP = 0x04100000E5800000,
+ MTCTR_R12 = 0x7D8903A6,
+ BCTR = 0x4E800420,
+};
+
template <class ELFT> class ELFFile;
+template <class T> struct DataRegion {
+ // This constructor is used when we know the start and the size of a data
+ // region. We assume that Arr does not go past the end of the file.
+ DataRegion(ArrayRef<T> Arr) : First(Arr.data()), Size(Arr.size()) {}
+
+ // Sometimes we only know the start of a data region. We still don't want to
+ // read past the end of the file, so we provide the end of a buffer.
+ DataRegion(const T *Data, const uint8_t *BufferEnd)
+ : First(Data), BufEnd(BufferEnd) {}
+
+ Expected<T> operator[](uint64_t N) {
+ assert(Size || BufEnd);
+ if (Size) {
+ if (N >= *Size)
+ return createError(
+ "the index is greater than or equal to the number of entries (" +
+ Twine(*Size) + ")");
+ } else {
+ const uint8_t *EntryStart = (const uint8_t *)First + N * sizeof(T);
+ if (EntryStart + sizeof(T) > BufEnd)
+ return createError("can't read past the end of the file");
+ }
+ return *(First + N);
+ }
+
+ const T *First;
+ Optional<uint64_t> Size = None;
+ const uint8_t *BufEnd = nullptr;
+};
+
template <class ELFT>
-std::string getSecIndexForError(const ELFFile<ELFT> *Obj,
- const typename ELFT::Shdr *Sec) {
- auto TableOrErr = Obj->sections();
+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()) + "]";
+ 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
@@ -65,37 +102,34 @@
}
template <class ELFT>
+std::string getPhdrIndexForError(const ELFFile<ELFT> &Obj,
+ const typename ELFT::Phdr &Phdr) {
+ auto Headers = Obj.program_headers();
+ if (Headers)
+ return ("[index " + Twine(&Phdr - &Headers->front()) + "]").str();
+ // See comment in the getSecIndexForError() above.
+ llvm::consumeError(Headers.takeError());
+ return "[unknown index]";
+}
+
+static inline Error defaultWarningHandler(const Twine &Msg) {
+ return createError(Msg);
+}
+
+template <class ELFT>
class ELFFile {
public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
- using uintX_t = typename ELFT::uint;
- using Elf_Ehdr = typename ELFT::Ehdr;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Sym = typename ELFT::Sym;
- using Elf_Dyn = typename ELFT::Dyn;
- using Elf_Phdr = typename ELFT::Phdr;
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
- using Elf_Relr = typename ELFT::Relr;
- using Elf_Verdef = typename ELFT::Verdef;
- using Elf_Verdaux = typename ELFT::Verdaux;
- using Elf_Verneed = typename ELFT::Verneed;
- using Elf_Vernaux = typename ELFT::Vernaux;
- using Elf_Versym = typename ELFT::Versym;
- using Elf_Hash = typename ELFT::Hash;
- using Elf_GnuHash = typename ELFT::GnuHash;
- using Elf_Nhdr = typename ELFT::Nhdr;
- using Elf_Note = typename ELFT::Note;
- using Elf_Note_Iterator = typename ELFT::NoteIterator;
- using Elf_Dyn_Range = typename ELFT::DynRange;
- using Elf_Shdr_Range = typename ELFT::ShdrRange;
- using Elf_Sym_Range = typename ELFT::SymRange;
- using Elf_Rel_Range = typename ELFT::RelRange;
- using Elf_Rela_Range = typename ELFT::RelaRange;
- using Elf_Relr_Range = typename ELFT::RelrRange;
- using Elf_Phdr_Range = typename ELFT::PhdrRange;
+
+ // This is a callback that can be passed to a number of functions.
+ // It can be used to ignore non-critical errors (warnings), which is
+ // useful for dumpers, like llvm-readobj.
+ // It accepts a warning message string and returns a success
+ // when the warning should be ignored or an error otherwise.
+ using WarningHandler = llvm::function_ref<Error(const Twine &Msg)>;
const uint8_t *base() const { return Buf.bytes_begin(); }
+ const uint8_t *end() const { return base() + getBufSize(); }
size_t getBufSize() const { return Buf.size(); }
@@ -105,16 +139,18 @@
ELFFile(StringRef Object);
public:
- const Elf_Ehdr *getHeader() const {
- return reinterpret_cast<const Elf_Ehdr *>(base());
+ const Elf_Ehdr &getHeader() const {
+ return *reinterpret_cast<const Elf_Ehdr *>(base());
}
template <typename T>
Expected<const T *> getEntry(uint32_t Section, uint32_t Entry) const;
template <typename T>
- Expected<const T *> getEntry(const Elf_Shdr *Section, uint32_t Entry) const;
+ Expected<const T *> getEntry(const Elf_Shdr &Section, uint32_t Entry) const;
- Expected<StringRef> getStringTable(const Elf_Shdr *Section) const;
+ Expected<StringRef>
+ getStringTable(const Elf_Shdr &Section,
+ WarningHandler WarnHandler = &defaultWarningHandler) const;
Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const;
Expected<StringRef> getStringTableForSymtab(const Elf_Shdr &Section,
Elf_Shdr_Range Sections) const;
@@ -132,65 +168,70 @@
std::string getDynamicTagAsString(uint64_t Type) const;
/// Get the symbol for a given relocation.
- Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
+ Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel &Rel,
const Elf_Shdr *SymTab) const;
static Expected<ELFFile> create(StringRef Object);
- bool isMipsELF64() const {
- return getHeader()->e_machine == ELF::EM_MIPS &&
- getHeader()->getFileClass() == ELF::ELFCLASS64;
+ bool isLE() const {
+ return getHeader().getDataEncoding() == ELF::ELFDATA2LSB;
}
- bool isMips64EL() const {
- return isMipsELF64() &&
- getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
+ bool isMipsELF64() const {
+ return getHeader().e_machine == ELF::EM_MIPS &&
+ getHeader().getFileClass() == ELF::ELFCLASS64;
}
+ bool isMips64EL() const { return isMipsELF64() && isLE(); }
+
Expected<Elf_Shdr_Range> sections() const;
Expected<Elf_Dyn_Range> dynamicEntries() const;
- Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const;
+ Expected<const uint8_t *>
+ toMappedAddr(uint64_t VAddr,
+ WarningHandler WarnHandler = &defaultWarningHandler) const;
Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const {
if (!Sec)
return makeArrayRef<Elf_Sym>(nullptr, nullptr);
- return getSectionContentsAsArray<Elf_Sym>(Sec);
+ return getSectionContentsAsArray<Elf_Sym>(*Sec);
}
- Expected<Elf_Rela_Range> relas(const Elf_Shdr *Sec) const {
+ Expected<Elf_Rela_Range> relas(const Elf_Shdr &Sec) const {
return getSectionContentsAsArray<Elf_Rela>(Sec);
}
- Expected<Elf_Rel_Range> rels(const Elf_Shdr *Sec) const {
+ Expected<Elf_Rel_Range> rels(const Elf_Shdr &Sec) const {
return getSectionContentsAsArray<Elf_Rel>(Sec);
}
- Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const {
+ Expected<Elf_Relr_Range> relrs(const Elf_Shdr &Sec) const {
return getSectionContentsAsArray<Elf_Relr>(Sec);
}
- Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const;
+ std::vector<Elf_Rel> decode_relrs(Elf_Relr_Range relrs) const;
- Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const;
+ Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr &Sec) const;
/// Iterate over program header table.
Expected<Elf_Phdr_Range> program_headers() const {
- if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
+ if (getHeader().e_phnum && getHeader().e_phentsize != sizeof(Elf_Phdr))
return createError("invalid e_phentsize: " +
- Twine(getHeader()->e_phentsize));
- if (getHeader()->e_phoff +
- (getHeader()->e_phnum * getHeader()->e_phentsize) >
- getBufSize())
+ Twine(getHeader().e_phentsize));
+
+ uint64_t HeadersSize =
+ (uint64_t)getHeader().e_phnum * getHeader().e_phentsize;
+ uint64_t PhOff = getHeader().e_phoff;
+ if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
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);
+ 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() + PhOff);
+ return makeArrayRef(Begin, Begin + getHeader().e_phnum);
}
/// Get an iterator over notes in a program header.
@@ -201,14 +242,12 @@
/// \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) {
- // TODO: this error is untested.
- 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()) {
- // TODO: this error is untested.
- Err = createError("invalid program header offset/size");
+ Err =
+ createError("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);
@@ -222,14 +261,12 @@
/// \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) {
- // TODO: this error is untested.
- 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()) {
- // TODO: this error is untested.
- Err = createError("invalid section offset/size");
+ Err =
+ createError("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);
@@ -264,27 +301,31 @@
return make_range(notes_begin(Shdr, Err), notes_end());
}
- Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const;
- Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
- ArrayRef<Elf_Word> ShndxTable) const;
- Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
+ Expected<StringRef> getSectionStringTable(
+ Elf_Shdr_Range Sections,
+ WarningHandler WarnHandler = &defaultWarningHandler) const;
+ Expected<uint32_t> getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms,
+ DataRegion<Elf_Word> ShndxTable) const;
+ Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym,
const Elf_Shdr *SymTab,
- ArrayRef<Elf_Word> ShndxTable) const;
- Expected<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
+ DataRegion<Elf_Word> ShndxTable) const;
+ Expected<const Elf_Shdr *> getSection(const Elf_Sym &Sym,
Elf_Sym_Range Symtab,
- ArrayRef<Elf_Word> ShndxTable) const;
+ DataRegion<Elf_Word> ShndxTable) const;
Expected<const Elf_Shdr *> getSection(uint32_t Index) const;
- Expected<const Elf_Shdr *> getSection(const StringRef SectionName) const;
Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec,
uint32_t Index) const;
- Expected<StringRef> getSectionName(const Elf_Shdr *Section) const;
- Expected<StringRef> getSectionName(const Elf_Shdr *Section,
+ Expected<StringRef>
+ getSectionName(const Elf_Shdr &Section,
+ WarningHandler WarnHandler = &defaultWarningHandler) const;
+ Expected<StringRef> getSectionName(const Elf_Shdr &Section,
StringRef DotShstrtab) const;
template <typename T>
- Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr *Sec) const;
- Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const;
+ Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr &Sec) const;
+ Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr &Sec) const;
+ Expected<ArrayRef<uint8_t>> getSegmentContents(const Elf_Phdr &Phdr) const;
};
using ELF32LEFile = ELFFile<ELF32LE>;
@@ -302,29 +343,30 @@
template <class ELFT>
inline Expected<uint32_t>
-getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym,
- const typename ELFT::Sym *FirstSym,
- ArrayRef<typename ELFT::Word> ShndxTable) {
- assert(Sym->st_shndx == ELF::SHN_XINDEX);
- unsigned Index = Sym - FirstSym;
- if (Index >= ShndxTable.size())
+getExtendedSymbolTableIndex(const typename ELFT::Sym &Sym, unsigned SymIndex,
+ DataRegion<typename ELFT::Word> ShndxTable) {
+ assert(Sym.st_shndx == ELF::SHN_XINDEX);
+ if (!ShndxTable.First)
return createError(
- "extended symbol index (" + Twine(Index) +
- ") is past the end of the SHT_SYMTAB_SHNDX section of size " +
- Twine(ShndxTable.size()));
+ "found an extended symbol index (" + Twine(SymIndex) +
+ "), but unable to locate the extended symbol index table");
- // The size of the table was checked in getSHNDXTable.
- return ShndxTable[Index];
+ Expected<typename ELFT::Word> TableOrErr = ShndxTable[SymIndex];
+ if (!TableOrErr)
+ return createError("unable to read an extended symbol table at index " +
+ Twine(SymIndex) + ": " +
+ toString(TableOrErr.takeError()));
+ return *TableOrErr;
}
template <class ELFT>
Expected<uint32_t>
-ELFFile<ELFT>::getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms,
- ArrayRef<Elf_Word> ShndxTable) const {
- uint32_t Index = Sym->st_shndx;
+ELFFile<ELFT>::getSectionIndex(const Elf_Sym &Sym, Elf_Sym_Range Syms,
+ DataRegion<Elf_Word> ShndxTable) const {
+ uint32_t Index = Sym.st_shndx;
if (Index == ELF::SHN_XINDEX) {
- auto ErrorOrIndex = getExtendedSymbolTableIndex<ELFT>(
- Sym, Syms.begin(), ShndxTable);
+ Expected<uint32_t> ErrorOrIndex =
+ getExtendedSymbolTableIndex<ELFT>(Sym, &Sym - Syms.begin(), ShndxTable);
if (!ErrorOrIndex)
return ErrorOrIndex.takeError();
return *ErrorOrIndex;
@@ -336,8 +378,8 @@
template <class ELFT>
Expected<const typename ELFT::Shdr *>
-ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
- ArrayRef<Elf_Word> ShndxTable) const {
+ELFFile<ELFT>::getSection(const Elf_Sym &Sym, const Elf_Shdr *SymTab,
+ DataRegion<Elf_Word> ShndxTable) const {
auto SymsOrErr = symbols(SymTab);
if (!SymsOrErr)
return SymsOrErr.takeError();
@@ -346,8 +388,8 @@
template <class ELFT>
Expected<const typename ELFT::Shdr *>
-ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols,
- ArrayRef<Elf_Word> ShndxTable) const {
+ELFFile<ELFT>::getSection(const Elf_Sym &Sym, Elf_Sym_Range Symbols,
+ DataRegion<Elf_Word> ShndxTable) const {
auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable);
if (!IndexOrErr)
return IndexOrErr.takeError();
@@ -358,45 +400,48 @@
}
template <class ELFT>
-inline Expected<const typename ELFT::Sym *>
-getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) {
- if (Index >= Symbols.size())
- // TODO: this error is untested.
- 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>
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("section " + getSecIndexForError(this, Sec) +
- " has an invalid sh_entsize: " + Twine(Sec->sh_entsize));
+ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr &Sec) const {
+ if (Sec.sh_entsize != sizeof(T) && sizeof(T) != 1)
+ return createError("section " + getSecIndexForError(*this, Sec) +
+ " has invalid sh_entsize: expected " + Twine(sizeof(T)) +
+ ", but got " + Twine(Sec.sh_entsize));
- uintX_t Offset = Sec->sh_offset;
- uintX_t Size = Sec->sh_size;
+ uintX_t Offset = Sec.sh_offset;
+ uintX_t Size = Sec.sh_size;
if (Size % sizeof(T))
- return createError("section " + getSecIndexForError(this, Sec) +
+ 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("section " + getSecIndexForError(this, Sec) +
+ Twine(Sec.sh_entsize) + ")");
+ if (std::numeric_limits<uintX_t>::max() - Offset < Size)
+ return createError("section " + getSecIndexForError(*this, Sec) +
" has a sh_offset (0x" + Twine::utohexstr(Offset) +
- ") + sh_size (0x" + Twine(Size) +
+ ") + sh_size (0x" + Twine::utohexstr(Size) +
") that cannot be represented");
+ if (Offset + Size > Buf.size())
+ return createError("section " + getSecIndexForError(*this, Sec) +
+ " has a sh_offset (0x" + Twine::utohexstr(Offset) +
+ ") + sh_size (0x" + Twine::utohexstr(Size) +
+ ") that is greater than the file size (0x" +
+ Twine::utohexstr(Buf.size()) + ")");
if (Offset % alignof(T))
// TODO: this error is untested.
@@ -408,13 +453,33 @@
template <class ELFT>
Expected<ArrayRef<uint8_t>>
-ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const {
+ELFFile<ELFT>::getSegmentContents(const Elf_Phdr &Phdr) const {
+ uintX_t Offset = Phdr.p_offset;
+ uintX_t Size = Phdr.p_filesz;
+
+ if (std::numeric_limits<uintX_t>::max() - Offset < Size)
+ return createError("program header " + getPhdrIndexForError(*this, Phdr) +
+ " has a p_offset (0x" + Twine::utohexstr(Offset) +
+ ") + p_filesz (0x" + Twine::utohexstr(Size) +
+ ") that cannot be represented");
+ if (Offset + Size > Buf.size())
+ return createError("program header " + getPhdrIndexForError(*this, Phdr) +
+ " has a p_offset (0x" + Twine::utohexstr(Offset) +
+ ") + p_filesz (0x" + Twine::utohexstr(Size) +
+ ") that is greater than the file size (0x" +
+ Twine::utohexstr(Buf.size()) + ")");
+ return makeArrayRef(base() + Offset, Size);
+}
+
+template <class ELFT>
+Expected<ArrayRef<uint8_t>>
+ELFFile<ELFT>::getSectionContents(const Elf_Shdr &Sec) const {
return getSectionContentsAsArray<uint8_t>(Sec);
}
template <class ELFT>
StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
- return getELFRelocationTypeName(getHeader()->e_machine, Type);
+ return getELFRelocationTypeName(getHeader().e_machine, Type);
}
template <class ELFT>
@@ -450,32 +515,42 @@
template <class ELFT>
uint32_t ELFFile<ELFT>::getRelativeRelocationType() const {
- return getELFRelativeRelocationType(getHeader()->e_machine);
+ return getELFRelativeRelocationType(getHeader().e_machine);
}
template <class ELFT>
Expected<const typename ELFT::Sym *>
-ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
+ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel &Rel,
const Elf_Shdr *SymTab) const {
- uint32_t Index = Rel->getSymbol(isMips64EL());
+ uint32_t Index = Rel.getSymbol(isMips64EL());
if (Index == 0)
return nullptr;
- return getEntry<Elf_Sym>(SymTab, Index);
+ return getEntry<Elf_Sym>(*SymTab, Index);
}
template <class ELFT>
Expected<StringRef>
-ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const {
- uint32_t Index = getHeader()->e_shstrndx;
- if (Index == ELF::SHN_XINDEX)
+ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
+ WarningHandler WarnHandler) const {
+ uint32_t Index = getHeader().e_shstrndx;
+ if (Index == ELF::SHN_XINDEX) {
+ // If the section name string table section index is greater than
+ // or equal to SHN_LORESERVE, then the actual index of the section name
+ // string table section is contained in the sh_link field of the section
+ // header at index 0.
+ if (Sections.empty())
+ return createError(
+ "e_shstrndx == SHN_XINDEX, but the section header table is empty");
+
Index = Sections[0].sh_link;
+ }
if (!Index) // no section string table.
return "";
if (Index >= Sections.size())
- // TODO: this error is untested.
- return createError("invalid section index");
- return getStringTable(&Sections[Index]);
+ return createError("section header string table index " + Twine(Index) +
+ " does not exist");
+ return getStringTable(Sections[Index], WarnHandler);
}
template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
@@ -491,16 +566,17 @@
template <class ELFT>
Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
- const uintX_t SectionTableOffset = getHeader()->e_shoff;
+ const uintX_t SectionTableOffset = getHeader().e_shoff;
if (SectionTableOffset == 0)
return ArrayRef<Elf_Shdr>();
- if (getHeader()->e_shentsize != sizeof(Elf_Shdr))
+ if (getHeader().e_shentsize != sizeof(Elf_Shdr))
return createError("invalid e_shentsize in ELF header: " +
- Twine(getHeader()->e_shentsize));
+ Twine(getHeader().e_shentsize));
const uint64_t FileSize = Buf.size();
- if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
+ if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize ||
+ SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset)
return createError(
"section header table goes past the end of the file: e_shoff = 0x" +
Twine::utohexstr(SectionTableOffset));
@@ -513,20 +589,27 @@
const Elf_Shdr *First =
reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
- uintX_t NumSections = getHeader()->e_shnum;
+ uintX_t NumSections = getHeader().e_shnum;
if (NumSections == 0)
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");
+ return createError("invalid number of sections specified in the NULL "
+ "section's sh_size field (" +
+ Twine(NumSections) + ")");
const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
+ if (SectionTableOffset + SectionTableSize < SectionTableOffset)
+ return createError(
+ "invalid section header table offset (e_shoff = 0x" +
+ Twine::utohexstr(SectionTableOffset) +
+ ") or invalid number of sections specified in the first section "
+ "header's sh_size field (0x" +
+ Twine::utohexstr(NumSections) + ")");
// Section table goes past end of file!
if (SectionTableOffset + SectionTableSize > FileSize)
return createError("section table goes past the end of file");
-
return makeArrayRef(First, NumSections);
}
@@ -537,23 +620,25 @@
auto SecOrErr = getSection(Section);
if (!SecOrErr)
return SecOrErr.takeError();
- return getEntry<T>(*SecOrErr, Entry);
+ return getEntry<T>(**SecOrErr, Entry);
}
template <class ELFT>
template <typename T>
-Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section,
+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("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);
+ Expected<ArrayRef<T>> EntriesOrErr = getSectionContentsAsArray<T>(Section);
+ if (!EntriesOrErr)
+ return EntriesOrErr.takeError();
+
+ ArrayRef<T> Arr = *EntriesOrErr;
+ if (Entry >= Arr.size())
+ return createError(
+ "can't read an entry at 0x" +
+ Twine::utohexstr(Entry * static_cast<uint64_t>(sizeof(T))) +
+ ": it goes past the end of the section (0x" +
+ Twine::utohexstr(Section.sh_size) + ")");
+ return &Arr[Entry];
}
template <class ELFT>
@@ -566,43 +651,27 @@
}
template <class ELFT>
-Expected<const typename ELFT::Shdr *>
-ELFFile<ELFT>::getSection(const StringRef SectionName) const {
- auto TableOrErr = sections();
- if (!TableOrErr)
- return TableOrErr.takeError();
- for (auto &Sec : *TableOrErr) {
- auto SecNameOrErr = getSectionName(&Sec);
- if (!SecNameOrErr)
- return SecNameOrErr.takeError();
- if (*SecNameOrErr == SectionName)
- return &Sec;
- }
- // TODO: this error is untested.
- return createError("invalid section name");
-}
-
-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 section " +
- getSecIndexForError(this, Section) +
- ": expected SHT_STRTAB, but got " +
- object::getELFSectionTypeName(getHeader()->e_machine,
- Section->sh_type));
+ELFFile<ELFT>::getStringTable(const Elf_Shdr &Section,
+ WarningHandler WarnHandler) const {
+ if (Section.sh_type != ELF::SHT_STRTAB)
+ if (Error E = WarnHandler("invalid sh_type for string table section " +
+ getSecIndexForError(*this, Section) +
+ ": expected SHT_STRTAB, but got " +
+ object::getELFSectionTypeName(
+ getHeader().e_machine, Section.sh_type)))
+ return std::move(E);
+
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");
+ return createError("SHT_STRTAB string table section " +
+ getSecIndexForError(*this, Section) + " is empty");
if (Data.back() != '\0')
- return createError(object::getELFSectionTypeName(getHeader()->e_machine,
- Section->sh_type) +
- " string table section " +
- getSecIndexForError(this, Section) +
+ return createError("SHT_STRTAB string table section " +
+ getSecIndexForError(*this, Section) +
" is non-null terminated");
return StringRef(Data.begin(), Data.size());
}
@@ -621,7 +690,7 @@
ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section,
Elf_Shdr_Range Sections) const {
assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);
- auto VOrErr = getSectionContentsAsArray<Elf_Word>(&Section);
+ auto VOrErr = getSectionContentsAsArray<Elf_Word>(Section);
if (!VOrErr)
return VOrErr.takeError();
ArrayRef<Elf_Word> V = *VOrErr;
@@ -631,13 +700,17 @@
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("SHT_SYMTAB_SHNDX section has sh_size (" +
- Twine(SymTable.sh_size) +
- ") which is not equal to the number of symbols (" +
- Twine(V.size()) + ")");
+ return createError(
+ "SHT_SYMTAB_SHNDX section is linked with " +
+ object::getELFSectionTypeName(getHeader().e_machine, SymTable.sh_type) +
+ " section (expected SHT_SYMTAB/SHT_DYNSYM)");
+
+ uint64_t Syms = SymTable.sh_size / sizeof(Elf_Sym);
+ if (V.size() != Syms)
+ return createError("SHT_SYMTAB_SHNDX has " + Twine(V.size()) +
+ " entries, but the symbol table associated has " +
+ Twine(Syms));
+
return V;
}
@@ -656,35 +729,36 @@
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);
+ Expected<const Elf_Shdr *> SectionOrErr =
+ object::getSection<ELFT>(Sections, Sec.sh_link);
if (!SectionOrErr)
return SectionOrErr.takeError();
- return getStringTable(*SectionOrErr);
+ return getStringTable(**SectionOrErr);
}
template <class ELFT>
Expected<StringRef>
-ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const {
+ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section,
+ WarningHandler WarnHandler) const {
auto SectionsOrErr = sections();
if (!SectionsOrErr)
return SectionsOrErr.takeError();
- auto Table = getSectionStringTable(*SectionsOrErr);
+ auto Table = getSectionStringTable(*SectionsOrErr, WarnHandler);
if (!Table)
return Table.takeError();
return getSectionName(Section, *Table);
}
template <class ELFT>
-Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section,
+Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr &Section,
StringRef DotShstrtab) const {
- uint32_t Offset = Section->sh_name;
+ uint32_t Offset = Section.sh_name;
if (Offset == 0)
return StringRef();
if (Offset >= DotShstrtab.size())
- return createError("a section " + getSecIndexForError(this, Section) +
+ return createError("a section " + getSecIndexForError(*this, Section) +
" has an invalid sh_name (0x" +
Twine::utohexstr(Offset) +
") offset which goes past the end of the "
diff --git a/linux-x64/clang/include/llvm/Object/ELFObjectFile.h b/linux-x64/clang/include/llvm/Object/ELFObjectFile.h
index 86c015e..fed53ee 100644
--- a/linux-x64/clang/include/llvm/Object/ELFObjectFile.h
+++ b/linux-x64/clang/include/llvm/Object/ELFObjectFile.h
@@ -28,8 +28,8 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/ARMAttributeParser.h"
-#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/ELFAttributes.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
@@ -41,7 +41,7 @@
namespace llvm {
namespace object {
-constexpr int NumElfSymbolTypes = 8;
+constexpr int NumElfSymbolTypes = 16;
extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes];
class elf_symbol_iterator;
@@ -51,6 +51,12 @@
friend class ELFSectionRef;
friend class ELFSymbolRef;
+ SubtargetFeatures getMIPSFeatures() const;
+ SubtargetFeatures getARMFeatures() const;
+ SubtargetFeatures getRISCVFeatures() const;
+
+ StringRef getAMDGPUCPUName() const;
+
protected:
ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
@@ -64,7 +70,7 @@
virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0;
virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
- virtual Error getBuildAttributes(ARMAttributeParser &Attributes) const = 0;
+ virtual Error getBuildAttributes(ELFAttributeParser &Attributes) const = 0;
public:
using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>;
@@ -80,11 +86,7 @@
SubtargetFeatures getFeatures() const override;
- SubtargetFeatures getMIPSFeatures() const;
-
- SubtargetFeatures getARMFeatures() const;
-
- SubtargetFeatures getRISCVFeatures() const;
+ Optional<StringRef> tryGetCPUName() const override;
void setARMSubArch(Triple &TheTriple) const override;
@@ -92,7 +94,8 @@
virtual uint16_t getEMachine() const = 0;
- std::vector<std::pair<DataRefImpl, uint64_t>> getPltAddresses() const;
+ std::vector<std::pair<Optional<DataRefImpl>, uint64_t>>
+ getPltAddresses() const;
};
class ELFSectionRef : public SectionRef {
@@ -230,26 +233,31 @@
public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
- using uintX_t = typename ELFT::uint;
+ SectionRef toSectionRef(const Elf_Shdr *Sec) const {
+ return SectionRef(toDRI(Sec), this);
+ }
- using Elf_Sym = typename ELFT::Sym;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Ehdr = typename ELFT::Ehdr;
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
- using Elf_Dyn = typename ELFT::Dyn;
+ ELFSymbolRef toSymbolRef(const Elf_Shdr *SymTable, unsigned SymbolNum) const {
+ return ELFSymbolRef({toDRI(SymTable, SymbolNum), this});
+ }
+
+ bool IsContentValid() const { return ContentValid; }
private:
ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF,
const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec,
- ArrayRef<Elf_Word> ShndxTable);
+ const Elf_Shdr *DotSymtabShndxSec);
+
+ bool ContentValid = false;
protected:
ELFFile<ELFT> EF;
const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
- ArrayRef<Elf_Word> ShndxTable;
+ const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section.
+
+ Error initContent() override;
void moveSymbolNext(DataRefImpl &Symb) const override;
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
@@ -257,7 +265,7 @@
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
- uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ Expected<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;
@@ -281,10 +289,12 @@
bool isSectionVirtual(DataRefImpl Sec) const override;
bool isBerkeleyText(DataRefImpl Sec) const override;
bool isBerkeleyData(DataRefImpl Sec) const override;
+ bool isDebugSection(StringRef SectionName) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
std::vector<SectionRef> dynamic_relocation_sections() const override;
- section_iterator getRelocatedSection(DataRefImpl Sec) const override;
+ Expected<section_iterator>
+ getRelocatedSection(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
uint64_t getRelocationOffset(DataRefImpl Rel) const override;
@@ -298,14 +308,6 @@
uint64_t getSectionOffset(DataRefImpl Sec) const override;
StringRef getRelocationTypeName(uint32_t Type) const;
- /// Get the relocation section that contains \a Rel.
- const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
- auto RelSecOrErr = EF.getSection(Rel.d.a);
- if (!RelSecOrErr)
- report_fatal_error(errorToErrorCode(RelSecOrErr.takeError()).message());
- return *RelSecOrErr;
- }
-
DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const {
DataRefImpl DRI;
if (!SymTable) {
@@ -360,22 +362,24 @@
(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED));
}
- Error getBuildAttributes(ARMAttributeParser &Attributes) const override {
+ Error getBuildAttributes(ELFAttributeParser &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 (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES ||
+ Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) {
+ auto ErrorOrContents = EF.getSectionContents(Sec);
if (!ErrorOrContents)
return ErrorOrContents.takeError();
auto Contents = ErrorOrContents.get();
- if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
+ if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1)
return Error::success();
- Attributes.Parse(Contents, ELFT::TargetEndianness == support::little);
+ if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness))
+ return E;
break;
}
}
@@ -389,16 +393,22 @@
public:
ELFObjectFile(ELFObjectFile<ELFT> &&Other);
- static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object);
+ static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object,
+ bool InitContent = true);
const Elf_Rel *getRel(DataRefImpl Rel) const;
const Elf_Rela *getRela(DataRefImpl Rela) const;
- const Elf_Sym *getSymbol(DataRefImpl Sym) const {
- auto Ret = EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
- if (!Ret)
- report_fatal_error(errorToErrorCode(Ret.takeError()).message());
- return *Ret;
+ Expected<const Elf_Sym *> getSymbol(DataRefImpl Sym) const {
+ return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
+ }
+
+ /// Get the relocation section that contains \a Rel.
+ const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
+ auto RelSecOrErr = EF.getSection(Rel.d.a);
+ if (!RelSecOrErr)
+ report_fatal_error(errorToErrorCode(RelSecOrErr.takeError()).message());
+ return *RelSecOrErr;
}
const Elf_Shdr *getSection(DataRefImpl Sec) const {
@@ -421,9 +431,9 @@
Triple::ArchType getArch() const override;
Expected<uint64_t> getStartAddress() const override;
- unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; }
+ unsigned getPlatformFlags() const override { return EF.getHeader().e_flags; }
- const ELFFile<ELFT> *getELFFile() const { return &EF; }
+ const ELFFile<ELFT> &getELFFile() const { return EF; }
bool isDyldType() const { return isDyldELFObject; }
static bool classof(const Binary *v) {
@@ -446,9 +456,40 @@
++Sym.d.b;
}
+template <class ELFT> Error ELFObjectFile<ELFT>::initContent() {
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return SectionsOrErr.takeError();
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_DYNSYM: {
+ if (!DotDynSymSec)
+ DotDynSymSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB: {
+ if (!DotSymtabSec)
+ DotSymtabSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB_SHNDX: {
+ if (!DotSymtabShndxSec)
+ DotSymtabShndxSec = &Sec;
+ break;
+ }
+ }
+ }
+
+ ContentValid = true;
+ return Error::success();
+}
+
template <class ELFT>
Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
- const Elf_Sym *ESym = getSymbol(Sym);
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym);
+ if (!SymOrErr)
+ return SymOrErr.takeError();
auto SymTabOrErr = EF.getSection(Sym.d.a);
if (!SymTabOrErr)
return SymTabOrErr.takeError();
@@ -457,17 +498,19 @@
if (!StrTabOrErr)
return StrTabOrErr.takeError();
const Elf_Shdr *StringTableSec = *StrTabOrErr;
- auto SymStrTabOrErr = EF.getStringTable(StringTableSec);
+ auto SymStrTabOrErr = EF.getStringTable(*StringTableSec);
if (!SymStrTabOrErr)
return SymStrTabOrErr.takeError();
- Expected<StringRef> Name = ESym->getName(*SymStrTabOrErr);
+ Expected<StringRef> Name = (*SymOrErr)->getName(*SymStrTabOrErr);
+ if (Name && !Name->empty())
+ return Name;
// 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;
+ if ((*SymOrErr)->getType() == ELF::STT_SECTION) {
+ if (Expected<section_iterator> SecOrErr = getSymbolSection(Sym)) {
+ consumeError(Name.takeError());
+ return (*SecOrErr)->getName();
+ }
}
return Name;
}
@@ -489,15 +532,18 @@
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const {
- const Elf_Sym *ESym = getSymbol(Symb);
- uint64_t Ret = ESym->st_value;
- if (ESym->st_shndx == ELF::SHN_ABS)
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ report_fatal_error(SymOrErr.takeError());
+
+ uint64_t Ret = (*SymOrErr)->st_value;
+ if ((*SymOrErr)->st_shndx == ELF::SHN_ABS)
return Ret;
- const Elf_Ehdr *Header = EF.getHeader();
+ const Elf_Ehdr &Header = EF.getHeader();
// Clear the ARM/Thumb or microMIPS indicator flag.
- if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) &&
- ESym->getType() == ELF::STT_FUNC)
+ if ((Header.e_machine == ELF::EM_ARM || Header.e_machine == ELF::EM_MIPS) &&
+ (*SymOrErr)->getType() == ELF::STT_FUNC)
Ret &= ~1;
return Ret;
@@ -506,23 +552,40 @@
template <class ELFT>
Expected<uint64_t>
ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const {
- uint64_t Result = getSymbolValue(Symb);
- const Elf_Sym *ESym = getSymbol(Symb);
- switch (ESym->st_shndx) {
+ Expected<uint64_t> SymbolValueOrErr = getSymbolValue(Symb);
+ if (!SymbolValueOrErr)
+ // TODO: Test this error.
+ return SymbolValueOrErr.takeError();
+
+ uint64_t Result = *SymbolValueOrErr;
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ return SymOrErr.takeError();
+
+ switch ((*SymOrErr)->st_shndx) {
case ELF::SHN_COMMON:
case ELF::SHN_UNDEF:
case ELF::SHN_ABS:
return Result;
}
- const Elf_Ehdr *Header = EF.getHeader();
auto SymTabOrErr = EF.getSection(Symb.d.a);
if (!SymTabOrErr)
return SymTabOrErr.takeError();
- const Elf_Shdr *SymTab = *SymTabOrErr;
- if (Header->e_type == ELF::ET_REL) {
- auto SectionOrErr = EF.getSection(ESym, SymTab, ShndxTable);
+ if (EF.getHeader().e_type == ELF::ET_REL) {
+ ArrayRef<Elf_Word> ShndxTable;
+ if (DotSymtabShndxSec) {
+ // TODO: Test this error.
+ if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =
+ EF.getSHNDXTable(*DotSymtabShndxSec))
+ ShndxTable = *ShndxTableOrErr;
+ else
+ return ShndxTableOrErr.takeError();
+ }
+
+ Expected<const Elf_Shdr *> SectionOrErr =
+ EF.getSection(**SymOrErr, *SymTabOrErr, ShndxTable);
if (!SectionOrErr)
return SectionOrErr.takeError();
const Elf_Shdr *Section = *SectionOrErr;
@@ -535,52 +598,68 @@
template <class ELFT>
uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
- const Elf_Sym *Sym = getSymbol(Symb);
- if (Sym->st_shndx == ELF::SHN_COMMON)
- return Sym->st_value;
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ report_fatal_error(SymOrErr.takeError());
+ if ((*SymOrErr)->st_shndx == ELF::SHN_COMMON)
+ return (*SymOrErr)->st_value;
return 0;
}
template <class ELFT>
uint16_t ELFObjectFile<ELFT>::getEMachine() const {
- return EF.getHeader()->e_machine;
+ return EF.getHeader().e_machine;
}
template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const {
- return EF.getHeader()->e_type;
+ return EF.getHeader().e_type;
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
- return getSymbol(Sym)->st_size;
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym);
+ if (!SymOrErr)
+ report_fatal_error(SymOrErr.takeError());
+ return (*SymOrErr)->st_size;
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
- return getSymbol(Symb)->st_size;
+ return getSymbolSize(Symb);
}
template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const {
- return getSymbol(Symb)->getBinding();
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ report_fatal_error(SymOrErr.takeError());
+ return (*SymOrErr)->getBinding();
}
template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const {
- return getSymbol(Symb)->st_other;
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ report_fatal_error(SymOrErr.takeError());
+ return (*SymOrErr)->st_other;
}
template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const {
- return getSymbol(Symb)->getType();
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ report_fatal_error(SymOrErr.takeError());
+ return (*SymOrErr)->getType();
}
template <class ELFT>
Expected<SymbolRef::Type>
ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const {
- const Elf_Sym *ESym = getSymbol(Symb);
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ return SymOrErr.takeError();
- switch (ESym->getType()) {
+ switch ((*SymOrErr)->getType()) {
case ELF::STT_NOTYPE:
return SymbolRef::ST_Unknown;
case ELF::STT_SECTION:
@@ -599,9 +678,12 @@
}
template <class ELFT>
-uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
- const Elf_Sym *ESym = getSymbol(Sym);
+Expected<uint32_t> ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const {
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym);
+ if (!SymOrErr)
+ return SymOrErr.takeError();
+ const Elf_Sym *ESym = *SymOrErr;
uint32_t Result = SymbolRef::SF_None;
if (ESym->getBinding() != ELF::STB_LOCAL)
@@ -616,14 +698,25 @@
if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION)
Result |= SymbolRef::SF_FormatSpecific;
- auto DotSymtabSecSyms = EF.symbols(DotSymtabSec);
- if (DotSymtabSecSyms && ESym == (*DotSymtabSecSyms).begin())
- Result |= SymbolRef::SF_FormatSpecific;
- auto DotDynSymSecSyms = EF.symbols(DotDynSymSec);
- if (DotDynSymSecSyms && ESym == (*DotDynSymSecSyms).begin())
- Result |= SymbolRef::SF_FormatSpecific;
+ if (Expected<typename ELFT::SymRange> SymbolsOrErr =
+ EF.symbols(DotSymtabSec)) {
+ // Set the SF_FormatSpecific flag for the 0-index null symbol.
+ if (ESym == SymbolsOrErr->begin())
+ Result |= SymbolRef::SF_FormatSpecific;
+ } else
+ // TODO: Test this error.
+ return SymbolsOrErr.takeError();
- if (EF.getHeader()->e_machine == ELF::EM_ARM) {
+ if (Expected<typename ELFT::SymRange> SymbolsOrErr =
+ EF.symbols(DotDynSymSec)) {
+ // Set the SF_FormatSpecific flag for the 0-index null symbol.
+ if (ESym == SymbolsOrErr->begin())
+ Result |= SymbolRef::SF_FormatSpecific;
+ } else
+ // TODO: Test this error.
+ return SymbolsOrErr.takeError();
+
+ if (EF.getHeader().e_machine == ELF::EM_ARM) {
if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) {
StringRef Name = *NameOrErr;
if (Name.startswith("$d") || Name.startswith("$t") ||
@@ -656,7 +749,17 @@
Expected<section_iterator>
ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
const Elf_Shdr *SymTab) const {
- auto ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable);
+ ArrayRef<Elf_Word> ShndxTable;
+ if (DotSymtabShndxSec) {
+ // TODO: Test this error.
+ Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =
+ EF.getSHNDXTable(*DotSymtabShndxSec);
+ if (!ShndxTableOrErr)
+ return ShndxTableOrErr.takeError();
+ ShndxTable = *ShndxTableOrErr;
+ }
+
+ auto ESecOrErr = EF.getSection(*ESym, SymTab, ShndxTable);
if (!ESecOrErr)
return ESecOrErr.takeError();
@@ -672,12 +775,14 @@
template <class ELFT>
Expected<section_iterator>
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const {
- const Elf_Sym *Sym = getSymbol(Symb);
+ Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb);
+ if (!SymOrErr)
+ return SymOrErr.takeError();
+
auto SymTabOrErr = EF.getSection(Symb.d.a);
if (!SymTabOrErr)
return SymTabOrErr.takeError();
- const Elf_Shdr *SymTab = *SymTabOrErr;
- return getSymbolSection(Sym, SymTab);
+ return getSymbolSection(*SymOrErr, *SymTabOrErr);
}
template <class ELFT>
@@ -688,7 +793,7 @@
template <class ELFT>
Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const {
- return EF.getSectionName(&*getSection(Sec));
+ return EF.getSectionName(*getSection(Sec));
}
template <class ELFT>
@@ -716,10 +821,12 @@
Expected<ArrayRef<uint8_t>>
ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const {
const Elf_Shdr *EShdr = getSection(Sec);
- if (std::error_code EC =
+ if (EShdr->sh_type == ELF::SHT_NOBITS)
+ return makeArrayRef((const uint8_t *)base(), 0);
+ if (Error E =
checkOffset(getMemoryBufferRef(),
(uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size))
- return errorCodeToError(EC);
+ return std::move(E);
return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset,
EShdr->sh_size);
}
@@ -803,6 +910,12 @@
}
template <class ELFT>
+bool ELFObjectFile<ELFT>::isDebugSection(StringRef SectionName) const {
+ return SectionName.startswith(".debug") ||
+ SectionName.startswith(".zdebug") || SectionName == ".gdb_index";
+}
+
+template <class ELFT>
relocation_iterator
ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
DataRefImpl RelData;
@@ -810,7 +923,7 @@
if (!SectionsOrErr)
return relocation_iterator(RelocationRef());
uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin());
- RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize;
+ RelData.d.a = (Sec.p - SHT) / EF.getHeader().e_shentsize;
RelData.d.b = 0;
return relocation_iterator(RelocationRef(RelData, this));
}
@@ -835,9 +948,9 @@
}
template <class ELFT>
-section_iterator
+Expected<section_iterator>
ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
- if (EF.getHeader()->e_type != ELF::ET_REL)
+ if (EF.getHeader().e_type != ELF::ET_REL)
return section_end();
const Elf_Shdr *EShdr = getSection(Sec);
@@ -845,10 +958,10 @@
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
return section_end();
- auto R = EF.getSection(EShdr->sh_info);
- if (!R)
- report_fatal_error(errorToErrorCode(R.takeError()).message());
- return section_iterator(SectionRef(toDRI(*R), this));
+ Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info);
+ if (!SecOrErr)
+ return SecOrErr.takeError();
+ return section_iterator(SectionRef(toDRI(*SecOrErr), this));
}
// Relocations
@@ -896,7 +1009,7 @@
template <class ELFT>
StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
- return getELFRelocationTypeName(EF.getHeader()->e_machine, Type);
+ return getELFRelocationTypeName(EF.getHeader().e_machine, Type);
}
template <class ELFT>
@@ -936,59 +1049,34 @@
template <class ELFT>
Expected<ELFObjectFile<ELFT>>
-ELFObjectFile<ELFT>::create(MemoryBufferRef Object) {
+ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) {
auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer());
if (Error E = EFOrErr.takeError())
return std::move(E);
- auto EF = std::move(*EFOrErr);
- auto SectionsOrErr = EF.sections();
- if (!SectionsOrErr)
- return SectionsOrErr.takeError();
-
- const Elf_Shdr *DotDynSymSec = nullptr;
- const Elf_Shdr *DotSymtabSec = nullptr;
- ArrayRef<Elf_Word> ShndxTable;
- for (const Elf_Shdr &Sec : *SectionsOrErr) {
- switch (Sec.sh_type) {
- case ELF::SHT_DYNSYM: {
- if (!DotDynSymSec)
- DotDynSymSec = &Sec;
- break;
- }
- case ELF::SHT_SYMTAB: {
- if (!DotSymtabSec)
- DotSymtabSec = &Sec;
- break;
- }
- case ELF::SHT_SYMTAB_SHNDX: {
- auto TableOrErr = EF.getSHNDXTable(Sec);
- if (!TableOrErr)
- return TableOrErr.takeError();
- ShndxTable = *TableOrErr;
- break;
- }
- }
- }
- return ELFObjectFile<ELFT>(Object, EF, DotDynSymSec, DotSymtabSec,
- ShndxTable);
+ ELFObjectFile<ELFT> Obj = {Object, std::move(*EFOrErr), nullptr, nullptr,
+ nullptr};
+ if (InitContent)
+ if (Error E = Obj.initContent())
+ return std::move(E);
+ return std::move(Obj);
}
template <class ELFT>
ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF,
const Elf_Shdr *DotDynSymSec,
const Elf_Shdr *DotSymtabSec,
- ArrayRef<Elf_Word> ShndxTable)
+ const Elf_Shdr *DotSymtabShndx)
: ELFObjectFileBase(
getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits),
Object),
EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec),
- ShndxTable(ShndxTable) {}
+ DotSymtabShndxSec(DotSymtabShndx) {}
template <class ELFT>
ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other)
: ELFObjectFile(Other.Data, Other.EF, Other.DotDynSymSec,
- Other.DotSymtabSec, Other.ShndxTable) {}
+ Other.DotSymtabSec, Other.DotSymtabShndxSec) {}
template <class ELFT>
basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const {
@@ -1009,8 +1097,12 @@
template <class ELFT>
elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const {
- DataRefImpl Sym = toDRI(DotDynSymSec, 0);
- return symbol_iterator(SymbolRef(Sym, this));
+ if (!DotDynSymSec || DotDynSymSec->sh_size < sizeof(Elf_Sym))
+ // Ignore errors here where the dynsym is empty or sh_size less than the
+ // size of one symbol. These should be handled elsewhere.
+ return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 0), this));
+ // Skip 0-index NULL symbol.
+ return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 1), this));
}
template <class ELFT>
@@ -1046,63 +1138,67 @@
template <class ELFT>
StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
bool IsLittleEndian = ELFT::TargetEndianness == support::little;
- switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
+ switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
- switch (EF.getHeader()->e_machine) {
+ switch (EF.getHeader().e_machine) {
case ELF::EM_386:
- return "ELF32-i386";
+ return "elf32-i386";
case ELF::EM_IAMCU:
- return "ELF32-iamcu";
+ return "elf32-iamcu";
case ELF::EM_X86_64:
- return "ELF32-x86-64";
+ return "elf32-x86-64";
case ELF::EM_ARM:
- return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big");
+ return (IsLittleEndian ? "elf32-littlearm" : "elf32-bigarm");
case ELF::EM_AVR:
- return "ELF32-avr";
+ return "elf32-avr";
case ELF::EM_HEXAGON:
- return "ELF32-hexagon";
+ return "elf32-hexagon";
case ELF::EM_LANAI:
- return "ELF32-lanai";
+ return "elf32-lanai";
case ELF::EM_MIPS:
- return "ELF32-mips";
+ return "elf32-mips";
case ELF::EM_MSP430:
- return "ELF32-msp430";
+ return "elf32-msp430";
case ELF::EM_PPC:
- return "ELF32-ppc";
+ return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc");
case ELF::EM_RISCV:
- return "ELF32-riscv";
+ return "elf32-littleriscv";
+ case ELF::EM_CSKY:
+ return "elf32-csky";
case ELF::EM_SPARC:
case ELF::EM_SPARC32PLUS:
- return "ELF32-sparc";
+ return "elf32-sparc";
case ELF::EM_AMDGPU:
- return "ELF32-amdgpu";
+ return "elf32-amdgpu";
default:
- return "ELF32-unknown";
+ return "elf32-unknown";
}
case ELF::ELFCLASS64:
- switch (EF.getHeader()->e_machine) {
+ switch (EF.getHeader().e_machine) {
case ELF::EM_386:
- return "ELF64-i386";
+ return "elf64-i386";
case ELF::EM_X86_64:
- return "ELF64-x86-64";
+ return "elf64-x86-64";
case ELF::EM_AARCH64:
- return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big");
+ return (IsLittleEndian ? "elf64-littleaarch64" : "elf64-bigaarch64");
case ELF::EM_PPC64:
- return "ELF64-ppc64";
+ return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc");
case ELF::EM_RISCV:
- return "ELF64-riscv";
+ return "elf64-littleriscv";
case ELF::EM_S390:
- return "ELF64-s390";
+ return "elf64-s390";
case ELF::EM_SPARCV9:
- return "ELF64-sparc";
+ return "elf64-sparc";
case ELF::EM_MIPS:
- return "ELF64-mips";
+ return "elf64-mips";
case ELF::EM_AMDGPU:
- return "ELF64-amdgpu";
+ return "elf64-amdgpu";
case ELF::EM_BPF:
- return "ELF64-BPF";
+ return "elf64-bpf";
+ case ELF::EM_VE:
+ return "elf64-ve";
default:
- return "ELF64-unknown";
+ return "elf64-unknown";
}
default:
// FIXME: Proper error handling.
@@ -1112,7 +1208,7 @@
template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
bool IsLittleEndian = ELFT::TargetEndianness == support::little;
- switch (EF.getHeader()->e_machine) {
+ switch (EF.getHeader().e_machine) {
case ELF::EM_386:
case ELF::EM_IAMCU:
return Triple::x86;
@@ -1129,7 +1225,7 @@
case ELF::EM_LANAI:
return Triple::lanai;
case ELF::EM_MIPS:
- switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
+ switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
return IsLittleEndian ? Triple::mipsel : Triple::mips;
case ELF::ELFCLASS64:
@@ -1140,11 +1236,11 @@
case ELF::EM_MSP430:
return Triple::msp430;
case ELF::EM_PPC:
- return Triple::ppc;
+ return IsLittleEndian ? Triple::ppcle : Triple::ppc;
case ELF::EM_PPC64:
return IsLittleEndian ? Triple::ppc64le : Triple::ppc64;
case ELF::EM_RISCV:
- switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) {
+ switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
return Triple::riscv32;
case ELF::ELFCLASS64:
@@ -1165,7 +1261,7 @@
if (!IsLittleEndian)
return Triple::UnknownArch;
- unsigned MACH = EF.getHeader()->e_flags & ELF::EF_AMDGPU_MACH;
+ unsigned MACH = EF.getHeader().e_flags & ELF::EF_AMDGPU_MACH;
if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST &&
MACH <= ELF::EF_AMDGPU_MACH_R600_LAST)
return Triple::r600;
@@ -1179,6 +1275,10 @@
case ELF::EM_BPF:
return IsLittleEndian ? Triple::bpfel : Triple::bpfeb;
+ case ELF::EM_VE:
+ return Triple::ve;
+ case ELF::EM_CSKY:
+ return Triple::csky;
default:
return Triple::UnknownArch;
}
@@ -1186,7 +1286,7 @@
template <class ELFT>
Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const {
- return EF.getHeader()->e_entry;
+ return EF.getHeader().e_entry;
}
template <class ELFT>
@@ -1196,7 +1296,7 @@
}
template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
- return EF.getHeader()->e_type == ELF::ET_REL;
+ return EF.getHeader().e_type == ELF::ET_REL;
}
} // end namespace object
diff --git a/linux-x64/clang/include/llvm/Object/ELFTypes.h b/linux-x64/clang/include/llvm/Object/ELFTypes.h
index 5552208..f64e7c0 100644
--- a/linux-x64/clang/include/llvm/Object/ELFTypes.h
+++ b/linux-x64/clang/include/llvm/Object/ELFTypes.h
@@ -53,7 +53,7 @@
static const endianness TargetEndianness = E;
static const bool Is64Bits = Is64;
- using uint = typename std::conditional<Is64, uint64_t, uint32_t>::type;
+ using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
using Ehdr = Elf_Ehdr_Impl<ELFType<E, Is64>>;
using Shdr = Elf_Shdr_Impl<ELFType<E, Is64>>;
using Sym = Elf_Sym_Impl<ELFType<E, Is64>>;
@@ -107,7 +107,34 @@
using Elf_Word = typename ELFT::Word; \
using Elf_Sword = typename ELFT::Sword; \
using Elf_Xword = typename ELFT::Xword; \
- using Elf_Sxword = typename ELFT::Sxword;
+ using Elf_Sxword = typename ELFT::Sxword; \
+ using uintX_t = typename ELFT::uint; \
+ using Elf_Ehdr = typename ELFT::Ehdr; \
+ using Elf_Shdr = typename ELFT::Shdr; \
+ using Elf_Sym = typename ELFT::Sym; \
+ using Elf_Dyn = typename ELFT::Dyn; \
+ using Elf_Phdr = typename ELFT::Phdr; \
+ using Elf_Rel = typename ELFT::Rel; \
+ using Elf_Rela = typename ELFT::Rela; \
+ using Elf_Relr = typename ELFT::Relr; \
+ using Elf_Verdef = typename ELFT::Verdef; \
+ using Elf_Verdaux = typename ELFT::Verdaux; \
+ using Elf_Verneed = typename ELFT::Verneed; \
+ using Elf_Vernaux = typename ELFT::Vernaux; \
+ using Elf_Versym = typename ELFT::Versym; \
+ using Elf_Hash = typename ELFT::Hash; \
+ using Elf_GnuHash = typename ELFT::GnuHash; \
+ using Elf_Nhdr = typename ELFT::Nhdr; \
+ using Elf_Note = typename ELFT::Note; \
+ using Elf_Note_Iterator = typename ELFT::NoteIterator; \
+ using Elf_CGProfile = typename ELFT::CGProfile; \
+ using Elf_Dyn_Range = typename ELFT::DynRange; \
+ using Elf_Shdr_Range = typename ELFT::ShdrRange; \
+ using Elf_Sym_Range = typename ELFT::SymRange; \
+ using Elf_Rel_Range = typename ELFT::RelRange; \
+ using Elf_Rela_Range = typename ELFT::RelaRange; \
+ using Elf_Relr_Range = typename ELFT::RelrRange; \
+ using Elf_Phdr_Range = typename ELFT::PhdrRange; \
#define LLVM_ELF_COMMA ,
#define LLVM_ELF_IMPORT_TYPES(E, W) \
@@ -248,7 +275,11 @@
Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
uint32_t Offset = this->st_name;
if (Offset >= StrTab.size())
- return errorCodeToError(object_error::parse_failed);
+ return createStringError(object_error::parse_failed,
+ "st_name (0x%" PRIx32
+ ") is past the end of the string table"
+ " of size 0x%zx",
+ Offset, StrTab.size());
return StringRef(StrTab.data() + Offset);
}
@@ -265,7 +296,6 @@
template <class ELFT>
struct Elf_Verdef_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
- using Elf_Verdaux = Elf_Verdaux_Impl<ELFT>;
Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT)
Elf_Half vd_flags; // Bitwise flags (VER_DEF_*)
Elf_Half vd_ndx; // Version index, used in .gnu.version entries
@@ -342,10 +372,8 @@
struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
using Elf_Dyn_Base<ELFT>::d_tag;
using Elf_Dyn_Base<ELFT>::d_un;
- using intX_t = typename std::conditional<ELFT::Is64Bits,
- int64_t, int32_t>::type;
- using uintX_t = typename std::conditional<ELFT::Is64Bits,
- uint64_t, uint32_t>::type;
+ using intX_t = std::conditional_t<ELFT::Is64Bits, int64_t, int32_t>;
+ using uintX_t = std::conditional_t<ELFT::Is64Bits, uint64_t, uint32_t>;
intX_t getTag() const { return d_tag; }
uintX_t getVal() const { return d_un.d_val; }
uintX_t getPtr() const { return d_un.d_ptr; }
@@ -537,6 +565,7 @@
}
ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const {
+ assert(DynamicSymCount >= symndx);
return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx);
}
};
@@ -613,6 +642,12 @@
Nhdr.n_descsz);
}
+ /// Get the note's descriptor as StringRef
+ StringRef getDescAsStringRef() const {
+ ArrayRef<uint8_t> Desc = getDesc();
+ return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
+ }
+
/// Get the note's type.
Elf_Word getType() const { return Nhdr.n_type; }
};
diff --git a/linux-x64/clang/include/llvm/Object/Error.h b/linux-x64/clang/include/llvm/Object/Error.h
index b7bbf06..0774418 100644
--- a/linux-x64/clang/include/llvm/Object/Error.h
+++ b/linux-x64/clang/include/llvm/Object/Error.h
@@ -13,11 +13,13 @@
#ifndef LLVM_OBJECT_ERROR_H
#define LLVM_OBJECT_ERROR_H
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/Error.h"
#include <system_error>
namespace llvm {
+
+class Twine;
+
namespace object {
class Binary;
@@ -49,7 +51,7 @@
/// Currently inherits from ECError for easy interoperability with
/// std::error_code, but this will be removed in the future.
class BinaryError : public ErrorInfo<BinaryError, ECError> {
- virtual void anchor();
+ void anchor() override;
public:
static char ID;
BinaryError() {
@@ -65,8 +67,8 @@
class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> {
public:
static char ID;
- GenericBinaryError(Twine Msg);
- GenericBinaryError(Twine Msg, object_error ECOverride);
+ GenericBinaryError(const Twine &Msg);
+ GenericBinaryError(const Twine &Msg, object_error ECOverride);
const std::string &getMessage() const { return Msg; }
void log(raw_ostream &OS) const override;
private:
diff --git a/linux-x64/clang/include/llvm/Object/IRObjectFile.h b/linux-x64/clang/include/llvm/Object/IRObjectFile.h
index 08b92f1..338b194 100644
--- a/linux-x64/clang/include/llvm/Object/IRObjectFile.h
+++ b/linux-x64/clang/include/llvm/Object/IRObjectFile.h
@@ -38,7 +38,7 @@
~IRObjectFile() override;
void moveSymbolNext(DataRefImpl &Symb) const override;
Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override;
- uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
diff --git a/linux-x64/clang/include/llvm/Object/IRSymtab.h b/linux-x64/clang/include/llvm/Object/IRSymtab.h
index 0bbfc93..4ee32fc 100644
--- a/linux-x64/clang/include/llvm/Object/IRSymtab.h
+++ b/linux-x64/clang/include/llvm/Object/IRSymtab.h
@@ -28,6 +28,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cassert>
diff --git a/linux-x64/clang/include/llvm/Object/MachO.h b/linux-x64/clang/include/llvm/Object/MachO.h
index ca9512f..7eb0173 100644
--- a/linux-x64/clang/include/llvm/Object/MachO.h
+++ b/linux-x64/clang/include/llvm/Object/MachO.h
@@ -65,7 +65,7 @@
/// ExportEntry encapsulates the current-state-of-the-walk used when doing a
/// non-recursive walk of the trie data structure. This allows you to iterate
/// across all exported symbols using:
-/// Error Err;
+/// Error Err = Error::success();
/// for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) {
/// }
/// if (Err) { report error ...
@@ -160,7 +160,7 @@
/// MachORebaseEntry encapsulates the current state in the decompression of
/// rebasing opcodes. This allows you to iterate through the compressed table of
/// rebasing using:
-/// Error Err;
+/// Error Err = Error::success();
/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
/// }
/// if (Err) { report error ...
@@ -204,7 +204,7 @@
/// MachOBindEntry encapsulates the current state in the decompression of
/// binding opcodes. This allows you to iterate through the compressed table of
/// bindings using:
-/// Error Err;
+/// Error Err = Error::success();
/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
/// }
/// if (Err) { report error ...
@@ -287,7 +287,7 @@
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
- uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
unsigned getSymbolSectionID(SymbolRef Symb) const;
unsigned getSectionID(SectionRef Sec) const;
@@ -297,6 +297,7 @@
uint64_t getSectionAddress(DataRefImpl Sec) const override;
uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
+ ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const;
Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
@@ -308,6 +309,7 @@
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
bool isSectionBitcode(DataRefImpl Sec) const override;
+ bool isDebugSection(StringRef SectionName) const override;
/// When dsymutil generates the companion file, it strips all unnecessary
/// sections (e.g. everything in the _TEXT segment) by omitting their body
@@ -566,7 +568,7 @@
static StringRef guessLibraryShortName(StringRef Name, bool &isFramework,
StringRef &Suffix);
- static Triple::ArchType getArch(uint32_t CPUType);
+ static Triple::ArchType getArch(uint32_t CPUType, uint32_t CPUSubType);
static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
const char **McpuDefault = nullptr,
const char **ArchFlag = nullptr);
@@ -613,6 +615,7 @@
case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
+ case MachO::PLATFORM_DRIVERKIT: return "driverkit";
default:
std::string ret;
raw_string_ostream ss(ret);
@@ -643,7 +646,7 @@
Version = utostr(major) + "." + utostr(minor);
if (update != 0)
Version += "." + utostr(update);
- return Version.str();
+ return std::string(std::string(Version.str()));
}
private:
diff --git a/linux-x64/clang/include/llvm/Object/MachOUniversal.h b/linux-x64/clang/include/llvm/Object/MachOUniversal.h
index 5bf724f..9bcacb5 100644
--- a/linux-x64/clang/include/llvm/Object/MachOUniversal.h
+++ b/linux-x64/clang/include/llvm/Object/MachOUniversal.h
@@ -22,8 +22,11 @@
namespace llvm {
class StringRef;
+class Module;
+class LLVMContext;
namespace object {
+class IRObjectFile;
class MachOUniversalBinary : public Binary {
virtual void anchor();
@@ -31,6 +34,8 @@
uint32_t Magic;
uint32_t NumberOfObjects;
public:
+ static constexpr uint32_t MaxSectionAlignment = 15; /* 2**15 or 0x8000 */
+
class ObjectForArch {
const MachOUniversalBinary *Parent;
/// Index of object in the universal binary.
@@ -64,13 +69,13 @@
else // Parent->getMagic() == MachO::FAT_MAGIC_64
return Header64.cpusubtype;
}
- uint32_t getOffset() const {
+ uint64_t getOffset() const {
if (Parent->getMagic() == MachO::FAT_MAGIC)
return Header.offset;
else // Parent->getMagic() == MachO::FAT_MAGIC_64
return Header64.offset;
}
- uint32_t getSize() const {
+ uint64_t getSize() const {
if (Parent->getMagic() == MachO::FAT_MAGIC)
return Header.size;
else // Parent->getMagic() == MachO::FAT_MAGIC_64
@@ -88,28 +93,19 @@
else // Parent->getMagic() == MachO::FAT_MAGIC_64
return Header64.reserved;
}
+ Triple getTriple() const {
+ return MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType());
+ }
std::string getArchFlagName() const {
const char *McpuDefault, *ArchFlag;
- if (Parent->getMagic() == MachO::FAT_MAGIC) {
- Triple T =
- MachOObjectFile::getArchTriple(Header.cputype, Header.cpusubtype,
- &McpuDefault, &ArchFlag);
- } else { // Parent->getMagic() == MachO::FAT_MAGIC_64
- Triple T =
- MachOObjectFile::getArchTriple(Header64.cputype,
- Header64.cpusubtype,
- &McpuDefault, &ArchFlag);
- }
- if (ArchFlag) {
- std::string ArchFlagName(ArchFlag);
- return ArchFlagName;
- } else {
- std::string ArchFlagName("");
- return ArchFlagName;
- }
+ MachOObjectFile::getArchTriple(getCPUType(), getCPUSubType(),
+ &McpuDefault, &ArchFlag);
+ return ArchFlag ? ArchFlag : std::string();
}
Expected<std::unique_ptr<MachOObjectFile>> getAsObjectFile() const;
+ Expected<std::unique_ptr<IRObjectFile>>
+ getAsIRObject(LLVMContext &Ctx) const;
Expected<std::unique_ptr<Archive>> getAsArchive() const;
};
@@ -157,8 +153,17 @@
return V->isMachOUniversalBinary();
}
- Expected<std::unique_ptr<MachOObjectFile>>
+ Expected<ObjectForArch>
getObjectForArch(StringRef ArchName) const;
+
+ Expected<std::unique_ptr<MachOObjectFile>>
+ getMachOObjectForArch(StringRef ArchName) const;
+
+ Expected<std::unique_ptr<IRObjectFile>>
+ getIRObjectForArch(StringRef ArchName, LLVMContext &Ctx) const;
+
+ Expected<std::unique_ptr<Archive>>
+ getArchiveForArch(StringRef ArchName) const;
};
}
diff --git a/linux-x64/clang/include/llvm/Object/MachOUniversalWriter.h b/linux-x64/clang/include/llvm/Object/MachOUniversalWriter.h
new file mode 100644
index 0000000..cdfedcf
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Object/MachOUniversalWriter.h
@@ -0,0 +1,102 @@
+//===- MachOUniversalWriter.h - MachO universal binary writer----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares the Slice class and writeUniversalBinary function for writing a
+// MachO universal binary file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_MACHOUNIVERSALWRITER_H
+#define LLVM_OBJECT_MACHOUNIVERSALWRITER_H
+
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/MachO.h"
+
+namespace llvm {
+class LLVMContext;
+
+namespace object {
+class IRObjectFile;
+
+class Slice {
+ const Binary *B;
+ uint32_t CPUType;
+ uint32_t CPUSubType;
+ std::string ArchName;
+
+ // P2Alignment field stores slice alignment values from universal
+ // binaries. This is also needed to order the slices so the total
+ // file size can be calculated before creating the output buffer.
+ uint32_t P2Alignment;
+
+ Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType,
+ std::string ArchName, uint32_t Align);
+
+public:
+ explicit Slice(const MachOObjectFile &O);
+
+ Slice(const MachOObjectFile &O, uint32_t Align);
+
+ /// This constructor takes pre-specified \param CPUType , \param CPUSubType ,
+ /// \param ArchName , \param Align instead of inferring them from the archive
+ /// members.
+ Slice(const Archive &A, uint32_t CPUType, uint32_t CPUSubType,
+ std::string ArchName, uint32_t Align);
+
+ static Expected<Slice> create(const Archive &A,
+ LLVMContext *LLVMCtx = nullptr);
+
+ static Expected<Slice> create(const IRObjectFile &IRO, uint32_t Align);
+
+ void setP2Alignment(uint32_t Align) { P2Alignment = Align; }
+
+ const Binary *getBinary() const { return B; }
+
+ uint32_t getCPUType() const { return CPUType; }
+
+ uint32_t getCPUSubType() const { return CPUSubType; }
+
+ uint32_t getP2Alignment() const { return P2Alignment; }
+
+ uint64_t getCPUID() const {
+ return static_cast<uint64_t>(CPUType) << 32 | CPUSubType;
+ }
+
+ std::string getArchString() const {
+ if (!ArchName.empty())
+ return ArchName;
+ return ("unknown(" + Twine(CPUType) + "," +
+ Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")")
+ .str();
+ }
+
+ friend bool operator<(const Slice &Lhs, const Slice &Rhs) {
+ if (Lhs.CPUType == Rhs.CPUType)
+ return Lhs.CPUSubType < Rhs.CPUSubType;
+ // force arm64-family to follow after all other slices for
+ // compatibility with cctools lipo
+ if (Lhs.CPUType == MachO::CPU_TYPE_ARM64)
+ return false;
+ if (Rhs.CPUType == MachO::CPU_TYPE_ARM64)
+ return true;
+ // Sort by alignment to minimize file size
+ return Lhs.P2Alignment < Rhs.P2Alignment;
+ }
+};
+
+Error writeUniversalBinary(ArrayRef<Slice> Slices, StringRef OutputFileName);
+
+Expected<std::unique_ptr<MemoryBuffer>>
+writeUniversalBinaryToBuffer(ArrayRef<Slice> Slices);
+
+} // end namespace object
+
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_MACHOUNIVERSALWRITER_H
diff --git a/linux-x64/clang/include/llvm/Object/Minidump.h b/linux-x64/clang/include/llvm/Object/Minidump.h
index 470008d..4429493 100644
--- a/linux-x64/clang/include/llvm/Object/Minidump.h
+++ b/linux-x64/clang/include/llvm/Object/Minidump.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/BinaryFormat/Minidump.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
@@ -80,16 +81,65 @@
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.
+ /// Returns the contents of the Exception stream. An error is returned if the
+ /// file does not contain this stream, or the stream is smaller than the size
+ /// of the ExceptionStream structure. The internal consistency of the stream
+ /// is not checked in any way.
+ Expected<const minidump::ExceptionStream &> getExceptionStream() const {
+ return getStream<minidump::ExceptionStream>(
+ minidump::StreamType::Exception);
+ }
+
+ /// Returns the list of descriptors embedded in the MemoryList stream. The
+ /// descriptors provide the content of interesting regions of memory at the
+ /// time the minidump was taken. 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);
}
+ class MemoryInfoIterator
+ : public iterator_facade_base<MemoryInfoIterator,
+ std::forward_iterator_tag,
+ minidump::MemoryInfo> {
+ public:
+ MemoryInfoIterator(ArrayRef<uint8_t> Storage, size_t Stride)
+ : Storage(Storage), Stride(Stride) {
+ assert(Storage.size() % Stride == 0);
+ }
+
+ bool operator==(const MemoryInfoIterator &R) const {
+ return Storage.size() == R.Storage.size();
+ }
+
+ const minidump::MemoryInfo &operator*() const {
+ assert(Storage.size() >= sizeof(minidump::MemoryInfo));
+ return *reinterpret_cast<const minidump::MemoryInfo *>(Storage.data());
+ }
+
+ MemoryInfoIterator &operator++() {
+ Storage = Storage.drop_front(Stride);
+ return *this;
+ }
+
+ private:
+ ArrayRef<uint8_t> Storage;
+ size_t Stride;
+ };
+
+ /// Returns the list of descriptors embedded in the MemoryInfoList stream. The
+ /// descriptors provide properties (e.g. permissions) of interesting regions
+ /// of memory at the time the minidump was taken. 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 MemoryInfoList entries themselves is not checked
+ /// in any way.
+ Expected<iterator_range<MemoryInfoIterator>> getMemoryInfoList() const;
+
private:
static Error createError(StringRef Str) {
return make_error<GenericBinaryError>(Str, object_error::parse_failed);
@@ -137,10 +187,10 @@
};
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());
+Expected<const T &> MinidumpFile::getStream(minidump::StreamType Type) const {
+ if (Optional<ArrayRef<uint8_t>> Stream = getRawStream(Type)) {
+ if (Stream->size() >= sizeof(T))
+ return *reinterpret_cast<const T *>(Stream->data());
return createEOFError();
}
return createError("No such stream");
@@ -153,10 +203,11 @@
// 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);
+ Expected<ArrayRef<uint8_t>> Slice =
+ getDataSlice(Data, Offset, sizeof(T) * Count);
+ if (!Slice)
+ return Slice.takeError();
+ return ArrayRef<T>(reinterpret_cast<const T *>(Slice->data()), Count);
}
} // end namespace object
diff --git a/linux-x64/clang/include/llvm/Object/ModuleSymbolTable.h b/linux-x64/clang/include/llvm/Object/ModuleSymbolTable.h
index 4c582fb..1134b98 100644
--- a/linux-x64/clang/include/llvm/Object/ModuleSymbolTable.h
+++ b/linux-x64/clang/include/llvm/Object/ModuleSymbolTable.h
@@ -28,6 +28,7 @@
namespace llvm {
class GlobalValue;
+class Module;
class ModuleSymbolTable {
public:
diff --git a/linux-x64/clang/include/llvm/Object/ObjectFile.h b/linux-x64/clang/include/llvm/Object/ObjectFile.h
index 483a348..27e40cb 100644
--- a/linux-x64/clang/include/llvm/Object/ObjectFile.h
+++ b/linux-x64/clang/include/llvm/Object/ObjectFile.h
@@ -18,13 +18,11 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.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>
@@ -34,6 +32,7 @@
namespace llvm {
class ARMAttributeParser;
+class SubtargetFeatures;
namespace object {
@@ -94,7 +93,7 @@
void moveNext();
- std::error_code getName(StringRef &Result) const;
+ Expected<StringRef> getName() const;
uint64_t getAddress() const;
uint64_t getIndex() const;
uint64_t getSize() const;
@@ -123,6 +122,9 @@
/// contains data (e.g. PROGBITS), but is not text.
bool isBerkeleyData() const;
+ /// Whether this section is a debug section.
+ bool isDebugSection(StringRef SectionName) const;
+
bool containsSymbol(SymbolRef S) const;
relocation_iterator relocation_begin() const;
@@ -130,18 +132,13 @@
iterator_range<relocation_iterator> relocations() const {
return make_range(relocation_begin(), relocation_end());
}
- section_iterator getRelocatedSection() const;
+ Expected<section_iterator> getRelocatedSection() const;
DataRefImpl getRawDataRefImpl() const;
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;
@@ -160,6 +157,8 @@
std::tie(RHS.SectionIndex, RHS.Address);
}
+raw_ostream &operator<<(raw_ostream &OS, const SectionedAddress &Addr);
+
/// This is a value type class that represents a single symbol in the list of
/// symbols in the object file.
class SymbolRef : public BasicSymbolRef {
@@ -188,7 +187,7 @@
/// Return the value of the symbol depending on the object this can be an
/// offset or a virtual address.
- uint64_t getValue() const;
+ Expected<uint64_t> getValue() const;
/// Get the alignment of this symbol as the actual value (not log 2).
uint32_t getAlignment() const;
@@ -275,9 +274,10 @@
virtual bool isSectionStripped(DataRefImpl Sec) const;
virtual bool isBerkeleyText(DataRefImpl Sec) const;
virtual bool isBerkeleyData(DataRefImpl Sec) const;
+ virtual bool isDebugSection(StringRef SectionName) const;
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
- virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
+ virtual Expected<section_iterator> getRelocatedSection(DataRefImpl Sec) const;
// Same as above for RelocationRef.
friend class RelocationRef;
@@ -288,14 +288,18 @@
virtual void getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const = 0;
- uint64_t getSymbolValue(DataRefImpl Symb) const;
+ Expected<uint64_t> getSymbolValue(DataRefImpl Symb) const;
public:
ObjectFile() = delete;
ObjectFile(const ObjectFile &other) = delete;
uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
- assert(getSymbolFlags(Symb) & SymbolRef::SF_Common);
+ Expected<uint32_t> SymbolFlagsOrErr = getSymbolFlags(Symb);
+ if (!SymbolFlagsOrErr)
+ // TODO: Actually report errors helpfully.
+ report_fatal_error(SymbolFlagsOrErr.takeError());
+ assert(*SymbolFlagsOrErr & SymbolRef::SF_Common);
return getCommonSymbolSizeImpl(Symb);
}
@@ -323,6 +327,7 @@
virtual StringRef getFileFormatName() const = 0;
virtual Triple::ArchType getArch() const = 0;
virtual SubtargetFeatures getFeatures() const = 0;
+ virtual Optional<StringRef> tryGetCPUName() const { return None; };
virtual void setARMSubArch(Triple &TheTriple) const { }
virtual Expected<uint64_t> getStartAddress() const {
return errorCodeToError(object_error::parse_failed);
@@ -345,7 +350,8 @@
createObjectFile(StringRef ObjectPath);
static Expected<std::unique_ptr<ObjectFile>>
- createObjectFile(MemoryBufferRef Object, llvm::file_magic Type);
+ createObjectFile(MemoryBufferRef Object, llvm::file_magic Type,
+ bool InitContent = true);
static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object) {
return createObjectFile(Object, llvm::file_magic::unknown);
@@ -362,7 +368,7 @@
createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
static Expected<std::unique_ptr<ObjectFile>>
- createELFObjectFile(MemoryBufferRef Object);
+ createELFObjectFile(MemoryBufferRef Object, bool InitContent = true);
static Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Object,
@@ -385,7 +391,7 @@
return getObject()->getSymbolAddress(getRawDataRefImpl());
}
-inline uint64_t SymbolRef::getValue() const {
+inline Expected<uint64_t> SymbolRef::getValue() const {
return getObject()->getSymbolValue(getRawDataRefImpl());
}
@@ -434,12 +440,8 @@
return OwningObject->moveSectionNext(SectionPimpl);
}
-inline std::error_code SectionRef::getName(StringRef &Result) const {
- Expected<StringRef> NameOrErr = OwningObject->getSectionName(SectionPimpl);
- if (!NameOrErr)
- return errorToErrorCode(NameOrErr.takeError());
- Result = *NameOrErr;
- return std::error_code();
+inline Expected<StringRef> SectionRef::getName() const {
+ return OwningObject->getSectionName(SectionPimpl);
}
inline uint64_t SectionRef::getAddress() const {
@@ -502,6 +504,10 @@
return OwningObject->isBerkeleyData(SectionPimpl);
}
+inline bool SectionRef::isDebugSection(StringRef SectionName) const {
+ return OwningObject->isDebugSection(SectionName);
+}
+
inline relocation_iterator SectionRef::relocation_begin() const {
return OwningObject->section_rel_begin(SectionPimpl);
}
@@ -510,7 +516,7 @@
return OwningObject->section_rel_end(SectionPimpl);
}
-inline section_iterator SectionRef::getRelocatedSection() const {
+inline Expected<section_iterator> SectionRef::getRelocatedSection() const {
return OwningObject->getRelocatedSection(SectionPimpl);
}
diff --git a/linux-x64/clang/include/llvm/Object/RelocationResolver.h b/linux-x64/clang/include/llvm/Object/RelocationResolver.h
index 1246dcc..46f74e9 100644
--- a/linux-x64/clang/include/llvm/Object/RelocationResolver.h
+++ b/linux-x64/clang/include/llvm/Object/RelocationResolver.h
@@ -31,11 +31,17 @@
namespace llvm {
namespace object {
-using RelocationResolver = uint64_t (*)(RelocationRef R, uint64_t S, uint64_t A);
+using SupportsRelocation = bool (*)(uint64_t);
+using RelocationResolver = uint64_t (*)(uint64_t Type, uint64_t Offset,
+ uint64_t S, uint64_t LocData,
+ int64_t Addend);
-std::pair<bool (*)(uint64_t), RelocationResolver>
+std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile &Obj);
+uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
+ uint64_t S, uint64_t LocData);
+
} // end namespace object
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Object/StackMapParser.h b/linux-x64/clang/include/llvm/Object/StackMapParser.h
index ed44efb..4ee6711 100644
--- a/linux-x64/clang/include/llvm/Object/StackMapParser.h
+++ b/linux-x64/clang/include/llvm/Object/StackMapParser.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h"
#include <cassert>
#include <cstddef>
@@ -19,7 +20,7 @@
namespace llvm {
-/// A parser for the latest stackmap format. At the moment, latest=V2.
+/// A parser for the latest stackmap format. At the moment, latest=V3.
template <support::endianness Endianness>
class StackMapParser {
public:
@@ -35,11 +36,13 @@
return tmp;
}
- bool operator==(const AccessorIterator &Other) {
+ bool operator==(const AccessorIterator &Other) const {
return A.P == Other.A.P;
}
- bool operator!=(const AccessorIterator &Other) { return !(*this == Other); }
+ bool operator!=(const AccessorIterator &Other) const {
+ return !(*this == Other);
+ }
AccessorT& operator*() { return A; }
AccessorT* operator->() { return &A; }
@@ -299,7 +302,7 @@
const uint8_t *P;
};
- /// Construct a parser for a version-2 stackmap. StackMap data will be read
+ /// Construct a parser for a version-3 stackmap. StackMap data will be read
/// from the given array.
StackMapParser(ArrayRef<uint8_t> StackMapSection)
: StackMapSection(StackMapSection) {
@@ -318,6 +321,23 @@
}
}
+ /// Validates the header of the specified stack map section.
+ static Error validateHeader(ArrayRef<uint8_t> StackMapSection) {
+ // See the comment for StackMaps::emitStackmapHeader().
+ if (StackMapSection.size() < 16)
+ return object::createError(
+ "the stack map section size (" + Twine(StackMapSection.size()) +
+ ") is less than the minimum possible size of its header (16)");
+
+ unsigned Version = StackMapSection[0];
+ if (Version != 3)
+ return object::createError(
+ "the version (" + Twine(Version) +
+ ") of the stack map section is unsupported, the "
+ "supported version is 3");
+ return Error::success();
+ }
+
using function_iterator = AccessorIterator<FunctionAccessor>;
using constant_iterator = AccessorIterator<ConstantAccessor>;
using record_iterator = AccessorIterator<RecordAccessor>;
diff --git a/linux-x64/clang/include/llvm/Object/SymbolicFile.h b/linux-x64/clang/include/llvm/Object/SymbolicFile.h
index 1398fa1..012f9f7 100644
--- a/linux-x64/clang/include/llvm/Object/SymbolicFile.h
+++ b/linux-x64/clang/include/llvm/Object/SymbolicFile.h
@@ -18,7 +18,6 @@
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cinttypes>
@@ -129,7 +128,7 @@
Error printName(raw_ostream &OS) const;
/// Get symbol flags (bitwise OR of SymbolRef::Flags)
- uint32_t getFlags() const;
+ Expected<uint32_t> getFlags() const;
DataRefImpl getRawDataRefImpl() const;
const SymbolicFile *getObject() const;
@@ -147,7 +146,7 @@
virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0;
- virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0;
+ virtual Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const = 0;
virtual basic_symbol_iterator symbol_begin() const = 0;
@@ -162,18 +161,18 @@
// construction aux.
static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type,
- LLVMContext *Context);
+ LLVMContext *Context, bool InitContent = true);
static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object) {
return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr);
}
- static Expected<OwningBinary<SymbolicFile>>
- createSymbolicFile(StringRef ObjectPath);
static bool classof(const Binary *v) {
return v->isSymbolic();
}
+
+ static bool isSymbolicFile(file_magic Type, const LLVMContext *Context);
};
inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP,
@@ -196,7 +195,7 @@
return OwningObject->printSymbolName(OS, SymbolPimpl);
}
-inline uint32_t BasicSymbolRef::getFlags() const {
+inline Expected<uint32_t> BasicSymbolRef::getFlags() const {
return OwningObject->getSymbolFlags(SymbolPimpl);
}
diff --git a/linux-x64/clang/include/llvm/Object/TapiFile.h b/linux-x64/clang/include/llvm/Object/TapiFile.h
new file mode 100644
index 0000000..ab99690
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Object/TapiFile.h
@@ -0,0 +1,63 @@
+//===- TapiFile.h - Text-based Dynamic Library Stub -------------*- 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 TapiFile interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_TAPI_FILE_H
+#define LLVM_OBJECT_TAPI_FILE_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TextAPI/MachO/InterfaceFile.h"
+
+namespace llvm {
+namespace object {
+
+class TapiFile : public SymbolicFile {
+public:
+ TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &interface,
+ MachO::Architecture Arch);
+ ~TapiFile() override;
+
+ void moveSymbolNext(DataRefImpl &DRI) const override;
+
+ Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override;
+
+ Expected<uint32_t> getSymbolFlags(DataRefImpl DRI) const override;
+
+ basic_symbol_iterator symbol_begin() const override;
+
+ basic_symbol_iterator symbol_end() const override;
+
+ static bool classof(const Binary *v) { return v->isTapiFile(); }
+
+ bool is64Bit() { return MachO::is64Bit(Arch); }
+
+private:
+ struct Symbol {
+ StringRef Prefix;
+ StringRef Name;
+ uint32_t Flags;
+
+ constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags)
+ : Prefix(Prefix), Name(Name), Flags(Flags) {}
+ };
+
+ std::vector<Symbol> Symbols;
+ MachO::Architecture Arch;
+};
+
+} // end namespace object.
+} // end namespace llvm.
+
+#endif // LLVM_OBJECT_TAPI_FILE_H
diff --git a/linux-x64/clang/include/llvm/Object/TapiUniversal.h b/linux-x64/clang/include/llvm/Object/TapiUniversal.h
new file mode 100644
index 0000000..0f494fc
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Object/TapiUniversal.h
@@ -0,0 +1,121 @@
+//===-- TapiUniversal.h - Text-based Dynamic Library Stub -------*- 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 TapiUniversal interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_TAPI_UNIVERSAL_H
+#define LLVM_OBJECT_TAPI_UNIVERSAL_H
+
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/TapiFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TextAPI/MachO/Architecture.h"
+#include "llvm/TextAPI/MachO/InterfaceFile.h"
+
+namespace llvm {
+namespace object {
+
+class TapiUniversal : public Binary {
+public:
+ class ObjectForArch {
+ const TapiUniversal *Parent;
+ int Index;
+
+ public:
+ ObjectForArch(const TapiUniversal *Parent, int Index)
+ : Parent(Parent), Index(Index) {}
+
+ ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
+
+ bool operator==(const ObjectForArch &Other) const {
+ return (Parent == Other.Parent) && (Index == Other.Index);
+ }
+
+ uint32_t getCPUType() const {
+ auto Result =
+ MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch);
+ return Result.first;
+ }
+
+ uint32_t getCPUSubType() const {
+ auto Result =
+ MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch);
+ return Result.second;
+ }
+
+ StringRef getArchFlagName() const {
+ return MachO::getArchitectureName(Parent->Libraries[Index].Arch);
+ }
+
+ std::string getInstallName() const {
+ return std::string(Parent->Libraries[Index].InstallName);
+ }
+
+ bool isTopLevelLib() const {
+ return Parent->ParsedFile->getInstallName() == getInstallName();
+ }
+
+ Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const;
+ };
+
+ class object_iterator {
+ ObjectForArch Obj;
+
+ public:
+ object_iterator(const ObjectForArch &Obj) : Obj(Obj) {}
+ const ObjectForArch *operator->() const { return &Obj; }
+ const ObjectForArch &operator*() const { return Obj; }
+
+ bool operator==(const object_iterator &Other) const {
+ return Obj == Other.Obj;
+ }
+ bool operator!=(const object_iterator &Other) const {
+ return !(*this == Other);
+ }
+
+ object_iterator &operator++() { // Preincrement
+ Obj = Obj.getNext();
+ return *this;
+ }
+ };
+
+ TapiUniversal(MemoryBufferRef Source, Error &Err);
+ static Expected<std::unique_ptr<TapiUniversal>>
+ create(MemoryBufferRef Source);
+ ~TapiUniversal() override;
+
+ object_iterator begin_objects() const { return ObjectForArch(this, 0); }
+ object_iterator end_objects() const {
+ return ObjectForArch(this, Libraries.size());
+ }
+
+ iterator_range<object_iterator> objects() const {
+ return make_range(begin_objects(), end_objects());
+ }
+
+ uint32_t getNumberOfObjects() const { return Libraries.size(); }
+
+ static bool classof(const Binary *v) { return v->isTapiUniversal(); }
+
+private:
+ struct Library {
+ StringRef InstallName;
+ MachO::Architecture Arch;
+ };
+
+ std::unique_ptr<MachO::InterfaceFile> ParsedFile;
+ std::vector<Library> Libraries;
+};
+
+} // end namespace object.
+} // end namespace llvm.
+
+#endif // LLVM_OBJECT_TAPI_UNIVERSAL_H
diff --git a/linux-x64/clang/include/llvm/Object/Wasm.h b/linux-x64/clang/include/llvm/Object/Wasm.h
index e130ea3..f7cd2e6 100644
--- a/linux-x64/clang/include/llvm/Object/Wasm.h
+++ b/linux-x64/clang/include/llvm/Object/Wasm.h
@@ -17,7 +17,6 @@
#define LLVM_OBJECT_WASM_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/Config/llvm-config.h"
@@ -37,13 +36,15 @@
public:
WasmSymbol(const wasm::WasmSymbolInfo &Info,
const wasm::WasmGlobalType *GlobalType,
+ const wasm::WasmTableType *TableType,
const wasm::WasmEventType *EventType,
const wasm::WasmSignature *Signature)
- : Info(Info), GlobalType(GlobalType), EventType(EventType),
- Signature(Signature) {}
+ : Info(Info), GlobalType(GlobalType), TableType(TableType),
+ EventType(EventType), Signature(Signature) {}
const wasm::WasmSymbolInfo &Info;
const wasm::WasmGlobalType *GlobalType;
+ const wasm::WasmTableType *TableType;
const wasm::WasmEventType *EventType;
const wasm::WasmSignature *Signature;
@@ -51,6 +52,8 @@
return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
}
+ bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; }
+
bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
bool isTypeGlobal() const {
@@ -106,6 +109,7 @@
uint32_t Type = 0; // Section type (See below)
uint32_t Offset = 0; // Offset with in the file
StringRef Name; // Section name (User-defined sections only)
+ uint32_t Comdat = UINT32_MAX; // From the "comdat info" section
ArrayRef<uint8_t> Content; // Section content
std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
};
@@ -147,14 +151,16 @@
ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
- ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
+ ArrayRef<wasm::WasmDebugName> debugNames() const { return DebugNames; }
uint32_t startFunction() const { return StartFunction; }
uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
+ uint32_t getNumImportedTables() const { return NumImportedTables; }
uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
uint32_t getNumImportedEvents() const { return NumImportedEvents; }
+ uint32_t getNumSections() const { return Sections.size(); }
void moveSymbolNext(DataRefImpl &Symb) const override;
- uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
@@ -168,6 +174,7 @@
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+ uint32_t getSymbolSectionId(SymbolRef Sym) const;
// Overrides from SectionRef.
void moveSectionNext(DataRefImpl &Sec) const override;
@@ -183,7 +190,6 @@
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
- bool isSectionBitcode(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
@@ -214,10 +220,13 @@
bool isValidFunctionIndex(uint32_t Index) const;
bool isDefinedFunctionIndex(uint32_t Index) const;
bool isValidGlobalIndex(uint32_t Index) const;
+ bool isValidTableIndex(uint32_t Index) const;
bool isDefinedGlobalIndex(uint32_t Index) const;
+ bool isDefinedTableIndex(uint32_t Index) const;
bool isValidEventIndex(uint32_t Index) const;
bool isDefinedEventIndex(uint32_t Index) const;
bool isValidFunctionSymbol(uint32_t Index) const;
+ bool isValidTableSymbol(uint32_t Index) const;
bool isValidGlobalSymbol(uint32_t Index) const;
bool isValidEventSymbol(uint32_t Index) const;
bool isValidDataSymbol(uint32_t Index) const;
@@ -229,6 +238,7 @@
const WasmSection &getWasmSection(DataRefImpl Ref) const;
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
+ uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const;
Error parseSection(WasmSection &Sec);
Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
@@ -239,8 +249,8 @@
Error parseFunctionSection(ReadContext &Ctx);
Error parseTableSection(ReadContext &Ctx);
Error parseMemorySection(ReadContext &Ctx);
- Error parseGlobalSection(ReadContext &Ctx);
Error parseEventSection(ReadContext &Ctx);
+ Error parseGlobalSection(ReadContext &Ctx);
Error parseExportSection(ReadContext &Ctx);
Error parseStartSection(ReadContext &Ctx);
Error parseElemSection(ReadContext &Ctx);
@@ -276,18 +286,22 @@
llvm::Optional<size_t> DataCount;
std::vector<wasm::WasmFunction> Functions;
std::vector<WasmSymbol> Symbols;
- std::vector<wasm::WasmFunctionName> DebugNames;
+ std::vector<wasm::WasmDebugName> DebugNames;
uint32_t StartFunction = -1;
bool HasLinkingSection = false;
bool HasDylinkSection = false;
+ bool SeenCodeSection = false;
+ bool HasMemory64 = false;
wasm::WasmLinkingData LinkingData;
uint32_t NumImportedGlobals = 0;
+ uint32_t NumImportedTables = 0;
uint32_t NumImportedFunctions = 0;
uint32_t NumImportedEvents = 0;
uint32_t CodeSection = 0;
uint32_t DataSection = 0;
- uint32_t GlobalSection = 0;
uint32_t EventSection = 0;
+ uint32_t GlobalSection = 0;
+ uint32_t TableSection = 0;
};
class WasmSectionOrderChecker {
@@ -303,8 +317,8 @@
WASM_SEC_ORDER_FUNCTION,
WASM_SEC_ORDER_TABLE,
WASM_SEC_ORDER_MEMORY,
- WASM_SEC_ORDER_GLOBAL,
WASM_SEC_ORDER_EVENT,
+ WASM_SEC_ORDER_GLOBAL,
WASM_SEC_ORDER_EXPORT,
WASM_SEC_ORDER_START,
WASM_SEC_ORDER_ELEM,
diff --git a/linux-x64/clang/include/llvm/Object/WasmTraits.h b/linux-x64/clang/include/llvm/Object/WasmTraits.h
deleted file mode 100644
index 3eee8e7..0000000
--- a/linux-x64/clang/include/llvm/Object/WasmTraits.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- 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 llvm::DenseMapInfo traits for the Wasm structures.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_OBJECT_WASMTRAITS_H
-#define LLVM_OBJECT_WASMTRAITS_H
-
-#include "llvm/ADT/Hashing.h"
-#include "llvm/BinaryFormat/Wasm.h"
-
-namespace llvm {
-
-template <typename T> struct DenseMapInfo;
-
-// Traits for using WasmSignature in a DenseMap.
-template <> struct DenseMapInfo<wasm::WasmSignature> {
- static wasm::WasmSignature getEmptyKey() {
- wasm::WasmSignature Sig;
- Sig.State = wasm::WasmSignature::Empty;
- return Sig;
- }
- static wasm::WasmSignature getTombstoneKey() {
- wasm::WasmSignature Sig;
- Sig.State = wasm::WasmSignature::Tombstone;
- return Sig;
- }
- static unsigned getHashValue(const wasm::WasmSignature &Sig) {
- uintptr_t H = hash_value(Sig.State);
- for (auto Ret : Sig.Returns)
- H = hash_combine(H, Ret);
- for (auto Param : Sig.Params)
- H = hash_combine(H, Param);
- return H;
- }
- static bool isEqual(const wasm::WasmSignature &LHS,
- const wasm::WasmSignature &RHS) {
- return LHS == RHS;
- }
-};
-
-// Traits for using WasmGlobalType in a DenseMap
-template <> struct DenseMapInfo<wasm::WasmGlobalType> {
- static wasm::WasmGlobalType getEmptyKey() {
- return wasm::WasmGlobalType{1, true};
- }
- static wasm::WasmGlobalType getTombstoneKey() {
- return wasm::WasmGlobalType{2, true};
- }
- static unsigned getHashValue(const wasm::WasmGlobalType &GlobalType) {
- return hash_combine(GlobalType.Type, GlobalType.Mutable);
- }
- static bool isEqual(const wasm::WasmGlobalType &LHS,
- const wasm::WasmGlobalType &RHS) {
- return LHS == RHS;
- }
-};
-
-} // end namespace llvm
-
-#endif // LLVM_OBJECT_WASMTRAITS_H
diff --git a/linux-x64/clang/include/llvm/Object/WindowsResource.h b/linux-x64/clang/include/llvm/Object/WindowsResource.h
index 356dcb0..a0d6584 100644
--- a/linux-x64/clang/include/llvm/Object/WindowsResource.h
+++ b/linux-x64/clang/include/llvm/Object/WindowsResource.h
@@ -31,6 +31,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/Binary.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
@@ -48,6 +49,7 @@
namespace object {
class WindowsResource;
+class ResourceSectionRef;
const size_t WIN_RES_MAGIC_SIZE = 16;
const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
@@ -151,8 +153,11 @@
class WindowsResourceParser {
public:
class TreeNode;
- WindowsResourceParser();
+ WindowsResourceParser(bool MinGW = false);
Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
+ Error parse(ResourceSectionRef &RSR, StringRef Filename,
+ std::vector<std::string> &Duplicates);
+ void cleanUpManifests(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; }
@@ -181,32 +186,38 @@
private:
friend class WindowsResourceParser;
- static uint32_t StringCount;
- static uint32_t DataCount;
-
- static std::unique_ptr<TreeNode> createStringNode();
+ // Index is the StringTable vector index for this node's name.
+ static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
static std::unique_ptr<TreeNode> createIDNode();
+ // DataIndex is the Data vector index that the data node points at.
static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
uint16_t MinorVersion,
uint32_t Characteristics,
- uint32_t Origin);
+ uint32_t Origin,
+ uint32_t DataIndex);
- explicit TreeNode(bool IsStringNode);
+ explicit TreeNode(uint32_t StringIndex);
TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
- uint32_t Characteristics, uint32_t Origin);
+ uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
- bool &IsNewTypeString, bool &IsNewNameString,
+ std::vector<std::vector<uint8_t>> &Data,
+ std::vector<std::vector<UTF16>> &StringTable,
TreeNode *&Result);
- TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString);
- TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString);
+ TreeNode &addTypeNode(const ResourceEntryRef &Entry,
+ std::vector<std::vector<UTF16>> &StringTable);
+ TreeNode &addNameNode(const ResourceEntryRef &Entry,
+ std::vector<std::vector<UTF16>> &StringTable);
bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
+ std::vector<std::vector<uint8_t>> &Data,
TreeNode *&Result);
bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin,
- TreeNode *&Result);
+ uint32_t DataIndex, TreeNode *&Result);
TreeNode &addIDChild(uint32_t ID);
- TreeNode &addNameChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
+ TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
+ std::vector<std::vector<UTF16>> &StringTable);
+ void shiftDataIndexDown(uint32_t Index);
bool IsDataNode = false;
uint32_t StringIndex;
@@ -222,12 +233,30 @@
uint32_t Origin;
};
+ struct StringOrID {
+ bool IsString;
+ ArrayRef<UTF16> String;
+ uint32_t ID;
+
+ StringOrID(uint32_t ID) : IsString(false), ID(ID) {}
+ StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {}
+ };
+
private:
+ Error addChildren(TreeNode &Node, ResourceSectionRef &RSR,
+ const coff_resource_dir_table &Table, uint32_t Origin,
+ std::vector<StringOrID> &Context,
+ std::vector<std::string> &Duplicates);
+ bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const;
+ bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const;
+
TreeNode Root;
std::vector<std::vector<uint8_t>> Data;
std::vector<std::vector<UTF16>> StringTable;
std::vector<std::string> InputFilenames;
+
+ bool MinGW;
};
Expected<std::unique_ptr<MemoryBuffer>>
diff --git a/linux-x64/clang/include/llvm/Object/XCOFFObjectFile.h b/linux-x64/clang/include/llvm/Object/XCOFFObjectFile.h
index cdee712..1ac00ed 100644
--- a/linux-x64/clang/include/llvm/Object/XCOFFObjectFile.h
+++ b/linux-x64/clang/include/llvm/Object/XCOFFObjectFile.h
@@ -13,23 +13,12 @@
#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/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.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>
+#include "llvm/Support/Endian.h"
+#include <limits>
namespace llvm {
namespace object {
@@ -62,8 +51,27 @@
support::ubig32_t NumberOfSymTableEntries;
};
-struct XCOFFSectionHeader32 {
- char Name[XCOFF::SectionNameSize];
+template <typename T> struct XCOFFSectionHeader {
+ // Least significant 3 bits are reserved.
+ static constexpr unsigned SectionFlagsReservedMask = 0x7;
+
+ // The low order 16 bits of section flags denotes the section type.
+ static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
+
+public:
+ StringRef getName() const;
+ uint16_t getSectionType() const;
+ bool isReservedSectionType() const;
+};
+
+// Explicit extern template declarations.
+struct XCOFFSectionHeader32;
+struct XCOFFSectionHeader64;
+extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
+extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
+
+struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
+ char Name[XCOFF::NameSize];
support::ubig32_t PhysicalAddress;
support::ubig32_t VirtualAddress;
support::ubig32_t SectionSize;
@@ -73,12 +81,10 @@
support::ubig16_t NumberOfRelocations;
support::ubig16_t NumberOfLineNumbers;
support::big32_t Flags;
-
- StringRef getName() const;
};
-struct XCOFFSectionHeader64 {
- char Name[XCOFF::SectionNameSize];
+struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
+ char Name[XCOFF::NameSize];
support::ubig64_t PhysicalAddress;
support::ubig64_t VirtualAddress;
support::ubig64_t SectionSize;
@@ -89,8 +95,6 @@
support::ubig32_t NumberOfLineNumbers;
support::big32_t Flags;
char Padding[4];
-
- StringRef getName() const;
};
struct XCOFFSymbolEntry {
@@ -106,7 +110,7 @@
} CFileLanguageIdAndTypeIdType;
union {
- char SymbolName[XCOFF::SymbolNameSize];
+ char SymbolName[XCOFF::NameSize];
NameInStrTblType NameInStrTbl;
};
@@ -127,6 +131,90 @@
const char *Data;
};
+struct XCOFFCsectAuxEnt32 {
+ static constexpr uint8_t SymbolTypeMask = 0x07;
+ static constexpr uint8_t SymbolAlignmentMask = 0xF8;
+ static constexpr size_t SymbolAlignmentBitOffset = 3;
+
+ support::ubig32_t
+ SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect
+ // length.
+ // If the symbol type is XTY_LD, the symbol table
+ // index of the containing csect.
+ // If the symbol type is XTY_ER, 0.
+ support::ubig32_t ParameterHashIndex;
+ support::ubig16_t TypeChkSectNum;
+ uint8_t SymbolAlignmentAndType;
+ XCOFF::StorageMappingClass StorageMappingClass;
+ support::ubig32_t StabInfoIndex;
+ support::ubig16_t StabSectNum;
+
+ uint16_t getAlignmentLog2() const {
+ return (SymbolAlignmentAndType & SymbolAlignmentMask) >>
+ SymbolAlignmentBitOffset;
+ }
+
+ uint8_t getSymbolType() const {
+ return SymbolAlignmentAndType & SymbolTypeMask;
+ }
+
+ bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
+};
+
+struct XCOFFFileAuxEnt {
+ typedef struct {
+ support::big32_t Magic; // Zero indicates name in string table.
+ support::ubig32_t Offset;
+ char NamePad[XCOFF::FileNamePadSize];
+ } NameInStrTblType;
+ union {
+ char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
+ NameInStrTblType NameInStrTbl;
+ };
+ XCOFF::CFileStringType Type;
+ uint8_t ReservedZeros[2];
+ uint8_t AuxType; // 64-bit XCOFF file only.
+};
+
+struct XCOFFSectAuxEntForStat {
+ support::ubig32_t SectionLength;
+ support::ubig16_t NumberOfRelocEnt;
+ support::ubig16_t NumberOfLineNum;
+ uint8_t Pad[10];
+};
+
+struct XCOFFRelocation32 {
+ // Masks for packing/unpacking the r_rsize field of relocations.
+
+ // The msb is used to indicate if the bits being relocated are signed or
+ // unsigned.
+ static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
+
+ // The 2nd msb is used to indicate that the binder has replaced/modified the
+ // original instruction.
+ static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
+
+ // The remaining bits specify the bit length of the relocatable reference
+ // minus one.
+ static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
+
+public:
+ support::ubig32_t VirtualAddress;
+ support::ubig32_t SymbolIndex;
+
+ // Packed field, see XR_* masks for details of packing.
+ uint8_t Info;
+
+ XCOFF::RelocationType Type;
+
+public:
+ bool isRelocationSigned() const;
+ bool isFixupIndicated() const;
+
+ // Returns the number of bits being relocated.
+ uint8_t getRelocatedLength() const;
+};
+
class XCOFFObjectFile : public ObjectFile {
private:
const void *FileHeader = nullptr;
@@ -146,18 +234,18 @@
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;
+ uintptr_t getEndOfSymbolTableAddress() 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;
+ // This function returns string table entry.
+ Expected<StringRef> getStringTableEntry(uint32_t Offset) 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
@@ -175,10 +263,15 @@
friend Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
+ void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
+
public:
+ static constexpr uint64_t InvalidRelocOffset =
+ std::numeric_limits<uint64_t>::max();
+
// Interface inherited from base classes.
void moveSymbolNext(DataRefImpl &Symb) const override;
- uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+ Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
@@ -207,6 +300,10 @@
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
+
+ /// \returns the relocation offset with the base address of the containing
+ /// section as zero, or InvalidRelocOffset on errors (such as a relocation
+ /// that does not refer to an address in any section).
uint64_t getRelocationOffset(DataRefImpl Rel) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
uint64_t getRelocationType(DataRefImpl Rel) const override;
@@ -253,15 +350,148 @@
uint32_t getLogicalNumberOfSymbolTableEntries32() const;
uint32_t getNumberOfSymbolTableEntries64() const;
+ uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
+ Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
+ Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
uint16_t getOptionalHeaderSize() const;
uint16_t getFlags() const;
// Section header table related interfaces.
ArrayRef<XCOFFSectionHeader32> sections32() const;
ArrayRef<XCOFFSectionHeader64> sections64() const;
+
+ int32_t getSectionFlags(DataRefImpl Sec) const;
+ Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
+
+ void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
+
+ // Relocation-related interfaces.
+ Expected<uint32_t>
+ getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const;
+
+ Expected<ArrayRef<XCOFFRelocation32>>
+ relocations(const XCOFFSectionHeader32 &) const;
+
+ static bool classof(const Binary *B) { return B->isXCOFF(); }
}; // XCOFFObjectFile
+class XCOFFSymbolRef {
+ const DataRefImpl SymEntDataRef;
+ const XCOFFObjectFile *const OwningObjectPtr;
+
+public:
+ XCOFFSymbolRef(DataRefImpl SymEntDataRef,
+ const XCOFFObjectFile *OwningObjectPtr)
+ : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){};
+
+ XCOFF::StorageClass getStorageClass() const;
+ uint8_t getNumberOfAuxEntries() const;
+ const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const;
+ uint16_t getType() const;
+ int16_t getSectionNumber() const;
+
+ bool hasCsectAuxEnt() const;
+ bool isFunction() const;
+};
+
+class TBVectorExt {
+ friend class XCOFFTracebackTable;
+
+ uint16_t Data;
+ uint32_t VecParmsInfo;
+
+ TBVectorExt(StringRef TBvectorStrRef);
+
+public:
+ uint8_t getNumberOfVRSaved() const;
+ bool isVRSavedOnStack() const;
+ bool hasVarArgs() const;
+ uint8_t getNumberOfVectorParms() const;
+ bool hasVMXInstruction() const;
+ SmallString<32> getVectorParmsInfoString() const;
+};
+
+/// This class provides methods to extract traceback table data from a buffer.
+/// The various accessors may reference the buffer provided via the constructor.
+
+class XCOFFTracebackTable {
+ const uint8_t *const TBPtr;
+ Optional<SmallString<32>> ParmsType;
+ Optional<uint32_t> TraceBackTableOffset;
+ Optional<uint32_t> HandlerMask;
+ Optional<uint32_t> NumOfCtlAnchors;
+ Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
+ Optional<StringRef> FunctionName;
+ Optional<uint8_t> AllocaRegister;
+ Optional<TBVectorExt> VecExt;
+ Optional<uint8_t> ExtensionTable;
+
+ XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
+public:
+ /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
+ /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
+ /// Error is returned.
+ ///
+ /// \param[in] Ptr
+ /// A pointer that points just past the initial 4 bytes of zeros at the
+ /// beginning of an XCOFF Traceback Table.
+ ///
+ /// \param[in, out] Size
+ /// A pointer that points to the length of the XCOFF Traceback Table.
+ /// If the XCOFF Traceback Table is not parsed successfully or there are
+ /// extra bytes that are not recognized, \a Size will be updated to be the
+ /// size up to the end of the last successfully parsed field of the table.
+ static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
+ uint64_t &Size);
+ uint8_t getVersion() const;
+ uint8_t getLanguageID() const;
+
+ bool isGlobalLinkage() const;
+ bool isOutOfLineEpilogOrPrologue() const;
+ bool hasTraceBackTableOffset() const;
+ bool isInternalProcedure() const;
+ bool hasControlledStorage() const;
+ bool isTOCless() const;
+ bool isFloatingPointPresent() const;
+ bool isFloatingPointOperationLogOrAbortEnabled() const;
+
+ bool isInterruptHandler() const;
+ bool isFuncNamePresent() const;
+ bool isAllocaUsed() const;
+ uint8_t getOnConditionDirective() const;
+ bool isCRSaved() const;
+ bool isLRSaved() const;
+
+ bool isBackChainStored() const;
+ bool isFixup() const;
+ uint8_t getNumOfFPRsSaved() const;
+
+ bool hasVectorInfo() const;
+ bool hasExtensionTable() const;
+ uint8_t getNumOfGPRsSaved() const;
+
+ uint8_t getNumberOfFixedParms() const;
+
+ uint8_t getNumberOfFPParms() const;
+ bool hasParmsOnStack() const;
+
+ const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
+ const Optional<uint32_t> &getTraceBackTableOffset() const {
+ return TraceBackTableOffset;
+ }
+ const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
+ const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
+ const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
+ return ControlledStorageInfoDisp;
+ }
+ const Optional<StringRef> &getFunctionName() const { return FunctionName; }
+ const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
+ const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
+ const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
+};
+
+bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
} // namespace object
} // namespace llvm