aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Object
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object')
-rw-r--r--include/llvm/Object/Archive.h7
-rw-r--r--include/llvm/Object/Binary.h16
-rw-r--r--include/llvm/Object/COFF.h36
-rw-r--r--include/llvm/Object/ELF.h112
-rw-r--r--include/llvm/Object/ELFObjectFile.h31
-rw-r--r--include/llvm/Object/ELFTypes.h6
-rw-r--r--include/llvm/Object/MachO.h1
-rw-r--r--include/llvm/Object/MachOUniversal.h14
-rw-r--r--include/llvm/Object/Minidump.h77
-rw-r--r--include/llvm/Object/ObjectFile.h21
-rw-r--r--include/llvm/Object/StackMapParser.h4
-rw-r--r--include/llvm/Object/TapiFile.h60
-rw-r--r--include/llvm/Object/TapiUniversal.h109
-rw-r--r--include/llvm/Object/WindowsResource.h55
-rw-r--r--include/llvm/Object/XCOFFObjectFile.h132
15 files changed, 539 insertions, 142 deletions
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index c40278a4f923..c3f36bdd9d1a 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -48,8 +48,7 @@ public:
/// 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 @@ public:
Expected<StringRef> getBuffer() const;
uint64_t getChildOffset() const;
+ uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }
Expected<MemoryBufferRef> getMemoryBufferRef() const;
@@ -221,6 +221,9 @@ public:
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/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 3c3e977baff4..aa5e718f5e9b 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -42,7 +42,9 @@ protected:
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,
@@ -101,16 +103,18 @@ public:
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 +141,8 @@ public:
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);
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index c53cbc46c747..b91ee5887fec 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -314,7 +314,10 @@ public:
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!");
@@ -969,11 +972,14 @@ public:
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;
+
+ 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; }
+
std::error_code getDataDirectory(uint32_t index,
const data_directory *&Res) const;
std::error_code getSection(int32_t index, const coff_section *&Res) const;
@@ -1201,16 +1207,34 @@ public:
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/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index cf8e4529bad9..28b00c8413de 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -64,6 +64,10 @@ std::string getSecIndexForError(const ELFFile<ELFT> *Obj,
return "[unknown index]";
}
+static inline Error defaultWarningHandler(const Twine &Msg) {
+ return createError(Msg);
+}
+
template <class ELFT>
class ELFFile {
public:
@@ -95,6 +99,13 @@ public:
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(); }
size_t getBufSize() const { return Buf.size(); }
@@ -114,7 +125,9 @@ public:
template <typename T>
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;
@@ -137,15 +150,16 @@ public:
static Expected<ELFFile> create(StringRef Object);
+ bool isLE() const {
+ return getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
+ }
+
bool isMipsELF64() const {
return getHeader()->e_machine == ELF::EM_MIPS &&
getHeader()->getFileClass() == ELF::ELFCLASS64;
}
- bool isMips64EL() const {
- return isMipsELF64() &&
- getHeader()->getDataEncoding() == ELF::ELFDATA2LSB;
- }
+ bool isMips64EL() const { return isMipsELF64() && isLE(); }
Expected<Elf_Shdr_Range> sections() const;
@@ -261,7 +275,9 @@ public:
return make_range(notes_begin(Shdr, Err), notes_end());
}
- Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const;
+ Expected<StringRef> getSectionStringTable(
+ Elf_Shdr_Range Sections,
+ WarningHandler WarnHandler = &defaultWarningHandler) 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,
@@ -271,12 +287,13 @@ public:
Elf_Sym_Range Symtab,
ArrayRef<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,
+ WarningHandler WarnHandler = &defaultWarningHandler) const;
Expected<StringRef> getSectionName(const Elf_Shdr *Section,
StringRef DotShstrtab) const;
template <typename T>
@@ -459,18 +476,18 @@ ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,
template <class ELFT>
Expected<StringRef>
-ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const {
+ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
+ WarningHandler WarnHandler) const {
uint32_t Index = getHeader()->e_shstrndx;
if (Index == ELF::SHN_XINDEX)
Index = Sections[0].sh_link;
if (!Index) // no section string table.
return "";
- // TODO: Test a case when the sh_link of the section with index 0 is broken.
if (Index >= Sections.size())
return createError("section header string table index " + Twine(Index) +
" does not exist");
- return getStringTable(&Sections[Index]);
+ return getStringTable(&Sections[Index], WarnHandler);
}
template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
@@ -495,7 +512,8 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
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,15 +531,22 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
NumSections = First->sh_size;
if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
- // TODO: this error is untested.
- return createError("section table goes past the end of file");
+ 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);
}
@@ -540,8 +565,9 @@ template <typename T>
Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section,
uint32_t Entry) const {
if (sizeof(T) != Section->sh_entsize)
- // TODO: this error is untested.
- return createError("invalid sh_entsize");
+ return createError("section " + getSecIndexForError(this, Section) +
+ " has invalid sh_entsize: expected " + Twine(sizeof(T)) +
+ ", but got " + Twine(Section->sh_entsize));
size_t Pos = Section->sh_offset + Entry * sizeof(T);
if (Pos + sizeof(T) > Buf.size())
return createError("unable to access section " +
@@ -561,42 +587,26 @@ ELFFile<ELFT>::getSection(uint32_t Index) const {
}
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 {
+ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section,
+ WarningHandler WarnHandler) 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));
+ 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 " +
+ return createError("SHT_STRTAB string table section " +
getSecIndexForError(this, Section) +
" is non-null terminated");
return StringRef(Data.begin(), Data.size());
@@ -626,8 +636,11 @@ ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section,
const Elf_Shdr &SymTable = **SymTableOrErr;
if (SymTable.sh_type != ELF::SHT_SYMTAB &&
SymTable.sh_type != ELF::SHT_DYNSYM)
- // TODO: this error is untested.
- return createError("invalid sh_type");
+ return createError("SHT_SYMTAB_SHNDX section is linked with " +
+ object::getELFSectionTypeName(getHeader()->e_machine,
+ SymTable.sh_type) +
+ " section (expected SHT_SYMTAB/SHT_DYNSYM)");
+
if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
return createError("SHT_SYMTAB_SHNDX section has sh_size (" +
Twine(SymTable.sh_size) +
@@ -662,11 +675,12 @@ ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec,
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);
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 86c015efd704..424289a9ccaa 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.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;
@@ -239,6 +239,10 @@ public:
using Elf_Rela = typename ELFT::Rela;
using Elf_Dyn = typename ELFT::Dyn;
+ SectionRef toSectionRef(const Elf_Shdr *Sec) const {
+ return SectionRef(toDRI(Sec), this);
+ }
+
private:
ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF,
const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec,
@@ -284,7 +288,8 @@ protected:
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;
@@ -461,13 +466,15 @@ Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
if (!SymStrTabOrErr)
return SymStrTabOrErr.takeError();
Expected<StringRef> Name = ESym->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 (ESym->getType() == ELF::STT_SECTION) {
+ if (Expected<section_iterator> SecOrErr = getSymbolSection(Sym)) {
+ consumeError(Name.takeError());
+ return (*SecOrErr)->getName();
+ }
}
return Name;
}
@@ -835,7 +842,7 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
}
template <class ELFT>
-section_iterator
+Expected<section_iterator>
ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
if (EF.getHeader()->e_type != ELF::ET_REL)
return section_end();
@@ -845,10 +852,10 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
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
diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h
index 5552208b1f8a..7d1ade4d5437 100644
--- a/include/llvm/Object/ELFTypes.h
+++ b/include/llvm/Object/ELFTypes.h
@@ -248,7 +248,11 @@ template <class ELFT>
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);
}
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index ca9512f21706..76be8049a7d4 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -297,6 +297,7 @@ public:
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;
diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h
index 5bf724f2c8b2..eb45aff4480b 100644
--- a/include/llvm/Object/MachOUniversal.h
+++ b/include/llvm/Object/MachOUniversal.h
@@ -31,6 +31,8 @@ class MachOUniversalBinary : public Binary {
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 +66,13 @@ public:
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
@@ -157,8 +159,14 @@ public:
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<Archive>>
+ getArchiveForArch(StringRef ArchName) const;
};
}
diff --git a/include/llvm/Object/Minidump.h b/include/llvm/Object/Minidump.h
index 470008d552e7..4429493aff45 100644
--- a/include/llvm/Object/Minidump.h
+++ b/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 @@ public:
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 @@ private:
};
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 @@ Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data,
// 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/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 483a3486bd72..adc9dbc189af 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -94,7 +94,7 @@ public:
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;
@@ -130,18 +130,13 @@ public:
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;
@@ -277,7 +272,7 @@ protected:
virtual bool isBerkeleyData(DataRefImpl Sec) 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;
@@ -434,12 +429,8 @@ inline void SectionRef::moveNext() {
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 {
@@ -510,7 +501,7 @@ inline relocation_iterator SectionRef::relocation_end() const {
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/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h
index ed44efbf80b9..b408f4041034 100644
--- a/include/llvm/Object/StackMapParser.h
+++ b/include/llvm/Object/StackMapParser.h
@@ -19,7 +19,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:
@@ -299,7 +299,7 @@ public:
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) {
diff --git a/include/llvm/Object/TapiFile.h b/include/llvm/Object/TapiFile.h
new file mode 100644
index 000000000000..bc2e04e1cc96
--- /dev/null
+++ b/include/llvm/Object/TapiFile.h
@@ -0,0 +1,60 @@
+//===- 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;
+
+ 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(); }
+
+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;
+};
+
+} // end namespace object.
+} // end namespace llvm.
+
+#endif // LLVM_OBJECT_TAPI_FILE_H
diff --git a/include/llvm/Object/TapiUniversal.h b/include/llvm/Object/TapiUniversal.h
new file mode 100644
index 000000000000..4931183852ad
--- /dev/null
+++ b/include/llvm/Object/TapiUniversal.h
@@ -0,0 +1,109 @@
+//===-- 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->Architectures[Index]);
+ return Result.first;
+ }
+
+ uint32_t getCPUSubType() const {
+ auto Result =
+ MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]);
+ return Result.second;
+ }
+
+ std::string getArchFlagName() const {
+ return MachO::getArchitectureName(Parent->Architectures[Index]);
+ }
+
+ 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, Architectures.size());
+ }
+
+ iterator_range<object_iterator> objects() const {
+ return make_range(begin_objects(), end_objects());
+ }
+
+ uint32_t getNumberOfObjects() const { return Architectures.size(); }
+
+ // Cast methods.
+ static bool classof(const Binary *v) { return v->isTapiUniversal(); }
+
+private:
+ std::unique_ptr<MachO::InterfaceFile> ParsedFile;
+ std::vector<MachO::Architecture> Architectures;
+};
+
+} // end namespace object.
+} // end namespace llvm.
+
+#endif // LLVM_OBJECT_TAPI_UNIVERSAL_H
diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h
index 356dcb03abba..a0d658491cb9 100644
--- a/include/llvm/Object/WindowsResource.h
+++ b/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 @@ class ScopedPrinter;
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 @@ private:
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 @@ public:
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 @@ public:
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/include/llvm/Object/XCOFFObjectFile.h b/include/llvm/Object/XCOFFObjectFile.h
index cdee7129a2ab..84073ce5f6cf 100644
--- a/include/llvm/Object/XCOFFObjectFile.h
+++ b/include/llvm/Object/XCOFFObjectFile.h
@@ -13,23 +13,8 @@
#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H
#define LLVM_OBJECT_XCOFFOBJECTFILE_H
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/BinaryFormat/Magic.h"
#include "llvm/BinaryFormat/XCOFF.h"
-#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Object/Binary.h"
-#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
-#include "llvm/Object/SymbolicFile.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <cassert>
-#include <cstdint>
-#include <memory>
-#include <system_error>
namespace llvm {
namespace object {
@@ -63,7 +48,7 @@ struct XCOFFFileHeader64 {
};
struct XCOFFSectionHeader32 {
- char Name[XCOFF::SectionNameSize];
+ char Name[XCOFF::NameSize];
support::ubig32_t PhysicalAddress;
support::ubig32_t VirtualAddress;
support::ubig32_t SectionSize;
@@ -78,7 +63,7 @@ struct XCOFFSectionHeader32 {
};
struct XCOFFSectionHeader64 {
- char Name[XCOFF::SectionNameSize];
+ char Name[XCOFF::NameSize];
support::ubig64_t PhysicalAddress;
support::ubig64_t VirtualAddress;
support::ubig64_t SectionSize;
@@ -106,7 +91,7 @@ struct XCOFFSymbolEntry {
} CFileLanguageIdAndTypeIdType;
union {
- char SymbolName[XCOFF::SymbolNameSize];
+ char SymbolName[XCOFF::NameSize];
NameInStrTblType NameInStrTbl;
};
@@ -127,6 +112,75 @@ struct XCOFFStringTable {
const char *Data;
};
+struct XCOFFCsectAuxEnt32 {
+ 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;
+};
+
+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 +200,18 @@ private:
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,6 +229,8 @@ private:
friend Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
+ void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
+
public:
// Interface inherited from base classes.
void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -253,15 +309,49 @@ public:
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;
}; // 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;
+};
+
} // namespace object
} // namespace llvm