aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-readobj
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-readobj')
-rw-r--r--tools/llvm-readobj/ARMEHABIPrinter.h19
-rw-r--r--tools/llvm-readobj/ARMWinEHPrinter.cpp9
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp362
-rw-r--r--tools/llvm-readobj/DwarfCFIEHPrinter.h54
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp1648
-rw-r--r--tools/llvm-readobj/MachODumper.cpp61
-rw-r--r--tools/llvm-readobj/ObjDumper.cpp32
-rw-r--r--tools/llvm-readobj/ObjDumper.h11
-rw-r--r--tools/llvm-readobj/WasmDumper.cpp7
-rw-r--r--tools/llvm-readobj/Win64EHDumper.cpp13
-rw-r--r--tools/llvm-readobj/WindowsResourceDumper.cpp8
-rw-r--r--tools/llvm-readobj/XCOFFDumper.cpp402
-rw-r--r--tools/llvm-readobj/llvm-readobj.cpp148
-rw-r--r--tools/llvm-readobj/llvm-readobj.h25
14 files changed, 2048 insertions, 751 deletions
diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h
index 11f9d6166a59..2c0912038c31 100644
--- a/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -329,6 +329,7 @@ class PrinterContext {
ScopedPrinter &SW;
const object::ELFFile<ET> *ELF;
+ StringRef FileName;
const Elf_Shdr *Symtab;
ArrayRef<Elf_Word> ShndxTable;
@@ -352,8 +353,8 @@ class PrinterContext {
public:
PrinterContext(ScopedPrinter &SW, const object::ELFFile<ET> *ELF,
- const Elf_Shdr *Symtab)
- : SW(SW), ELF(ELF), Symtab(Symtab) {}
+ StringRef FileName, const Elf_Shdr *Symtab)
+ : SW(SW), ELF(ELF), FileName(FileName), Symtab(Symtab) {}
void PrintUnwindInformation() const;
};
@@ -369,10 +370,10 @@ PrinterContext<ET>::FunctionAtAddress(unsigned Section,
return readobj_error::unknown_symbol;
auto StrTableOrErr = ELF->getStringTableForSymtab(*Symtab);
if (!StrTableOrErr)
- error(StrTableOrErr.takeError());
+ reportError(StrTableOrErr.takeError(), FileName);
StringRef StrTable = *StrTableOrErr;
- for (const Elf_Sym &Sym : unwrapOrError(ELF->symbols(Symtab)))
+ for (const Elf_Sym &Sym : unwrapOrError(FileName, ELF->symbols(Symtab)))
if (Sym.st_shndx == Section && Sym.st_value == Address &&
Sym.getType() == ELF::STT_FUNC) {
auto NameOrErr = Sym.getName(StrTable);
@@ -398,16 +399,16 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
/// handling table. Use this symbol to recover the actual exception handling
/// table.
- for (const Elf_Shdr &Sec : unwrapOrError(ELF->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(FileName, ELF->sections())) {
if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex)
continue;
auto SymTabOrErr = ELF->getSection(Sec.sh_link);
if (!SymTabOrErr)
- error(SymTabOrErr.takeError());
+ reportError(SymTabOrErr.takeError(), FileName);
const Elf_Shdr *SymTab = *SymTabOrErr;
- for (const Elf_Rel &R : unwrapOrError(ELF->rels(&Sec))) {
+ for (const Elf_Rel &R : unwrapOrError(FileName, ELF->rels(&Sec))) {
if (R.r_offset != static_cast<unsigned>(IndexTableOffset))
continue;
@@ -417,7 +418,7 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
RelA.r_addend = 0;
const Elf_Sym *Symbol =
- unwrapOrError(ELF->getRelocationSymbol(&RelA, SymTab));
+ unwrapOrError(FileName, ELF->getRelocationSymbol(&RelA, SymTab));
auto Ret = ELF->getSection(Symbol, SymTab, ShndxTable);
if (!Ret)
@@ -570,7 +571,7 @@ void PrinterContext<ET>::PrintUnwindInformation() const {
DictScope UI(SW, "UnwindInformation");
int SectionIndex = 0;
- for (const Elf_Shdr &Sec : unwrapOrError(ELF->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(FileName, ELF->sections())) {
if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
DictScope UIT(SW, "UnwindIndexTable");
diff --git a/tools/llvm-readobj/ARMWinEHPrinter.cpp b/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 4de14e2e78d5..3e026f58871b 100644
--- a/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -842,8 +842,10 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) -
(XData.E() ? 0 : XData.EpilogueCount() * 4) -
- (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength)
+ (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) {
+ SW.flush();
report_fatal_error("Malformed unwind data");
+ }
if (XData.E()) {
ArrayRef<uint8_t> UC = XData.UnwindByteCode();
@@ -1039,10 +1041,7 @@ bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
}
FunctionAddress = *FunctionAddressOrErr;
} else {
- const pe32_header *PEHeader;
- if (COFF.getPE32Header(PEHeader))
- return false;
- FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
+ FunctionAddress = COFF.getPE32Header()->ImageBase + RF.BeginAddress;
}
SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 4c2e39dfa3cc..9b2c6adb9d93 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -60,6 +60,10 @@ using namespace llvm::codeview;
using namespace llvm::support;
using namespace llvm::Win64EH;
+static inline Error createError(const Twine &Err) {
+ return make_error<StringError>(Err, object_error::parse_failed);
+}
+
namespace {
struct LoadConfigTables {
@@ -167,9 +171,6 @@ private:
void printDelayImportedSymbols(
const DelayImportDirectoryEntryRef &I,
iterator_range<imported_symbol_iterator> Range);
- ErrorOr<const coff_resource_dir_entry &>
- getResourceDirectoryTableEntry(const coff_resource_dir_table &Table,
- uint32_t Index);
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
@@ -627,14 +628,10 @@ void COFFDumper::printFileHeaders() {
// Print PE header. This header does not exist if this is an object file and
// not an executable.
- const pe32_header *PEHeader = nullptr;
- error(Obj->getPE32Header(PEHeader));
- if (PEHeader)
+ if (const pe32_header *PEHeader = Obj->getPE32Header())
printPEHeader<pe32_header>(PEHeader);
- const pe32plus_header *PEPlusHeader = nullptr;
- error(Obj->getPE32PlusHeader(PEPlusHeader));
- if (PEPlusHeader)
+ if (const pe32plus_header *PEPlusHeader = Obj->getPE32PlusHeader())
printPEHeader<pe32plus_header>(PEPlusHeader);
if (const dos_header *DH = Obj->getDOSHeader())
@@ -728,7 +725,9 @@ void COFFDumper::printCOFFDebugDirectory() {
if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) {
const codeview::DebugInfo *DebugInfo;
StringRef PDBFileName;
- error(Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName));
+ if (std::error_code EC = Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+
DictScope PDBScope(W, "PDBInfo");
W.printHex("PDBSignature", DebugInfo->Signature.CVSignature);
if (DebugInfo->Signature.CVSignature == OMF::Signature::PDB70) {
@@ -740,8 +739,9 @@ void COFFDumper::printCOFFDebugDirectory() {
// FIXME: Type values of 12 and 13 are commonly observed but are not in
// the documented type enum. Figure out what they mean.
ArrayRef<uint8_t> RawData;
- error(
- Obj->getRvaAndSizeAsBytes(D.AddressOfRawData, D.SizeOfData, RawData));
+ if (std::error_code EC = Obj->getRvaAndSizeAsBytes(D.AddressOfRawData,
+ D.SizeOfData, RawData))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printBinaryBlock("RawData", RawData);
}
}
@@ -750,8 +750,11 @@ void COFFDumper::printCOFFDebugDirectory() {
void COFFDumper::printRVATable(uint64_t TableVA, uint64_t Count,
uint64_t EntrySize, PrintExtraCB PrintExtra) {
uintptr_t TableStart, TableEnd;
- error(Obj->getVaPtr(TableVA, TableStart));
- error(Obj->getVaPtr(TableVA + Count * EntrySize - 1, TableEnd));
+ if (std::error_code EC = Obj->getVaPtr(TableVA, TableStart))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+ if (std::error_code EC =
+ Obj->getVaPtr(TableVA + Count * EntrySize - 1, TableEnd))
+ reportError(errorCodeToError(EC), Obj->getFileName());
TableEnd++;
for (uintptr_t I = TableStart; I < TableEnd; I += EntrySize) {
uint32_t RVA = *reinterpret_cast<const ulittle32_t *>(I);
@@ -887,16 +890,14 @@ void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
void COFFDumper::printCodeViewDebugInfo() {
// Print types first to build CVUDTNames, then print symbols.
for (const SectionRef &S : Obj->sections()) {
- StringRef SectionName;
- error(S.getName(SectionName));
+ StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());
// .debug$T is a standard CodeView type section, while .debug$P is the same
// format but used for MSVC precompiled header object files.
if (SectionName == ".debug$T" || SectionName == ".debug$P")
printCodeViewTypeSection(SectionName, S);
}
for (const SectionRef &S : Obj->sections()) {
- StringRef SectionName;
- error(S.getName(SectionName));
+ StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());
if (SectionName == ".debug$S")
printCodeViewSymbolSection(SectionName, S);
}
@@ -908,32 +909,40 @@ void COFFDumper::initializeFileAndStringTables(BinaryStreamReader &Reader) {
// The section consists of a number of subsection in the following format:
// |SubSectionType|SubSectionSize|Contents...|
uint32_t SubType, SubSectionSize;
- error(Reader.readInteger(SubType));
- error(Reader.readInteger(SubSectionSize));
+
+ if (Error E = Reader.readInteger(SubType))
+ reportError(std::move(E), Obj->getFileName());
+ if (Error E = Reader.readInteger(SubSectionSize))
+ reportError(std::move(E), Obj->getFileName());
StringRef Contents;
- error(Reader.readFixedString(Contents, SubSectionSize));
+ if (Error E = Reader.readFixedString(Contents, SubSectionSize))
+ reportError(std::move(E), Obj->getFileName());
BinaryStreamRef ST(Contents, support::little);
switch (DebugSubsectionKind(SubType)) {
case DebugSubsectionKind::FileChecksums:
- error(CVFileChecksumTable.initialize(ST));
+ if (Error E = CVFileChecksumTable.initialize(ST))
+ reportError(std::move(E), Obj->getFileName());
break;
case DebugSubsectionKind::StringTable:
- error(CVStringTable.initialize(ST));
+ if (Error E = CVStringTable.initialize(ST))
+ reportError(std::move(E), Obj->getFileName());
break;
default:
break;
}
uint32_t PaddedSize = alignTo(SubSectionSize, 4);
- error(Reader.skip(PaddedSize - SubSectionSize));
+ if (Error E = Reader.skip(PaddedSize - SubSectionSize))
+ reportError(std::move(E), Obj->getFileName());
}
}
void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
const SectionRef &Section) {
- StringRef SectionContents = unwrapOrError(Section.getContents());
+ StringRef SectionContents =
+ unwrapOrError(Obj->getFileName(), Section.getContents());
StringRef Data = SectionContents;
SmallVector<StringRef, 10> FunctionNames;
@@ -944,10 +953,13 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
W.printNumber("Section", SectionName, Obj->getSectionID(Section));
uint32_t Magic;
- error(consume(Data, Magic));
+ if (Error E = consume(Data, Magic))
+ reportError(std::move(E), Obj->getFileName());
+
W.printHex("Magic", Magic);
if (Magic != COFF::DEBUG_SECTION_MAGIC)
- return error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
BinaryStreamReader FSReader(Data, support::little);
initializeFileAndStringTables(FSReader);
@@ -957,8 +969,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
// The section consists of a number of subsection in the following format:
// |SubSectionType|SubSectionSize|Contents...|
uint32_t SubType, SubSectionSize;
- error(consume(Data, SubType));
- error(consume(Data, SubSectionSize));
+ if (Error E = consume(Data, SubType))
+ reportError(std::move(E), Obj->getFileName());
+ if (Error E = consume(Data, SubSectionSize))
+ reportError(std::move(E), Obj->getFileName());
ListScope S(W, "Subsection");
// Dump the subsection as normal even if the ignore bit is set.
@@ -971,7 +985,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
// Get the contents of the subsection.
if (SubSectionSize > Data.size())
- return error(object_error::parse_failed);
+ return reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
StringRef Contents = Data.substr(0, SubSectionSize);
// Add SubSectionSize to the current offset and align that offset to find
@@ -980,7 +995,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
size_t NextOffset = SectionOffset + SubSectionSize;
NextOffset = alignTo(NextOffset, 4);
if (NextOffset > SectionContents.size())
- return error(object_error::parse_failed);
+ return reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
Data = SectionContents.drop_front(NextOffset);
// Optionally print the subsection bytes in case our parsing gets confused
@@ -1010,17 +1026,21 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
if (SubSectionSize < 12) {
// There should be at least three words to store two function
// relocations and size of the code.
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
return;
}
StringRef LinkageName;
- error(resolveSymbolName(Obj->getCOFFSection(Section), SectionOffset,
- LinkageName));
+ if (std::error_code EC = resolveSymbolName(Obj->getCOFFSection(Section),
+ SectionOffset, LinkageName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+
W.printString("LinkageName", LinkageName);
if (FunctionLineTables.count(LinkageName) != 0) {
// Saw debug info for this function already?
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
return;
}
@@ -1033,17 +1053,21 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
BinaryStreamReader SR(Contents, llvm::support::little);
DebugFrameDataSubsectionRef FrameData;
- error(FrameData.initialize(SR));
+ if (Error E = FrameData.initialize(SR))
+ reportError(std::move(E), Obj->getFileName());
StringRef LinkageName;
- error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
- FrameData.getRelocPtr(), LinkageName));
+ if (std::error_code EC =
+ resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
+ FrameData.getRelocPtr(), LinkageName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printString("LinkageName", LinkageName);
// To find the active frame description, search this array for the
// smallest PC range that includes the current PC.
for (const auto &FD : FrameData) {
- StringRef FrameFunc = error(CVStringTable.getString(FD.FrameFunc));
+ StringRef FrameFunc = unwrapOrError(
+ Obj->getFileName(), CVStringTable.getString(FD.FrameFunc));
DictScope S(W, "FrameData");
W.printHex("RvaStart", FD.RvaStart);
@@ -1094,7 +1118,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
BinaryStreamReader Reader(FunctionLineTables[Name], support::little);
DebugLinesSubsectionRef LineInfo;
- error(LineInfo.initialize(Reader));
+ if (Error E = LineInfo.initialize(Reader))
+ reportError(std::move(E), Obj->getFileName());
W.printHex("Flags", LineInfo.header()->Flags);
W.printHex("CodeSize", LineInfo.header()->CodeSize);
@@ -1105,7 +1130,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
uint32_t ColumnIndex = 0;
for (const auto &Line : Entry.LineNumbers) {
if (Line.Offset >= LineInfo.header()->CodeSize) {
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
return;
}
@@ -1136,21 +1162,20 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
StringRef SectionContents) {
ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
Subsection.bytes_end());
- auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
+ auto CODD = std::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
SectionContents);
CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD),
CompilationCPUType, opts::CodeViewSubsectionBytes);
CVSymbolArray Symbols;
BinaryStreamReader Reader(BinaryData, llvm::support::little);
- if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
- consumeError(std::move(EC));
+ if (Error E = Reader.readArray(Symbols, Reader.getLength())) {
W.flush();
- error(object_error::parse_failed);
+ reportError(std::move(E), Obj->getFileName());
}
- if (auto EC = CVSD.dump(Symbols)) {
+ if (Error E = CVSD.dump(Symbols)) {
W.flush();
- error(std::move(EC));
+ reportError(std::move(E), Obj->getFileName());
}
CompilationCPUType = CVSD.getCompilationCPUType();
W.flush();
@@ -1159,12 +1184,14 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
BinaryStreamRef Stream(Subsection, llvm::support::little);
DebugChecksumsSubsectionRef Checksums;
- error(Checksums.initialize(Stream));
+ if (Error E = Checksums.initialize(Stream))
+ reportError(std::move(E), Obj->getFileName());
for (auto &FC : Checksums) {
DictScope S(W, "FileChecksum");
- StringRef Filename = error(CVStringTable.getString(FC.FileNameOffset));
+ StringRef Filename = unwrapOrError(
+ Obj->getFileName(), CVStringTable.getString(FC.FileNameOffset));
W.printHex("Filename", Filename, FC.FileNameOffset);
W.printHex("ChecksumSize", FC.Checksum.size());
W.printEnum("ChecksumKind", uint8_t(FC.Kind),
@@ -1177,7 +1204,8 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
BinaryStreamReader SR(Subsection, llvm::support::little);
DebugInlineeLinesSubsectionRef Lines;
- error(Lines.initialize(SR));
+ if (Error E = Lines.initialize(SR))
+ reportError(std::move(E), Obj->getFileName());
for (auto &Line : Lines) {
DictScope S(W, "InlineeSourceLine");
@@ -1198,15 +1226,18 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) {
// The file checksum subsection should precede all references to it.
if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
auto Iter = CVFileChecksumTable.getArray().at(FileOffset);
// Check if the file checksum table offset is valid.
if (Iter == CVFileChecksumTable.end())
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
- return error(CVStringTable.getString(Iter->FileNameOffset));
+ return unwrapOrError(Obj->getFileName(),
+ CVStringTable.getString(Iter->FileNameOffset));
}
void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) {
@@ -1219,35 +1250,38 @@ void COFFDumper::mergeCodeViewTypes(MergingTypeTableBuilder &CVIDs,
GlobalTypeTableBuilder &GlobalCVTypes,
bool GHash) {
for (const SectionRef &S : Obj->sections()) {
- StringRef SectionName;
- error(S.getName(SectionName));
+ StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());
if (SectionName == ".debug$T") {
- StringRef Data = unwrapOrError(S.getContents());
+ StringRef Data = unwrapOrError(Obj->getFileName(), S.getContents());
uint32_t Magic;
- error(consume(Data, Magic));
+ if (Error E = consume(Data, Magic))
+ reportError(std::move(E), Obj->getFileName());
+
if (Magic != 4)
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
CVTypeArray Types;
BinaryStreamReader Reader(Data, llvm::support::little);
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
consumeError(std::move(EC));
W.flush();
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
}
SmallVector<TypeIndex, 128> SourceToDest;
Optional<uint32_t> PCHSignature;
if (GHash) {
std::vector<GloballyHashedType> Hashes =
GloballyHashedType::hashTypes(Types);
- if (auto EC =
+ if (Error E =
mergeTypeAndIdRecords(GlobalCVIDs, GlobalCVTypes, SourceToDest,
Types, Hashes, PCHSignature))
- return error(std::move(EC));
+ return reportError(std::move(E), Obj->getFileName());
} else {
- if (auto EC = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types,
+ if (Error E = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types,
PCHSignature))
- return error(std::move(EC));
+ return reportError(std::move(E), Obj->getFileName());
}
}
}
@@ -1258,20 +1292,25 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
ListScope D(W, "CodeViewTypes");
W.printNumber("Section", SectionName, Obj->getSectionID(Section));
- StringRef Data = unwrapOrError(Section.getContents());
+ StringRef Data = unwrapOrError(Obj->getFileName(), Section.getContents());
if (opts::CodeViewSubsectionBytes)
W.printBinaryBlock("Data", Data);
uint32_t Magic;
- error(consume(Data, Magic));
+ if (Error E = consume(Data, Magic))
+ reportError(std::move(E), Obj->getFileName());
+
W.printHex("Magic", Magic);
if (Magic != COFF::DEBUG_SECTION_MAGIC)
- return error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
Types.reset(Data, 100);
TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
- error(codeview::visitTypeStream(Types, TDV));
+ if (Error E = codeview::visitTypeStream(Types, TDV))
+ reportError(std::move(E), Obj->getFileName());
+
W.flush();
}
@@ -1282,8 +1321,7 @@ void COFFDumper::printSectionHeaders() {
++SectionNumber;
const coff_section *Section = Obj->getCOFFSection(Sec);
- StringRef Name;
- error(Sec.getName(Name));
+ StringRef Name = unwrapOrError(Obj->getFileName(), Sec.getName());
DictScope D(W, "Section");
W.printNumber("Number", SectionNumber);
@@ -1318,7 +1356,7 @@ void COFFDumper::printSectionHeaders() {
if (opts::SectionData &&
!(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
- StringRef Data = unwrapOrError(Sec.getContents());
+ StringRef Data = unwrapOrError(Obj->getFileName(), Sec.getContents());
W.printBinaryBlock("SectionData", Data);
}
}
@@ -1330,8 +1368,7 @@ void COFFDumper::printRelocations() {
int SectionNumber = 0;
for (const SectionRef &Section : Obj->sections()) {
++SectionNumber;
- StringRef Name;
- error(Section.getName(Name));
+ StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());
bool PrintedGroup = false;
for (const RelocationRef &Reloc : Section.relocations()) {
@@ -1362,7 +1399,9 @@ void COFFDumper::printRelocation(const SectionRef &Section,
int64_t SymbolIndex = -1;
if (Symbol != Obj->symbol_end()) {
Expected<StringRef> SymbolNameOrErr = Symbol->getName();
- error(errorToErrorCode(SymbolNameOrErr.takeError()));
+ if (!SymbolNameOrErr)
+ reportError(SymbolNameOrErr.takeError(), Obj->getFileName());
+
SymbolName = *SymbolNameOrErr;
SymbolIndex = Obj->getSymbolIndex(Obj->getCOFFSymbol(*Symbol));
}
@@ -1439,7 +1478,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
if (Symbol.isFunctionDefinition()) {
const coff_aux_function_definition *Aux;
- error(getSymbolAuxData(Obj, Symbol, I, Aux));
+ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))
+ reportError(errorCodeToError(EC), Obj->getFileName());
DictScope AS(W, "AuxFunctionDef");
W.printNumber("TagIndex", Aux->TagIndex);
@@ -1449,15 +1489,16 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
} else if (Symbol.isAnyUndefined()) {
const coff_aux_weak_external *Aux;
- error(getSymbolAuxData(Obj, Symbol, I, Aux));
+ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))
+ reportError(errorCodeToError(EC), Obj->getFileName());
Expected<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
+ if (!Linked)
+ reportError(Linked.takeError(), Obj->getFileName());
+
StringRef LinkedName;
- std::error_code EC = errorToErrorCode(Linked.takeError());
- if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) {
- LinkedName = "";
- error(EC);
- }
+ if (std::error_code EC = Obj->getSymbolName(*Linked, LinkedName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
DictScope AS(W, "AuxWeakExternal");
W.printNumber("Linked", LinkedName, Aux->TagIndex);
@@ -1466,8 +1507,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
} else if (Symbol.isFileRecord()) {
const char *FileName;
- error(getSymbolAuxData(Obj, Symbol, I, FileName));
-
+ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, FileName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
DictScope AS(W, "AuxFileRecord");
StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() *
@@ -1476,7 +1517,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
break;
} else if (Symbol.isSectionDefinition()) {
const coff_aux_section_definition *Aux;
- error(getSymbolAuxData(Obj, Symbol, I, Aux));
+ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))
+ reportError(errorCodeToError(EC), Obj->getFileName());
int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
@@ -1493,26 +1535,27 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
const coff_section *Assoc;
StringRef AssocName = "";
if (std::error_code EC = Obj->getSection(AuxNumber, Assoc))
- error(EC);
+ reportError(errorCodeToError(EC), Obj->getFileName());
Expected<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc);
if (!Res)
- error(Res.takeError());
+ reportError(Res.takeError(), Obj->getFileName());
AssocName = *Res;
W.printNumber("AssocSection", AssocName, AuxNumber);
}
} else if (Symbol.isCLRToken()) {
const coff_aux_clr_token *Aux;
- error(getSymbolAuxData(Obj, Symbol, I, Aux));
+ if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))
+ reportError(errorCodeToError(EC), Obj->getFileName());
Expected<COFFSymbolRef> ReferredSym =
Obj->getSymbol(Aux->SymbolTableIndex);
+ if (!ReferredSym)
+ reportError(ReferredSym.takeError(), Obj->getFileName());
+
StringRef ReferredName;
- std::error_code EC = errorToErrorCode(ReferredSym.takeError());
- if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) {
- ReferredName = "";
- error(EC);
- }
+ if (std::error_code EC = Obj->getSymbolName(*ReferredSym, ReferredName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
DictScope AS(W, "AuxCLRToken");
W.printNumber("AuxType", Aux->AuxType);
@@ -1578,9 +1621,11 @@ void COFFDumper::printImportedSymbols(
iterator_range<imported_symbol_iterator> Range) {
for (const ImportedSymbolRef &I : Range) {
StringRef Sym;
- error(I.getSymbolName(Sym));
+ if (std::error_code EC = I.getSymbolName(Sym))
+ reportError(errorCodeToError(EC), Obj->getFileName());
uint16_t Ordinal;
- error(I.getOrdinal(Ordinal));
+ if (std::error_code EC = I.getOrdinal(Ordinal))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printNumber("Symbol", Sym, Ordinal);
}
}
@@ -1592,12 +1637,17 @@ void COFFDumper::printDelayImportedSymbols(
for (const ImportedSymbolRef &S : Range) {
DictScope Import(W, "Import");
StringRef Sym;
- error(S.getSymbolName(Sym));
+ if (std::error_code EC = S.getSymbolName(Sym))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+
uint16_t Ordinal;
- error(S.getOrdinal(Ordinal));
+ if (std::error_code EC = S.getOrdinal(Ordinal))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printNumber("Symbol", Sym, Ordinal);
+
uint64_t Addr;
- error(I.getImportAddress(Index++, Addr));
+ if (std::error_code EC = I.getImportAddress(Index++, Addr))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printHex("Address", Addr);
}
}
@@ -1607,13 +1657,16 @@ void COFFDumper::printCOFFImports() {
for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {
DictScope Import(W, "Import");
StringRef Name;
- error(I.getName(Name));
+ if (std::error_code EC = I.getName(Name))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printString("Name", Name);
uint32_t ILTAddr;
- error(I.getImportLookupTableRVA(ILTAddr));
+ if (std::error_code EC = I.getImportLookupTableRVA(ILTAddr))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printHex("ImportLookupTableRVA", ILTAddr);
uint32_t IATAddr;
- error(I.getImportAddressTableRVA(IATAddr));
+ if (std::error_code EC = I.getImportAddressTableRVA(IATAddr))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printHex("ImportAddressTableRVA", IATAddr);
// The import lookup table can be missing with certain older linkers, so
// fall back to the import address table in that case.
@@ -1627,10 +1680,12 @@ void COFFDumper::printCOFFImports() {
for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {
DictScope Import(W, "DelayImport");
StringRef Name;
- error(I.getName(Name));
+ if (std::error_code EC = I.getName(Name))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printString("Name", Name);
const delay_import_directory_table_entry *Table;
- error(I.getDelayImportTable(Table));
+ if (std::error_code EC = I.getDelayImportTable(Table))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printHex("Attributes", Table->Attributes);
W.printHex("ModuleHandle", Table->ModuleHandle);
W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
@@ -1648,9 +1703,12 @@ void COFFDumper::printCOFFExports() {
StringRef Name;
uint32_t Ordinal, RVA;
- error(E.getSymbolName(Name));
- error(E.getOrdinal(Ordinal));
- error(E.getExportRVA(RVA));
+ if (std::error_code EC = E.getSymbolName(Name))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+ if (std::error_code EC = E.getOrdinal(Ordinal))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+ if (std::error_code EC = E.getExportRVA(RVA))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printNumber("Ordinal", Ordinal);
W.printString("Name", Name);
@@ -1660,13 +1718,12 @@ void COFFDumper::printCOFFExports() {
void COFFDumper::printCOFFDirectives() {
for (const SectionRef &Section : Obj->sections()) {
- StringRef Name;
-
- error(Section.getName(Name));
+ StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());
if (Name != ".drectve")
continue;
- StringRef Contents = unwrapOrError(Section.getContents());
+ StringRef Contents =
+ unwrapOrError(Obj->getFileName(), Section.getContents());
W.printString("Directive(s)", Contents);
}
}
@@ -1689,8 +1746,10 @@ void COFFDumper::printCOFFBaseReloc() {
for (const BaseRelocRef &I : Obj->base_relocs()) {
uint8_t Type;
uint32_t RVA;
- error(I.getRVA(RVA));
- error(I.getType(Type));
+ if (std::error_code EC = I.getRVA(RVA))
+ reportError(errorCodeToError(EC), Obj->getFileName());
+ if (std::error_code EC = I.getType(Type))
+ reportError(errorCodeToError(EC), Obj->getFileName());
DictScope Import(W, "Entry");
W.printString("Type", getBaseRelocTypeName(Type));
W.printHex("Address", RVA);
@@ -1700,16 +1759,18 @@ void COFFDumper::printCOFFBaseReloc() {
void COFFDumper::printCOFFResources() {
ListScope ResourcesD(W, "Resources");
for (const SectionRef &S : Obj->sections()) {
- StringRef Name;
- error(S.getName(Name));
+ StringRef Name = unwrapOrError(Obj->getFileName(), S.getName());
if (!Name.startswith(".rsrc"))
continue;
- StringRef Ref = unwrapOrError(S.getContents());
+ StringRef Ref = unwrapOrError(Obj->getFileName(), S.getContents());
if ((Name == ".rsrc") || (Name == ".rsrc$01")) {
- ResourceSectionRef RSF(Ref);
- auto &BaseTable = unwrapOrError(RSF.getBaseTable());
+ ResourceSectionRef RSF;
+ Error E = RSF.load(Obj, S);
+ if (E)
+ reportError(std::move(E), Obj->getFileName());
+ auto &BaseTable = unwrapOrError(Obj->getFileName(), RSF.getBaseTable());
W.printNumber("Total Number of Resources",
countTotalTableEntries(RSF, BaseTable, "Type"));
W.printHex("Base Table Address",
@@ -1729,14 +1790,15 @@ COFFDumper::countTotalTableEntries(ResourceSectionRef RSF,
uint32_t TotalEntries = 0;
for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
i++) {
- auto Entry = unwrapOrError(getResourceDirectoryTableEntry(Table, i));
+ auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i));
if (Entry.Offset.isSubDir()) {
StringRef NextLevel;
if (Level == "Name")
NextLevel = "Language";
else
NextLevel = "Name";
- auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry));
+ auto &NextTable =
+ unwrapOrError(Obj->getFileName(), RSF.getEntrySubDir(Entry));
TotalEntries += countTotalTableEntries(RSF, NextTable, NextLevel);
} else {
TotalEntries += 1;
@@ -1755,13 +1817,13 @@ void COFFDumper::printResourceDirectoryTable(
// Iterate through level in resource directory tree.
for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
i++) {
- auto Entry = unwrapOrError(getResourceDirectoryTableEntry(Table, i));
+ auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i));
StringRef Name;
SmallString<20> IDStr;
raw_svector_ostream OS(IDStr);
if (i < Table.NumberOfNameEntries) {
ArrayRef<UTF16> RawEntryNameString =
- unwrapOrError(RSF.getEntryNameString(Entry));
+ unwrapOrError(Obj->getFileName(), RSF.getEntryNameString(Entry));
std::vector<UTF16> EndianCorrectedNameString;
if (llvm::sys::IsBigEndianHost) {
EndianCorrectedNameString.resize(RawEntryNameString.size() + 1);
@@ -1772,14 +1834,14 @@ void COFFDumper::printResourceDirectoryTable(
}
std::string EntryNameString;
if (!llvm::convertUTF16ToUTF8String(RawEntryNameString, EntryNameString))
- error(object_error::parse_failed);
+ reportError(errorCodeToError(object_error::parse_failed),
+ Obj->getFileName());
OS << ": ";
OS << EntryNameString;
} else {
if (Level == "Type") {
OS << ": ";
printResourceTypeName(Entry.Identifier.ID, OS);
- IDStr = IDStr.slice(0, IDStr.find_first_of(")", 0) + 1);
} else {
OS << ": (ID " << Entry.Identifier.ID << ")";
}
@@ -1793,7 +1855,8 @@ void COFFDumper::printResourceDirectoryTable(
NextLevel = "Language";
else
NextLevel = "Name";
- auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry));
+ auto &NextTable =
+ unwrapOrError(Obj->getFileName(), RSF.getEntrySubDir(Entry));
printResourceDirectoryTable(RSF, NextTable, NextLevel);
} else {
W.printHex("Entry Offset", Entry.Offset.value());
@@ -1804,24 +1867,29 @@ void COFFDumper::printResourceDirectoryTable(
W.printNumber("Major Version", Table.MajorVersion);
W.printNumber("Minor Version", Table.MinorVersion);
W.printNumber("Characteristics", Table.Characteristics);
+ ListScope DataScope(W, "Data");
+ auto &DataEntry =
+ unwrapOrError(Obj->getFileName(), RSF.getEntryData(Entry));
+ W.printHex("DataRVA", DataEntry.DataRVA);
+ W.printNumber("DataSize", DataEntry.DataSize);
+ W.printNumber("Codepage", DataEntry.Codepage);
+ W.printNumber("Reserved", DataEntry.Reserved);
+ StringRef Contents =
+ unwrapOrError(Obj->getFileName(), RSF.getContents(DataEntry));
+ W.printBinaryBlock("Data", Contents);
}
}
}
-ErrorOr<const coff_resource_dir_entry &>
-COFFDumper::getResourceDirectoryTableEntry(const coff_resource_dir_table &Table,
- uint32_t Index) {
- if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
- return object_error::parse_failed;
- auto TablePtr = reinterpret_cast<const coff_resource_dir_entry *>(&Table + 1);
- return TablePtr[Index];
-}
-
void COFFDumper::printStackMap() const {
object::SectionRef StackMapSection;
for (auto Sec : Obj->sections()) {
StringRef Name;
- Sec.getName(Name);
+ if (Expected<StringRef> NameOrErr = Sec.getName())
+ Name = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
+
if (Name == ".llvm_stackmaps") {
StackMapSection = Sec;
break;
@@ -1831,7 +1899,8 @@ void COFFDumper::printStackMap() const {
if (StackMapSection == object::SectionRef())
return;
- StringRef StackMapContents = unwrapOrError(StackMapSection.getContents());
+ StringRef StackMapContents =
+ unwrapOrError(Obj->getFileName(), StackMapSection.getContents());
ArrayRef<uint8_t> StackMapContentsArray =
arrayRefFromStringRef(StackMapContents);
@@ -1847,7 +1916,11 @@ void COFFDumper::printAddrsig() {
object::SectionRef AddrsigSection;
for (auto Sec : Obj->sections()) {
StringRef Name;
- Sec.getName(Name);
+ if (Expected<StringRef> NameOrErr = Sec.getName())
+ Name = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
+
if (Name == ".llvm_addrsig") {
AddrsigSection = Sec;
break;
@@ -1857,7 +1930,8 @@ void COFFDumper::printAddrsig() {
if (AddrsigSection == object::SectionRef())
return;
- StringRef AddrsigContents = unwrapOrError(AddrsigSection.getContents());
+ StringRef AddrsigContents =
+ unwrapOrError(Obj->getFileName(), AddrsigSection.getContents());
ArrayRef<uint8_t> AddrsigContentsArray(AddrsigContents.bytes_begin(),
AddrsigContents.size());
@@ -1869,15 +1943,15 @@ void COFFDumper::printAddrsig() {
const char *Err;
uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err);
if (Err)
- reportError(Err);
+ reportError(createError(Err), Obj->getFileName());
Expected<COFFSymbolRef> Sym = Obj->getSymbol(SymIndex);
+ if (!Sym)
+ reportError(Sym.takeError(), Obj->getFileName());
+
StringRef SymName;
- std::error_code EC = errorToErrorCode(Sym.takeError());
- if (EC || (EC = Obj->getSymbolName(*Sym, SymName))) {
- SymName = "";
- error(EC);
- }
+ if (std::error_code EC = Obj->getSymbolName(*Sym, SymName))
+ reportError(errorCodeToError(EC), Obj->getFileName());
W.printNumber("Sym", SymName, SymIndex);
Cur += Size;
@@ -1891,7 +1965,8 @@ void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
{
ListScope S(Writer, "MergedTypeStream");
TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
- error(codeview::visitTypeStream(TpiTypes, TDV));
+ if (Error Err = codeview::visitTypeStream(TpiTypes, TDV))
+ reportError(std::move(Err), "<?>");
Writer.flush();
}
@@ -1902,7 +1977,8 @@ void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
ListScope S(Writer, "MergedIDStream");
TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
TDV.setIpiTypes(IpiTypes);
- error(codeview::visitTypeStream(IpiTypes, TDV));
+ if (Error Err = codeview::visitTypeStream(IpiTypes, TDV))
+ reportError(std::move(Err), "<?>");
Writer.flush();
}
}
diff --git a/tools/llvm-readobj/DwarfCFIEHPrinter.h b/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 7055510ef2f2..0a365d4fe72a 100644
--- a/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -44,12 +44,12 @@ public:
void printUnwindInformation() const;
};
-template <class ELFO>
-static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj,
- uint64_t Addr) {
- auto Sections = Obj->sections();
+template <class ELFT>
+static const typename object::ELFObjectFile<ELFT>::Elf_Shdr *
+findSectionByAddress(const object::ELFObjectFile<ELFT> *ObjF, uint64_t Addr) {
+ auto Sections = ObjF->getELFFile()->sections();
if (Error E = Sections.takeError())
- reportError(toString(std::move(E)));
+ reportError(std::move(E), ObjF->getFileName());
for (const auto &Shdr : *Sections)
if (Shdr.sh_addr == Addr)
@@ -64,13 +64,15 @@ void PrinterContext<ELFT>::printUnwindInformation() const {
auto PHs = Obj->program_headers();
if (Error E = PHs.takeError())
- reportError(toString(std::move(E)));
+ reportError(std::move(E), ObjF->getFileName());
for (const auto &Phdr : *PHs) {
if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
EHFramePhdr = &Phdr;
if (Phdr.p_memsz != Phdr.p_filesz)
- reportError("p_memsz does not match p_filesz for GNU_EH_FRAME");
+ reportError(object::createError(
+ "p_memsz does not match p_filesz for GNU_EH_FRAME"),
+ ObjF->getFileName());
break;
}
}
@@ -81,12 +83,12 @@ void PrinterContext<ELFT>::printUnwindInformation() const {
auto Sections = Obj->sections();
if (Error E = Sections.takeError())
- reportError(toString(std::move(E)));
+ reportError(std::move(E), ObjF->getFileName());
for (const auto &Shdr : *Sections) {
auto SectionName = Obj->getSectionName(&Shdr);
if (Error E = SectionName.takeError())
- reportError(toString(std::move(E)));
+ reportError(std::move(E), ObjF->getFileName());
if (*SectionName == ".eh_frame")
printEHFrame(&Shdr);
@@ -97,49 +99,52 @@ template <typename ELFT>
void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
uint64_t EHFrameHdrAddress,
uint64_t EHFrameHdrSize) const {
- ListScope L(W, "EH_FRAME Header");
+ DictScope L(W, "EHFrameHeader");
W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
const object::ELFFile<ELFT> *Obj = ObjF->getELFFile();
- const auto *EHFrameHdrShdr = findSectionByAddress(Obj, EHFrameHdrAddress);
+ const auto *EHFrameHdrShdr = findSectionByAddress(ObjF, EHFrameHdrAddress);
if (EHFrameHdrShdr) {
auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
if (Error E = SectionName.takeError())
- reportError(toString(std::move(E)));
+ reportError(std::move(E), ObjF->getFileName());
W.printString("Corresponding Section", *SectionName);
}
- DataExtractor DE(
- StringRef(reinterpret_cast<const char *>(Obj->base()) + EHFrameHdrOffset,
- EHFrameHdrSize),
- ELFT::TargetEndianness == support::endianness::little,
- ELFT::Is64Bits ? 8 : 4);
+ DataExtractor DE(makeArrayRef(Obj->base() + EHFrameHdrOffset, EHFrameHdrSize),
+ ELFT::TargetEndianness == support::endianness::little,
+ ELFT::Is64Bits ? 8 : 4);
DictScope D(W, "Header");
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
auto Version = DE.getU8(&Offset);
W.printNumber("version", Version);
if (Version != 1)
- reportError("only version 1 of .eh_frame_hdr is supported");
+ reportError(
+ object::createError("only version 1 of .eh_frame_hdr is supported"),
+ ObjF->getFileName());
uint64_t EHFramePtrEnc = DE.getU8(&Offset);
W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);
if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
- reportError("unexpected encoding eh_frame_ptr_enc");
+ reportError(object::createError("unexpected encoding eh_frame_ptr_enc"),
+ ObjF->getFileName());
uint64_t FDECountEnc = DE.getU8(&Offset);
W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
if (FDECountEnc != dwarf::DW_EH_PE_udata4)
- reportError("unexpected encoding fde_count_enc");
+ reportError(object::createError("unexpected encoding fde_count_enc"),
+ ObjF->getFileName());
uint64_t TableEnc = DE.getU8(&Offset);
W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
- reportError("unexpected encoding table_enc");
+ reportError(object::createError("unexpected encoding table_enc"),
+ ObjF->getFileName());
auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
@@ -158,7 +163,8 @@ void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
if (InitialPC < PrevPC)
- reportError("initial_location is out of order");
+ reportError(object::createError("initial_location is out of order"),
+ ObjF->getFileName());
PrevPC = InitialPC;
++NumEntries;
@@ -178,7 +184,7 @@ void PrinterContext<ELFT>::printEHFrame(
const object::ELFFile<ELFT> *Obj = ObjF->getELFFile();
auto Result = Obj->getSectionContents(EHFrameShdr);
if (Error E = Result.takeError())
- reportError(toString(std::move(E)));
+ reportError(std::move(E), ObjF->getFileName());
auto Contents = Result.get();
DWARFDataExtractor DE(
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 4e1cb7d544e7..57144882c4b4 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
@@ -36,6 +37,7 @@
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/RelocationResolver.h"
#include "llvm/Object/StackMapParser.h"
#include "llvm/Support/AMDGPUMetadata.h"
#include "llvm/Support/ARMAttributeParser.h"
@@ -61,6 +63,7 @@
#include <memory>
#include <string>
#include <system_error>
+#include <unordered_set>
#include <vector>
using namespace llvm;
@@ -119,9 +122,9 @@ template <class ELFT> class DumpStyle;
/// the size, entity size and virtual address are different entries in arbitrary
/// order (DT_REL, DT_RELSZ, DT_RELENT for example).
struct DynRegionInfo {
- DynRegionInfo() = default;
- DynRegionInfo(const void *A, uint64_t S, uint64_t ES)
- : Addr(A), Size(S), EntSize(ES) {}
+ DynRegionInfo(StringRef ObjName) : FileName(ObjName) {}
+ DynRegionInfo(const void *A, uint64_t S, uint64_t ES, StringRef ObjName)
+ : Addr(A), Size(S), EntSize(ES), FileName(ObjName) {}
/// Address in current address space.
const void *Addr = nullptr;
@@ -130,14 +133,18 @@ struct DynRegionInfo {
/// Size of each entity in the region.
uint64_t EntSize = 0;
+ /// Name of the file. Used for error reporting.
+ StringRef FileName;
+
template <typename Type> ArrayRef<Type> getAsArrayRef() const {
const Type *Start = reinterpret_cast<const Type *>(Addr);
if (!Start)
return {Start, Start};
if (EntSize != sizeof(Type) || Size % EntSize) {
// TODO: Add a section index to this warning.
- reportWarning("invalid section size (" + Twine(Size) +
- ") or entity size (" + Twine(EntSize) + ")");
+ reportWarning(createError("invalid section size (" + Twine(Size) +
+ ") or entity size (" + Twine(EntSize) + ")"),
+ FileName);
return {Start, Start};
}
return {Start, Start + (Size / EntSize)};
@@ -166,11 +173,7 @@ public:
void printVersionInfo() override;
void printGroupSections() override;
- void printAttributes() override;
- void printMipsPLTGOT() override;
- void printMipsABIFlags() override;
- void printMipsReginfo() override;
- void printMipsOptions() override;
+ void printArchSpecificInfo() override;
void printStackMap() const override;
@@ -182,6 +185,7 @@ public:
void printNotes() override;
void printELFLinkerOptions() override;
+ void printStackSizes() override;
const object::ELFObjectFile<ELFT> *getElfObject() const { return ObjF; };
@@ -195,20 +199,27 @@ private:
if (DRI.Addr < Obj->base() ||
reinterpret_cast<const uint8_t *>(DRI.Addr) + DRI.Size >
Obj->base() + Obj->getBufSize())
- error(llvm::object::object_error::parse_failed);
+ reportError(errorCodeToError(llvm::object::object_error::parse_failed),
+ ObjF->getFileName());
return DRI;
}
DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) {
- return checkDRI(
- {ObjF->getELFFile()->base() + P->p_offset, P->p_filesz, EntSize});
+ return checkDRI({ObjF->getELFFile()->base() + P->p_offset, P->p_filesz,
+ EntSize, ObjF->getFileName()});
}
DynRegionInfo createDRIFrom(const Elf_Shdr *S) {
- return checkDRI(
- {ObjF->getELFFile()->base() + S->sh_offset, S->sh_size, S->sh_entsize});
+ return checkDRI({ObjF->getELFFile()->base() + S->sh_offset, S->sh_size,
+ S->sh_entsize, ObjF->getFileName()});
}
+ void printAttributes();
+ void printMipsReginfo();
+ void printMipsOptions();
+
+ std::pair<const Elf_Phdr *, const Elf_Shdr *>
+ findDynamic(const ELFFile<ELFT> *Obj);
void loadDynamicTable(const ELFFile<ELFT> *Obj);
void parseDynamicTable();
@@ -226,7 +237,7 @@ private:
DynRegionInfo DynSymRegion;
DynRegionInfo DynamicTable;
StringRef DynamicStringTable;
- StringRef SOName = "<Not found>";
+ std::string SOName = "<Not found>";
const Elf_Hash *HashTable = nullptr;
const Elf_GnuHash *GnuHashTable = nullptr;
const Elf_Shdr *DotSymtabSec = nullptr;
@@ -291,7 +302,8 @@ public:
void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
StringRef &SectionName,
unsigned &SectionIndex) const;
- std::string getStaticSymbolName(uint32_t Index) const;
+ Expected<std::string> getStaticSymbolName(uint32_t Index) const;
+ std::string getDynamicString(uint64_t Value) const;
StringRef getSymbolVersionByIndex(StringRef StrTab,
uint32_t VersionSymbolIndex,
bool &IsDefault) const;
@@ -328,16 +340,27 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
} else {
if (!DotSymtabSec)
return;
- StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
- Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
- SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec));
+ StrTable = unwrapOrError(ObjF->getFileName(),
+ Obj->getStringTableForSymtab(*DotSymtabSec));
+ Syms = unwrapOrError(ObjF->getFileName(), Obj->symbols(DotSymtabSec));
+ SymtabName =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DotSymtabSec));
Entries = DotSymtabSec->getEntityCount();
}
if (Syms.begin() == Syms.end())
return;
- ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries);
+
+ // The st_other field has 2 logical parts. The first two bits hold the symbol
+ // visibility (STV_*) and the remainder hold other platform-specific values.
+ bool NonVisibilityBitsUsed = llvm::find_if(Syms, [](const Elf_Sym &S) {
+ return S.st_other & ~0x3;
+ }) != Syms.end();
+
+ ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries,
+ NonVisibilityBitsUsed);
for (const auto &Sym : Syms)
- ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);
+ ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic,
+ NonVisibilityBitsUsed);
}
template <class ELFT> class MipsGOTParser;
@@ -346,8 +369,20 @@ template <typename ELFT> class DumpStyle {
public:
using Elf_Shdr = typename ELFT::Shdr;
using Elf_Sym = typename ELFT::Sym;
+ using Elf_Addr = typename ELFT::Addr;
+
+ DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {
+ FileName = this->Dumper->getElfObject()->getFileName();
+
+ // Dumper reports all non-critical errors as warnings.
+ // It does not print the same warning more than once.
+ WarningHandler = [this](const Twine &Msg) {
+ if (Warnings.insert(Msg.str()).second)
+ reportWarning(createError(Msg), FileName);
+ return Error::success();
+ };
+ }
- DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {}
virtual ~DumpStyle() = default;
virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0;
@@ -360,10 +395,10 @@ public:
virtual void printDynamic(const ELFFile<ELFT> *Obj) {}
virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name,
- size_t Offset) {}
+ size_t Offset, bool NonVisibilityBitsUsed) {}
virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol,
const Elf_Sym *FirstSym, StringRef StrTable,
- bool IsDynamic) = 0;
+ bool IsDynamic, bool NonVisibilityBitsUsed) = 0;
virtual void printProgramHeaders(const ELFFile<ELFT> *Obj,
bool PrintProgramHeaders,
cl::boolOrDefault PrintSectionMapping) = 0;
@@ -378,11 +413,31 @@ public:
virtual void printAddrsig(const ELFFile<ELFT> *Obj) = 0;
virtual void printNotes(const ELFFile<ELFT> *Obj) = 0;
virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printStackSizes(const ELFObjectFile<ELFT> *Obj) = 0;
+ void printNonRelocatableStackSizes(const ELFObjectFile<ELFT> *Obj,
+ std::function<void()> PrintHeader);
+ void printRelocatableStackSizes(const ELFObjectFile<ELFT> *Obj,
+ std::function<void()> PrintHeader);
+ void printFunctionStackSize(const ELFObjectFile<ELFT> *Obj, uint64_t SymValue,
+ SectionRef FunctionSec,
+ const StringRef SectionName, DataExtractor Data,
+ uint64_t *Offset);
+ void printStackSize(const ELFObjectFile<ELFT> *Obj, RelocationRef Rel,
+ SectionRef FunctionSec,
+ const StringRef &StackSizeSectionName,
+ const RelocationResolver &Resolver, DataExtractor Data);
+ virtual void printStackSizeEntry(uint64_t Size, StringRef FuncName) = 0;
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
+ virtual void printMipsABIFlags(const ELFObjectFile<ELFT> *Obj) = 0;
const ELFDumper<ELFT> *dumper() const { return Dumper; }
+protected:
+ std::function<Error(const Twine &Msg)> WarningHandler;
+ StringRef FileName;
+
private:
+ std::unordered_set<std::string> Warnings;
const ELFDumper<ELFT> *Dumper;
};
@@ -407,8 +462,8 @@ public:
void printHashSymbols(const ELFO *Obj) override;
void printDynamic(const ELFFile<ELFT> *Obj) override;
void printDynamicRelocations(const ELFO *Obj) override;
- void printSymtabMessage(const ELFO *Obj, StringRef Name,
- size_t Offset) override;
+ void printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Offset,
+ bool NonVisibilityBitsUsed) override;
void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders,
cl::boolOrDefault PrintSectionMapping) override;
void printVersionSymbolSection(const ELFFile<ELFT> *Obj,
@@ -422,8 +477,11 @@ public:
void printAddrsig(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
+ void printStackSizes(const ELFObjectFile<ELFT> *Obj) override;
+ void printStackSizeEntry(uint64_t Size, StringRef FuncName) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
+ void printMipsABIFlags(const ELFObjectFile<ELFT> *Obj) override;
private:
struct Field {
@@ -484,7 +542,8 @@ private:
void printRelocation(const ELFO *Obj, const Elf_Sym *Sym,
StringRef SymbolName, const Elf_Rela &R, bool IsRela);
void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
- StringRef StrTable, bool IsDynamic) override;
+ StringRef StrTable, bool IsDynamic,
+ bool NonVisibilityBitsUsed) override;
std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol,
const Elf_Sym *FirstSym);
void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela);
@@ -525,8 +584,11 @@ public:
void printAddrsig(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
+ void printStackSizes(const ELFObjectFile<ELFT> *Obj) override;
+ void printStackSizeEntry(uint64_t Size, StringRef FuncName) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
+ void printMipsABIFlags(const ELFObjectFile<ELFT> *Obj) override;
private:
void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
@@ -534,7 +596,8 @@ private:
void printSymbols(const ELFO *Obj);
void printDynamicSymbols(const ELFO *Obj);
void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
- StringRef StrTable, bool IsDynamic) override;
+ StringRef StrTable, bool IsDynamic,
+ bool /*NonVisibilityBitsUsed*/) override;
void printProgramHeaders(const ELFO *Obj);
void printSectionMapping(const ELFO *Obj) {}
@@ -680,9 +743,9 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
sizeof(Elf_Sym);
// Get the corresponding version index entry.
- const Elf_Versym *Versym =
- unwrapOrError(ObjF->getELFFile()->template getEntry<Elf_Versym>(
- SymbolVersionSection, EntryIndex));
+ const Elf_Versym *Versym = unwrapOrError(
+ ObjF->getFileName(), ObjF->getELFFile()->template getEntry<Elf_Versym>(
+ SymbolVersionSection, EntryIndex));
return this->getSymbolVersionByIndex(StrTab, Versym->vs_index, IsDefault);
}
@@ -691,15 +754,22 @@ static std::string maybeDemangle(StringRef Name) {
}
template <typename ELFT>
-std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
+Expected<std::string>
+ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
- StringRef StrTable =
- unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
- Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
- if (Index >= Syms.size())
- reportError("Invalid symbol index");
- const Elf_Sym *Sym = &Syms[Index];
- return maybeDemangle(unwrapOrError(Sym->getName(StrTable)));
+ Expected<const typename ELFT::Sym *> SymOrErr =
+ Obj->getSymbol(DotSymtabSec, Index);
+ if (!SymOrErr)
+ return SymOrErr.takeError();
+
+ Expected<StringRef> StrTabOrErr = Obj->getStringTableForSymtab(*DotSymtabSec);
+ if (!StrTabOrErr)
+ return StrTabOrErr.takeError();
+
+ Expected<StringRef> NameOrErr = (*SymOrErr)->getName(*StrTabOrErr);
+ if (!NameOrErr)
+ return NameOrErr.takeError();
+ return maybeDemangle(*NameOrErr);
}
template <typename ELFT>
@@ -717,7 +787,7 @@ StringRef ELFDumper<ELFT>::getSymbolVersionByIndex(StringRef StrTab,
// Lookup this symbol in the version table.
LoadVersionMap();
if (VersionIndex >= VersionMap.size() || VersionMap[VersionIndex].isNull())
- reportError("Invalid version entry");
+ reportError(createError("Invalid version entry"), ObjF->getFileName());
const VersionMapEntry &Entry = VersionMap[VersionIndex];
// Get the version name string.
@@ -731,7 +801,7 @@ StringRef ELFDumper<ELFT>::getSymbolVersionByIndex(StringRef StrTab,
IsDefault = false;
}
if (NameOffset >= StrTab.size())
- reportError("Invalid string offset");
+ reportError(createError("Invalid string offset"), ObjF->getFileName());
return StrTab.data() + NameOffset;
}
@@ -739,14 +809,14 @@ template <typename ELFT>
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
StringRef StrTable,
bool IsDynamic) const {
- std::string SymbolName =
- maybeDemangle(unwrapOrError(Symbol->getName(StrTable)));
+ std::string SymbolName = maybeDemangle(
+ unwrapOrError(ObjF->getFileName(), Symbol->getName(StrTable)));
if (SymbolName.empty() && Symbol->getType() == ELF::STT_SECTION) {
unsigned SectionIndex;
StringRef SectionName;
- Elf_Sym_Range Syms =
- unwrapOrError(ObjF->getELFFile()->symbols(DotSymtabSec));
+ Elf_Sym_Range Syms = unwrapOrError(
+ ObjF->getFileName(), ObjF->getELFFile()->symbols(DotSymtabSec));
getSectionNameIndex(Symbol, Syms.begin(), SectionName, SectionIndex);
return SectionName;
}
@@ -783,31 +853,32 @@ void ELFDumper<ELFT>::getSectionNameIndex(const Elf_Sym *Symbol,
SectionName = "Reserved";
else {
if (SectionIndex == SHN_XINDEX)
- SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>(
- Symbol, FirstSym, ShndxTable));
+ SectionIndex = unwrapOrError(ObjF->getFileName(),
+ object::getExtendedSymbolTableIndex<ELFT>(
+ Symbol, FirstSym, ShndxTable));
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
const typename ELFT::Shdr *Sec =
- unwrapOrError(Obj->getSection(SectionIndex));
- SectionName = unwrapOrError(Obj->getSectionName(Sec));
+ unwrapOrError(ObjF->getFileName(), Obj->getSection(SectionIndex));
+ SectionName = unwrapOrError(ObjF->getFileName(), Obj->getSectionName(Sec));
}
}
template <class ELFO>
static const typename ELFO::Elf_Shdr *
-findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) {
- for (const auto &Shdr : unwrapOrError(Obj->sections()))
+findNotEmptySectionByAddress(const ELFO *Obj, StringRef FileName,
+ uint64_t Addr) {
+ for (const auto &Shdr : unwrapOrError(FileName, Obj->sections()))
if (Shdr.sh_addr == Addr && Shdr.sh_size > 0)
return &Shdr;
return nullptr;
}
template <class ELFO>
-static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj,
- StringRef Name) {
- for (const auto &Shdr : unwrapOrError(Obj.sections())) {
- if (Name == unwrapOrError(Obj.getSectionName(&Shdr)))
+static const typename ELFO::Elf_Shdr *
+findSectionByName(const ELFO &Obj, StringRef FileName, StringRef Name) {
+ for (const auto &Shdr : unwrapOrError(FileName, Obj.sections()))
+ if (Name == unwrapOrError(FileName, Obj.getSectionName(&Shdr)))
return &Shdr;
- }
return nullptr;
}
@@ -1356,10 +1427,12 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) {
}
template <typename ELFT>
-void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
+std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *>
+ELFDumper<ELFT>::findDynamic(const ELFFile<ELFT> *Obj) {
// Try to locate the PT_DYNAMIC header.
const Elf_Phdr *DynamicPhdr = nullptr;
- for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
+ for (const Elf_Phdr &Phdr :
+ unwrapOrError(ObjF->getFileName(), Obj->program_headers())) {
if (Phdr.p_type != ELF::PT_DYNAMIC)
continue;
DynamicPhdr = &Phdr;
@@ -1368,61 +1441,132 @@ void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
// Try to locate the .dynamic section in the sections header table.
const Elf_Shdr *DynamicSec = nullptr;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec :
+ unwrapOrError(ObjF->getFileName(), Obj->sections())) {
if (Sec.sh_type != ELF::SHT_DYNAMIC)
continue;
DynamicSec = &Sec;
break;
}
- // Information in the section header has priority over the information
- // in a PT_DYNAMIC header.
+ if (DynamicPhdr && DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
+ ObjF->getMemoryBufferRef().getBufferSize()) {
+ reportWarning(
+ createError(
+ "PT_DYNAMIC segment offset + size exceeds the size of the file"),
+ ObjF->getFileName());
+ // Don't use the broken dynamic header.
+ DynamicPhdr = nullptr;
+ }
+
+ if (DynamicPhdr && DynamicSec) {
+ StringRef Name =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DynamicSec));
+ if (DynamicSec->sh_addr + DynamicSec->sh_size >
+ DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
+ DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
+ reportWarning(createError("The SHT_DYNAMIC section '" + Name +
+ "' is not contained within the "
+ "PT_DYNAMIC segment"),
+ ObjF->getFileName());
+
+ if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)
+ reportWarning(createError("The SHT_DYNAMIC section '" + Name +
+ "' is not at the start of "
+ "PT_DYNAMIC segment"),
+ ObjF->getFileName());
+ }
+
+ return std::make_pair(DynamicPhdr, DynamicSec);
+}
+
+template <typename ELFT>
+void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
+ const Elf_Phdr *DynamicPhdr;
+ const Elf_Shdr *DynamicSec;
+ std::tie(DynamicPhdr, DynamicSec) = findDynamic(Obj);
+ if (!DynamicPhdr && !DynamicSec)
+ return;
+
+ DynRegionInfo FromPhdr(ObjF->getFileName());
+ bool IsPhdrTableValid = false;
+ if (DynamicPhdr) {
+ FromPhdr = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn));
+ IsPhdrTableValid = !FromPhdr.getAsArrayRef<Elf_Dyn>().empty();
+ }
+
+ // Locate the dynamic table described in a section header.
// Ignore sh_entsize and use the expected value for entry size explicitly.
- // This allows us to dump the dynamic sections with a broken sh_entsize
+ // This allows us to dump dynamic sections with a broken sh_entsize
// field.
+ DynRegionInfo FromSec(ObjF->getFileName());
+ bool IsSecTableValid = false;
if (DynamicSec) {
- DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset,
- DynamicSec->sh_size, sizeof(Elf_Dyn)});
- parseDynamicTable();
+ FromSec =
+ checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset,
+ DynamicSec->sh_size, sizeof(Elf_Dyn), ObjF->getFileName()});
+ IsSecTableValid = !FromSec.getAsArrayRef<Elf_Dyn>().empty();
}
- // If we have a PT_DYNAMIC header, we will either check the found dynamic
- // section or take the dynamic table data directly from the header.
- if (!DynamicPhdr)
+ // When we only have information from one of the SHT_DYNAMIC section header or
+ // PT_DYNAMIC program header, just use that.
+ if (!DynamicPhdr || !DynamicSec) {
+ if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) {
+ DynamicTable = DynamicPhdr ? FromPhdr : FromSec;
+ parseDynamicTable();
+ } else {
+ reportWarning(createError("no valid dynamic table was found"),
+ ObjF->getFileName());
+ }
return;
+ }
- if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
- ObjF->getMemoryBufferRef().getBufferSize())
- reportError(
- "PT_DYNAMIC segment offset + size exceeds the size of the file");
+ // At this point we have tables found from the section header and from the
+ // dynamic segment. Usually they match, but we have to do sanity checks to
+ // verify that.
- if (!DynamicSec) {
- DynamicTable = createDRIFrom(DynamicPhdr, sizeof(Elf_Dyn));
- parseDynamicTable();
+ if (FromPhdr.Addr != FromSec.Addr)
+ reportWarning(createError("SHT_DYNAMIC section header and PT_DYNAMIC "
+ "program header disagree about "
+ "the location of the dynamic table"),
+ ObjF->getFileName());
+
+ if (!IsPhdrTableValid && !IsSecTableValid) {
+ reportWarning(createError("no valid dynamic table was found"),
+ ObjF->getFileName());
return;
}
- StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec));
- if (DynamicSec->sh_addr + DynamicSec->sh_size >
- DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
- DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
- reportWarning("The SHT_DYNAMIC section '" + Name +
- "' is not contained within the "
- "PT_DYNAMIC segment");
+ // Information in the PT_DYNAMIC program header has priority over the information
+ // in a section header.
+ if (IsPhdrTableValid) {
+ if (!IsSecTableValid)
+ reportWarning(
+ createError(
+ "SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used"),
+ ObjF->getFileName());
+ DynamicTable = FromPhdr;
+ } else {
+ reportWarning(
+ createError(
+ "PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used"),
+ ObjF->getFileName());
+ DynamicTable = FromSec;
+ }
- if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)
- reportWarning("The SHT_DYNAMIC section '" + Name +
- "' is not at the start of "
- "PT_DYNAMIC segment");
+ parseDynamicTable();
}
template <typename ELFT>
ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
- ScopedPrinter &Writer)
- : ObjDumper(Writer), ObjF(ObjF) {
+ ScopedPrinter &Writer)
+ : ObjDumper(Writer), ObjF(ObjF), DynRelRegion(ObjF->getFileName()),
+ DynRelaRegion(ObjF->getFileName()), DynRelrRegion(ObjF->getFileName()),
+ DynPLTRelRegion(ObjF->getFileName()), DynSymRegion(ObjF->getFileName()),
+ DynamicTable(ObjF->getFileName()) {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
-
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec :
+ unwrapOrError(ObjF->getFileName(), Obj->sections())) {
switch (Sec.sh_type) {
case ELF::SHT_SYMTAB:
if (!DotSymtabSec)
@@ -1433,16 +1577,17 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
DynSymRegion = createDRIFrom(&Sec);
// This is only used (if Elf_Shdr present)for naming section in GNU
// style
- DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
+ DynSymtabName =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionName(&Sec));
if (Expected<StringRef> E = Obj->getStringTableForSymtab(Sec))
DynamicStringTable = *E;
else
- warn(E.takeError());
+ reportWarning(E.takeError(), ObjF->getFileName());
}
break;
case ELF::SHT_SYMTAB_SHNDX:
- ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
+ ShndxTable = unwrapOrError(ObjF->getFileName(), Obj->getSHNDXTable(Sec));
break;
case ELF::SHT_GNU_versym:
if (!SymbolVersionSection)
@@ -1547,10 +1692,13 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * {
auto MappedAddrOrError = ObjF->getELFFile()->toMappedAddr(VAddr);
if (!MappedAddrOrError) {
- reportWarning("Unable to parse DT_" +
- Twine(getTypeString(
- ObjF->getELFFile()->getHeader()->e_machine, Tag)) +
- ": " + llvm::toString(MappedAddrOrError.takeError()));
+ Error Err =
+ createError("Unable to parse DT_" +
+ Twine(getTypeString(
+ ObjF->getELFFile()->getHeader()->e_machine, Tag)) +
+ ": " + llvm::toString(MappedAddrOrError.takeError()));
+
+ reportWarning(std::move(Err), ObjF->getFileName());
return nullptr;
}
return MappedAddrOrError.get();
@@ -1576,10 +1724,29 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
case ELF::DT_STRSZ:
StringTableSize = Dyn.getVal();
break;
- case ELF::DT_SYMTAB:
- DynSymRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
- DynSymRegion.EntSize = sizeof(Elf_Sym);
+ case ELF::DT_SYMTAB: {
+ // Often we find the information about the dynamic symbol table
+ // location in the SHT_DYNSYM section header. However, the value in
+ // DT_SYMTAB has priority, because it is used by dynamic loaders to
+ // locate .dynsym at runtime. The location we find in the section header
+ // and the location we find here should match. If we can't map the
+ // DT_SYMTAB value to an address (e.g. when there are no program headers), we
+ // ignore its value.
+ if (const uint8_t *VA = toMappedAddr(Dyn.getTag(), Dyn.getPtr())) {
+ // EntSize is non-zero if the dynamic symbol table has been found via a
+ // section header.
+ if (DynSymRegion.EntSize && VA != DynSymRegion.Addr)
+ reportWarning(
+ createError(
+ "SHT_DYNSYM section header and DT_SYMTAB disagree about "
+ "the location of the dynamic symbol table"),
+ ObjF->getFileName());
+
+ DynSymRegion.Addr = VA;
+ DynSymRegion.EntSize = sizeof(Elf_Sym);
+ }
break;
+ }
case ELF::DT_RELA:
DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
break;
@@ -1619,8 +1786,9 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
else if (Dyn.getVal() == DT_RELA)
DynPLTRelRegion.EntSize = sizeof(Elf_Rela);
else
- reportError(Twine("unknown DT_PLTREL value of ") +
- Twine((uint64_t)Dyn.getVal()));
+ reportError(createError(Twine("unknown DT_PLTREL value of ") +
+ Twine((uint64_t)Dyn.getVal())),
+ ObjF->getFileName());
break;
case ELF::DT_JMPREL:
DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
@@ -1632,8 +1800,7 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
}
if (StringTableBegin)
DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
- if (SONameOffset && SONameOffset < DynamicStringTable.size())
- SOName = DynamicStringTable.data() + SONameOffset;
+ SOName = getDynamicString(SONameOffset);
}
template <typename ELFT>
@@ -1715,6 +1882,10 @@ template <class ELFT> void ELFDumper<ELFT>::printELFLinkerOptions() {
ELFDumperStyle->printELFLinkerOptions(ObjF->getELFFile());
}
+template <class ELFT> void ELFDumper<ELFT>::printStackSizes() {
+ ELFDumperStyle->printStackSizes(ObjF);
+}
+
#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \
{ #enum, prefix##_##enum }
@@ -1953,13 +2124,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
{DT_RPATH, "Library rpath"},
{DT_RUNPATH, "Library runpath"},
};
- OS << TagNames.at(Type) << ": ";
- if (DynamicStringTable.empty())
- OS << "<String table is empty or was not found> ";
- else if (Value < DynamicStringTable.size())
- OS << "[" << StringRef(DynamicStringTable.data() + Value) << "]";
- else
- OS << "<Invalid offset 0x" << utohexstr(Value) << ">";
+ OS << TagNames.at(Type) << ": [" << getDynamicString(Value) << "]";
break;
}
case DT_FLAGS:
@@ -1974,6 +2139,15 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
}
}
+template <class ELFT>
+std::string ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
+ if (DynamicStringTable.empty())
+ return "<String table is empty or was not found>";
+ if (Value < DynamicStringTable.size())
+ return DynamicStringTable.data() + Value;
+ return Twine("<Invalid offset 0x" + utohexstr(Value) + ">").str();
+}
+
template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {
DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF);
Ctx.printUnwindInformation();
@@ -1985,7 +2159,8 @@ template <> void ELFDumper<ELF32LE>::printUnwindInfo() {
const ELFFile<ELF32LE> *Obj = ObjF->getELFFile();
const unsigned Machine = Obj->getHeader()->e_machine;
if (Machine == EM_ARM) {
- ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, DotSymtabSec);
+ ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, ObjF->getFileName(),
+ DotSymtabSec);
Ctx.PrintUnwindInformation();
}
DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF);
@@ -2001,17 +2176,10 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicTable() {
template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {
ListScope D(W, "NeededLibraries");
- using LibsTy = std::vector<StringRef>;
- LibsTy Libs;
-
+ std::vector<std::string> Libs;
for (const auto &Entry : dynamic_table())
- if (Entry.d_tag == ELF::DT_NEEDED) {
- uint64_t Value = Entry.d_un.d_val;
- if (Value < DynamicStringTable.size())
- Libs.push_back(StringRef(DynamicStringTable.data() + Value));
- else
- Libs.push_back("<Library name index out of range>");
- }
+ if (Entry.d_tag == ELF::DT_NEEDED)
+ Libs.push_back(getDynamicString(Entry.d_un.d_val));
llvm::stable_sort(Libs);
@@ -2042,7 +2210,7 @@ template <typename ELFT> void ELFDumper<ELFT>::printGnuHashTable() {
Elf_Sym_Range Syms = dynamic_symbols();
unsigned NumSyms = std::distance(Syms.begin(), Syms.end());
if (!NumSyms)
- reportError("No dynamic symbol section");
+ reportError(createError("No dynamic symbol section"), ObjF->getFileName());
W.printHexList("Values", GnuHashTable->values(NumSyms));
}
@@ -2050,6 +2218,30 @@ template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
W.printString("LoadName", SOName);
}
+template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
+ const ELFFile<ELFT> *Obj = ObjF->getELFFile();
+ switch (Obj->getHeader()->e_machine) {
+ case EM_ARM:
+ printAttributes();
+ break;
+ case EM_MIPS: {
+ ELFDumperStyle->printMipsABIFlags(ObjF);
+ printMipsOptions();
+ printMipsReginfo();
+
+ MipsGOTParser<ELFT> Parser(Obj, ObjF->getFileName(), dynamic_table(),
+ dynamic_symbols());
+ if (Parser.hasGot())
+ ELFDumperStyle->printMipsGOT(Parser);
+ if (Parser.hasPlt())
+ ELFDumperStyle->printMipsPLT(Parser);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
W.startLine() << "Attributes not implemented.\n";
}
@@ -2064,11 +2256,13 @@ template <> void ELFDumper<ELF32LE>::printAttributes() {
}
DictScope BA(W, "BuildAttributes");
- for (const ELFO::Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const ELFO::Elf_Shdr &Sec :
+ unwrapOrError(ObjF->getFileName(), Obj->sections())) {
if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES)
continue;
- ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Sec));
+ ArrayRef<uint8_t> Contents =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(&Sec));
if (Contents[0] != ARMBuildAttrs::Format_Version) {
errs() << "unrecognised FormatVersion: 0x"
<< Twine::utohexstr(Contents[0]) << '\n';
@@ -2092,7 +2286,8 @@ public:
const bool IsStatic;
const ELFO * const Obj;
- MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);
+ MipsGOTParser(const ELFO *Obj, StringRef FileName, Elf_Dyn_Range DynTable,
+ Elf_Sym_Range DynSyms);
bool hasGot() const { return !GotEntries.empty(); }
bool hasPlt() const { return !PltEntries.empty(); }
@@ -2126,6 +2321,8 @@ private:
const Elf_Shdr *PltSec;
const Elf_Shdr *PltRelSec;
const Elf_Shdr *PltSymTable;
+ StringRef FileName;
+
Elf_Sym_Range GotDynSyms;
StringRef PltStrTable;
@@ -2136,21 +2333,24 @@ private:
} // end anonymous namespace
template <class ELFT>
-MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
+MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, StringRef FileName,
+ Elf_Dyn_Range DynTable,
Elf_Sym_Range DynSyms)
: IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0),
- GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) {
+ GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr),
+ FileName(FileName) {
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed GOT description.
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
// Find static GOT secton.
if (IsStatic) {
- GotSec = findSectionByName(*Obj, ".got");
+ GotSec = findSectionByName(*Obj, FileName, ".got");
if (!GotSec)
- reportError("Cannot find .got section");
+ return;
- ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec));
+ ArrayRef<uint8_t> Content =
+ unwrapOrError(FileName, Obj->getSectionContents(GotSec));
GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
Content.size() / sizeof(Entry));
LocalNum = GotEntries.size();
@@ -2194,17 +2394,21 @@ MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
size_t DynSymTotal = DynSyms.size();
if (*DtGotSym > DynSymTotal)
- reportError("MIPS_GOTSYM exceeds a number of dynamic symbols");
+ reportError(
+ createError("MIPS_GOTSYM exceeds a number of dynamic symbols"),
+ FileName);
- GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot);
+ GotSec = findNotEmptySectionByAddress(Obj, FileName, *DtPltGot);
if (!GotSec)
- reportError("There is no not empty GOT section at 0x" +
- Twine::utohexstr(*DtPltGot));
+ reportError(createError("There is no not empty GOT section at 0x" +
+ Twine::utohexstr(*DtPltGot)),
+ FileName);
LocalNum = *DtLocalGotNum;
GlobalNum = DynSymTotal - *DtGotSym;
- ArrayRef<uint8_t> Content = unwrapOrError(Obj->getSectionContents(GotSec));
+ ArrayRef<uint8_t> Content =
+ unwrapOrError(FileName, Obj->getSectionContents(GotSec));
GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
Content.size() / sizeof(Entry));
GotDynSyms = DynSyms.drop_front(*DtGotSym);
@@ -2217,23 +2421,24 @@ MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
if (!DtJmpRel)
report_fatal_error("Cannot find JMPREL dynamic table tag.");
- PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot);
+ PltSec = findNotEmptySectionByAddress(Obj, FileName, * DtMipsPltGot);
if (!PltSec)
report_fatal_error("There is no not empty PLTGOT section at 0x " +
Twine::utohexstr(*DtMipsPltGot));
- PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel);
+ PltRelSec = findNotEmptySectionByAddress(Obj, FileName, * DtJmpRel);
if (!PltRelSec)
report_fatal_error("There is no not empty RELPLT section at 0x" +
Twine::utohexstr(*DtJmpRel));
ArrayRef<uint8_t> PltContent =
- unwrapOrError(Obj->getSectionContents(PltSec));
+ unwrapOrError(FileName, Obj->getSectionContents(PltSec));
PltEntries = Entries(reinterpret_cast<const Entry *>(PltContent.data()),
PltContent.size() / sizeof(Entry));
- PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link));
- PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable));
+ PltSymTable = unwrapOrError(FileName, Obj->getSection(PltRelSec->sh_link));
+ PltStrTable =
+ unwrapOrError(FileName, Obj->getStringTableForSymtab(*PltSymTable));
}
}
@@ -2334,26 +2539,16 @@ const typename MipsGOTParser<ELFT>::Elf_Sym *
MipsGOTParser<ELFT>::getPltSym(const Entry *E) const {
int64_t Offset = std::distance(getPltEntries().data(), E);
if (PltRelSec->sh_type == ELF::SHT_REL) {
- Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec));
- return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
+ Elf_Rel_Range Rels = unwrapOrError(FileName, Obj->rels(PltRelSec));
+ return unwrapOrError(FileName,
+ Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
} else {
- Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec));
- return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
+ Elf_Rela_Range Rels = unwrapOrError(FileName, Obj->relas(PltRelSec));
+ return unwrapOrError(FileName,
+ Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
}
}
-template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
- const ELFFile<ELFT> *Obj = ObjF->getELFFile();
- if (Obj->getHeader()->e_machine != EM_MIPS)
- reportError("MIPS PLT GOT is available for MIPS targets only");
-
- MipsGOTParser<ELFT> Parser(Obj, dynamic_table(), dynamic_symbols());
- if (Parser.hasGot())
- ELFDumperStyle->printMipsGOT(Parser);
- if (Parser.hasPlt())
- ELFDumperStyle->printMipsPLT(Parser);
-}
-
static const EnumEntry<unsigned> ElfMipsISAExtType[] = {
{"None", Mips::AFL_EXT_NONE},
{"Broadcom SB-1", Mips::AFL_EXT_SB1},
@@ -2427,41 +2622,6 @@ static int getMipsRegisterSize(uint8_t Flag) {
}
}
-template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() {
- const ELFFile<ELFT> *Obj = ObjF->getELFFile();
- const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags");
- if (!Shdr) {
- W.startLine() << "There is no .MIPS.abiflags section in the file.\n";
- return;
- }
- ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
- if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) {
- W.startLine() << "The .MIPS.abiflags section has a wrong size.\n";
- return;
- }
-
- auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data());
-
- raw_ostream &OS = W.getOStream();
- DictScope GS(W, "MIPS ABI Flags");
-
- W.printNumber("Version", Flags->version);
- W.startLine() << "ISA: ";
- if (Flags->isa_rev <= 1)
- OS << format("MIPS%u", Flags->isa_level);
- else
- OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);
- OS << "\n";
- W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType));
- W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags));
- W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType));
- W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));
- W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));
- W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));
- W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1));
- W.printHex("Flags 2", Flags->flags2);
-}
-
template <class ELFT>
static void printMipsReginfoData(ScopedPrinter &W,
const Elf_Mips_RegInfo<ELFT> &Reginfo) {
@@ -2475,12 +2635,13 @@ static void printMipsReginfoData(ScopedPrinter &W,
template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
- const Elf_Shdr *Shdr = findSectionByName(*Obj, ".reginfo");
+ const Elf_Shdr *Shdr = findSectionByName(*Obj, ObjF->getFileName(), ".reginfo");
if (!Shdr) {
W.startLine() << "There is no .reginfo section in the file.\n";
return;
}
- ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
+ ArrayRef<uint8_t> Sec =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr));
if (Sec.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
W.startLine() << "The .reginfo section has a wrong size.\n";
return;
@@ -2493,7 +2654,8 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
- const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.options");
+ const Elf_Shdr *Shdr =
+ findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.options");
if (!Shdr) {
W.startLine() << "There is no .MIPS.options section in the file.\n";
return;
@@ -2501,7 +2663,8 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
DictScope GS(W, "MIPS Options");
- ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
+ ArrayRef<uint8_t> Sec =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr));
while (!Sec.empty()) {
if (Sec.size() < sizeof(Elf_Mips_Options<ELFT>)) {
W.startLine() << "The .MIPS.options section has a wrong size.\n";
@@ -2524,8 +2687,9 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
const Elf_Shdr *StackMapSection = nullptr;
- for (const auto &Sec : unwrapOrError(Obj->sections())) {
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
+ for (const auto &Sec : unwrapOrError(ObjF->getFileName(), Obj->sections())) {
+ StringRef Name =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionName(&Sec));
if (Name == ".llvm_stackmaps") {
StackMapSection = &Sec;
break;
@@ -2535,8 +2699,8 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
if (!StackMapSection)
return;
- ArrayRef<uint8_t> StackMapContentsArray =
- unwrapOrError(Obj->getSectionContents(StackMapSection));
+ ArrayRef<uint8_t> StackMapContentsArray = unwrapOrError(
+ ObjF->getFileName(), Obj->getSectionContents(StackMapSection));
prettyPrintStackMap(
W, StackMapParser<ELFT::TargetEndianness>(StackMapContentsArray));
@@ -2560,24 +2724,26 @@ static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,
}
template <class ELFT>
-static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj) {
+static std::string getSectionHeadersNumString(const ELFFile<ELFT> *Obj,
+ StringRef FileName) {
const typename ELFT::Ehdr *ElfHeader = Obj->getHeader();
if (ElfHeader->e_shnum != 0)
return to_string(ElfHeader->e_shnum);
- ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections());
+ ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(FileName, Obj->sections());
if (Arr.empty())
return "0";
return "0 (" + to_string(Arr[0].sh_size) + ")";
}
template <class ELFT>
-static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj) {
+static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> *Obj,
+ StringRef FileName) {
const typename ELFT::Ehdr *ElfHeader = Obj->getHeader();
if (ElfHeader->e_shstrndx != SHN_XINDEX)
return to_string(ElfHeader->e_shstrndx);
- ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(Obj->sections());
+ ArrayRef<typename ELFT::Shdr> Arr = unwrapOrError(FileName, Obj->sections());
if (Arr.empty())
return "65535 (corrupt: out of range)";
return to_string(ElfHeader->e_shstrndx) + " (" + to_string(Arr[0].sh_link) +
@@ -2639,9 +2805,9 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
printFields(OS, "Number of program headers:", Str);
Str = to_string(e->e_shentsize) + " (bytes)";
printFields(OS, "Size of section headers:", Str);
- Str = getSectionHeadersNumString(Obj);
+ Str = getSectionHeadersNumString(Obj, this->FileName);
printFields(OS, "Number of section headers:", Str);
- Str = getSectionHeaderTableIndexString(Obj);
+ Str = getSectionHeaderTableIndexString(Obj, this->FileName);
printFields(OS, "Section header string table index:", Str);
}
@@ -2663,26 +2829,29 @@ struct GroupSection {
};
template <class ELFT>
-std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
+std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj,
+ StringRef FileName) {
using Elf_Shdr = typename ELFT::Shdr;
using Elf_Sym = typename ELFT::Sym;
using Elf_Word = typename ELFT::Word;
std::vector<GroupSection> Ret;
uint64_t I = 0;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(FileName, Obj->sections())) {
++I;
if (Sec.sh_type != ELF::SHT_GROUP)
continue;
- const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link));
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
- const Elf_Sym *Sym =
- unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
- auto Data =
- unwrapOrError(Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
+ const Elf_Shdr *Symtab =
+ unwrapOrError(FileName, Obj->getSection(Sec.sh_link));
+ StringRef StrTable =
+ unwrapOrError(FileName, Obj->getStringTableForSymtab(*Symtab));
+ const Elf_Sym *Sym = unwrapOrError(
+ FileName, Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
+ auto Data = unwrapOrError(
+ FileName, Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
+ StringRef Name = unwrapOrError(FileName, Obj->getSectionName(&Sec));
StringRef Signature = StrTable.data() + Sym->st_name;
Ret.push_back({Name,
maybeDemangle(Signature),
@@ -2695,8 +2864,8 @@ std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
std::vector<GroupMember> &GM = Ret.back().Members;
for (uint32_t Ndx : Data.slice(1)) {
- auto Sec = unwrapOrError(Obj->getSection(Ndx));
- const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
+ auto Sec = unwrapOrError(FileName, Obj->getSection(Ndx));
+ const StringRef Name = unwrapOrError(FileName, Obj->getSectionName(Sec));
GM.push_back({Name, Ndx});
}
}
@@ -2715,7 +2884,7 @@ mapSectionsToGroups(ArrayRef<GroupSection> Groups) {
} // namespace
template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
- std::vector<GroupSection> V = getGroups<ELFT>(Obj);
+ std::vector<GroupSection> V = getGroups<ELFT>(Obj, this->FileName);
DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
for (const GroupSection &G : V) {
OS << "\n"
@@ -2745,14 +2914,17 @@ template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
template <class ELFT>
void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
const Elf_Rela &R, bool IsRela) {
- const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab));
+ const Elf_Sym *Sym =
+ unwrapOrError(this->FileName, Obj->getRelocationSymbol(&R, SymTab));
std::string TargetName;
if (Sym && Sym->getType() == ELF::STT_SECTION) {
const Elf_Shdr *Sec = unwrapOrError(
+ this->FileName,
Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable()));
- TargetName = unwrapOrError(Obj->getSectionName(Sec));
+ TargetName = unwrapOrError(this->FileName, Obj->getSectionName(Sec));
} else if (Sym) {
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
+ StringRef StrTable =
+ unwrapOrError(this->FileName, Obj->getStringTableForSymtab(*SymTab));
TargetName = this->dumper()->getFullSymbolName(
Sym, StrTable, SymTab->sh_type == SHT_DYNSYM /* IsDynamic */);
}
@@ -2821,21 +2993,21 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) {
template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
bool HasRelocSections = false;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(this->FileName, Obj->sections())) {
if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL &&
Sec.sh_type != ELF::SHT_ANDROID_RELA &&
Sec.sh_type != ELF::SHT_ANDROID_RELR)
continue;
HasRelocSections = true;
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
+ StringRef Name = unwrapOrError(this->FileName, Obj->getSectionName(&Sec));
unsigned Entries = Sec.getEntityCount();
std::vector<Elf_Rela> AndroidRelas;
if (Sec.sh_type == ELF::SHT_ANDROID_REL ||
Sec.sh_type == ELF::SHT_ANDROID_RELA) {
// Android's packed relocation section needs to be unpacked first
// to get the actual number of entries.
- AndroidRelas = unwrapOrError(Obj->android_relas(&Sec));
+ AndroidRelas = unwrapOrError(this->FileName, Obj->android_relas(&Sec));
Entries = AndroidRelas.size();
}
std::vector<Elf_Rela> RelrRelas;
@@ -2843,8 +3015,8 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
Sec.sh_type == ELF::SHT_ANDROID_RELR)) {
// .relr.dyn relative relocation section needs to be unpacked first
// to get the actual number of entries.
- Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec));
- RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ Elf_Relr_Range Relrs = unwrapOrError(this->FileName, Obj->relrs(&Sec));
+ RelrRelas = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
Entries = RelrRelas.size();
}
uintX_t Offset = Sec.sh_offset;
@@ -2852,10 +3024,11 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
<< to_hexString(Offset, false) << " contains " << Entries
<< " entries:\n";
printRelocHeader(Sec.sh_type);
- const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link));
+ const Elf_Shdr *SymTab =
+ unwrapOrError(this->FileName, Obj->getSection(Sec.sh_link));
switch (Sec.sh_type) {
case ELF::SHT_REL:
- for (const auto &R : unwrapOrError(Obj->rels(&Sec))) {
+ for (const auto &R : unwrapOrError(this->FileName, Obj->rels(&Sec))) {
Elf_Rela Rela;
Rela.r_offset = R.r_offset;
Rela.r_info = R.r_info;
@@ -2864,13 +3037,13 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
}
break;
case ELF::SHT_RELA:
- for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
+ for (const auto &R : unwrapOrError(this->FileName, Obj->relas(&Sec)))
printRelocation(Obj, SymTab, R, true);
break;
case ELF::SHT_RELR:
case ELF::SHT_ANDROID_RELR:
if (opts::RawRelr)
- for (const auto &R : unwrapOrError(Obj->relrs(&Sec)))
+ for (const auto &R : unwrapOrError(this->FileName, Obj->relrs(&Sec)))
OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8))
<< "\n";
else
@@ -2992,6 +3165,12 @@ static std::string getSectionTypeString(unsigned Arch, unsigned Type) {
return "LLVM_ADDRSIG";
case SHT_LLVM_DEPENDENT_LIBRARIES:
return "LLVM_DEPENDENT_LIBRARIES";
+ case SHT_LLVM_SYMPART:
+ return "LLVM_SYMPART";
+ case SHT_LLVM_PART_EHDR:
+ return "LLVM_PART_EHDR";
+ case SHT_LLVM_PART_PHDR:
+ return "LLVM_PART_PHDR";
// FIXME: Parse processor specific GNU attributes
case SHT_GNU_ATTRIBUTES:
return "ATTRIBUTES";
@@ -3010,29 +3189,9 @@ static std::string getSectionTypeString(unsigned Arch, unsigned Type) {
}
template <class ELFT>
-static StringRef getSectionName(const typename ELFT::Shdr &Sec,
- const ELFObjectFile<ELFT> &ElfObj,
- ArrayRef<typename ELFT::Shdr> Sections) {
- const ELFFile<ELFT> &Obj = *ElfObj.getELFFile();
- uint32_t Index = Obj.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())
- reportError(ElfObj.getFileName(),
- createError("section header string table index " +
- Twine(Index) + " does not exist"));
- StringRef Data = toStringRef(unwrapOrError(
- Obj.template getSectionContentsAsArray<uint8_t>(&Sections[Index])));
- return unwrapOrError(Obj.getSectionName(&Sec, Data));
-}
-
-template <class ELFT>
void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
unsigned Bias = ELFT::Is64Bits ? 0 : 8;
- ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
+ ArrayRef<Elf_Shdr> Sections = unwrapOrError(this->FileName, Obj->sections());
OS << "There are " << to_string(Sections.size())
<< " section headers, starting at offset "
<< "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n";
@@ -3050,7 +3209,8 @@ void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
size_t SectionIndex = 0;
for (const Elf_Shdr &Sec : Sections) {
Fields[0].Str = to_string(SectionIndex);
- Fields[1].Str = getSectionName(Sec, *ElfObj, Sections);
+ Fields[1].Str = unwrapOrError<StringRef>(
+ ElfObj->getFileName(), Obj->getSectionName(&Sec, this->WarningHandler));
Fields[2].Str =
getSectionTypeString(Obj->getHeader()->e_machine, Sec.sh_type);
Fields[3].Str =
@@ -3089,7 +3249,8 @@ void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
template <class ELFT>
void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name,
- size_t Entries) {
+ size_t Entries,
+ bool NonVisibilityBitsUsed) {
if (!Name.empty())
OS << "\nSymbol table '" << Name << "' contains " << Entries
<< " entries:\n";
@@ -3097,9 +3258,13 @@ void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name,
OS << "\n Symbol table for image:\n";
if (ELFT::Is64Bits)
- OS << " Num: Value Size Type Bind Vis Ndx Name\n";
+ OS << " Num: Value Size Type Bind Vis";
else
- OS << " Num: Value Size Type Bind Vis Ndx Name\n";
+ OS << " Num: Value Size Type Bind Vis";
+
+ if (NonVisibilityBitsUsed)
+ OS << " ";
+ OS << " Ndx Name\n";
}
template <class ELFT>
@@ -3115,10 +3280,11 @@ std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj,
case ELF::SHN_COMMON:
return "COM";
case ELF::SHN_XINDEX:
- return to_string(
- format_decimal(unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>(
- Symbol, FirstSym, this->dumper()->getShndxTable())),
- 3));
+ return to_string(format_decimal(
+ unwrapOrError(this->FileName,
+ object::getExtendedSymbolTableIndex<ELFT>(
+ Symbol, FirstSym, this->dumper()->getShndxTable())),
+ 3));
default:
// Find if:
// Processor specific
@@ -3142,7 +3308,7 @@ std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj,
template <class ELFT>
void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
const Elf_Sym *FirstSym, StringRef StrTable,
- bool IsDynamic) {
+ bool IsDynamic, bool NonVisibilityBitsUsed) {
static int Idx = 0;
static bool Dynamic = true;
@@ -3156,7 +3322,7 @@ void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias,
- 31 + Bias, 38 + Bias, 47 + Bias, 51 + Bias};
+ 31 + Bias, 38 + Bias, 48 + Bias, 51 + Bias};
Fields[0].Str = to_string(format_decimal(Idx++, 6)) + ":";
Fields[1].Str = to_string(
format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8));
@@ -3173,7 +3339,13 @@ void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
Fields[5].Str =
printEnum(Symbol->getVisibility(), makeArrayRef(ElfSymbolVisibilities));
+ if (Symbol->st_other & ~0x3)
+ Fields[5].Str +=
+ " [<other: " + to_string(format_hex(Symbol->st_other, 2)) + ">]";
+
+ Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;
Fields[6].Str = getSymbolSectionNdx(Obj, Symbol, FirstSym);
+
Fields[7].Str =
this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic);
for (auto &Entry : Fields)
@@ -3193,7 +3365,7 @@ void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym,
const auto Symbol = FirstSym + Sym;
Fields[2].Str = to_string(
- format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 18 : 8));
+ format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8));
Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5));
unsigned char SymbolType = Symbol->getType();
@@ -3246,10 +3418,21 @@ template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
for (uint32_t Buc = 0; Buc < SysVHash->nbucket; Buc++) {
if (Buckets[Buc] == ELF::STN_UNDEF)
continue;
+ std::vector<bool> Visited(SysVHash->nchain);
for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash->nchain; Ch = Chains[Ch]) {
if (Ch == ELF::STN_UNDEF)
break;
+
+ if (Visited[Ch]) {
+ reportWarning(
+ createError(".hash section is invalid: bucket " + Twine(Ch) +
+ ": a cycle was detected in the linked chain"),
+ this->FileName);
+ break;
+ }
+
printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc);
+ Visited[Ch] = true;
}
}
}
@@ -3380,7 +3563,8 @@ void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
unsigned Width = ELFT::Is64Bits ? 18 : 10;
unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7;
- for (const auto &Phdr : unwrapOrError(Obj->program_headers())) {
+ for (const auto &Phdr :
+ unwrapOrError(this->FileName, Obj->program_headers())) {
Fields[0].Str = getElfPtType(Header->e_machine, Phdr.p_type);
Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8));
Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width));
@@ -3404,10 +3588,11 @@ void GNUStyle<ELFT>::printSectionMapping(const ELFO *Obj) {
OS << "\n Section to Segment mapping:\n Segment Sections...\n";
DenseSet<const Elf_Shdr *> BelongsToSegment;
int Phnum = 0;
- for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
+ for (const Elf_Phdr &Phdr :
+ unwrapOrError(this->FileName, Obj->program_headers())) {
std::string Sections;
OS << format(" %2.2d ", Phnum++);
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(this->FileName, Obj->sections())) {
// Check if each section is in a segment and then print mapping.
// readelf additionally makes sure it does not print zero sized sections
// at end of segments and for PT_DYNAMIC both start and end of section
@@ -3418,7 +3603,9 @@ void GNUStyle<ELFT>::printSectionMapping(const ELFO *Obj) {
if (!TbssInNonTLS && checkTLSSections(Phdr, Sec) &&
checkoffsets(Phdr, Sec) && checkVMA(Phdr, Sec) &&
checkPTDynamic(Phdr, Sec) && (Sec.sh_type != ELF::SHT_NULL)) {
- Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + " ";
+ Sections +=
+ unwrapOrError(this->FileName, Obj->getSectionName(&Sec)).str() +
+ " ";
BelongsToSegment.insert(&Sec);
}
}
@@ -3428,9 +3615,10 @@ void GNUStyle<ELFT>::printSectionMapping(const ELFO *Obj) {
// Display sections that do not belong to a segment.
std::string Sections;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(this->FileName, Obj->sections())) {
if (BelongsToSegment.find(&Sec) == BelongsToSegment.end())
- Sections += unwrapOrError(Obj->getSectionName(&Sec)).str() + ' ';
+ Sections +=
+ unwrapOrError(this->FileName, Obj->getSectionName(&Sec)).str() + ' ';
}
if (!Sections.empty()) {
OS << " None " << Sections << '\n';
@@ -3438,14 +3626,40 @@ void GNUStyle<ELFT>::printSectionMapping(const ELFO *Obj) {
}
}
+namespace {
+template <class ELFT> struct RelSymbol {
+ const typename ELFT::Sym *Sym;
+ std::string Name;
+};
+
+template <class ELFT>
+RelSymbol<ELFT> getSymbolForReloc(const ELFFile<ELFT> *Obj, StringRef FileName,
+ const ELFDumper<ELFT> *Dumper,
+ const typename ELFT::Rela &Reloc) {
+ uint32_t SymIndex = Reloc.getSymbol(Obj->isMips64EL());
+ const typename ELFT::Sym *Sym = Dumper->dynamic_symbols().begin() + SymIndex;
+ Expected<StringRef> ErrOrName = Sym->getName(Dumper->getDynamicStringTable());
+
+ std::string Name;
+ if (ErrOrName) {
+ Name = maybeDemangle(*ErrOrName);
+ } else {
+ reportWarning(
+ createError("unable to get name of the dynamic symbol with index " +
+ Twine(SymIndex) + ": " + toString(ErrOrName.takeError())),
+ FileName);
+ Name = "<corrupt>";
+ }
+
+ return {Sym, std::move(Name)};
+}
+} // namespace
+
template <class ELFT>
void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela R,
bool IsRela) {
- uint32_t SymIndex = R.getSymbol(Obj->isMips64EL());
- const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex;
- std::string SymbolName = maybeDemangle(
- unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())));
- printRelocation(Obj, Sym, SymbolName, R, IsRela);
+ RelSymbol<ELFT> S = getSymbolForReloc(Obj, this->FileName, this->dumper(), R);
+ printRelocation(Obj, S.Sym, S.Name, R, IsRela);
}
template <class ELFT> void GNUStyle<ELFT>::printDynamic(const ELFO *Obj) {
@@ -3518,7 +3732,8 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
<< " contains " << DynRelrRegion.Size << " bytes:\n";
printRelocHeader(ELF::SHT_REL);
Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
- std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ std::vector<Elf_Rela> RelrRelas =
+ unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
for (const Elf_Rela &Rela : RelrRelas) {
printDynamicRelocation(Obj, Rela, false);
}
@@ -3550,14 +3765,15 @@ template <class ELFT>
static void printGNUVersionSectionProlog(formatted_raw_ostream &OS,
const Twine &Name, unsigned EntriesNum,
const ELFFile<ELFT> *Obj,
- const typename ELFT::Shdr *Sec) {
- StringRef SecName = unwrapOrError(Obj->getSectionName(Sec));
+ const typename ELFT::Shdr *Sec,
+ StringRef FileName) {
+ StringRef SecName = unwrapOrError(FileName, Obj->getSectionName(Sec));
OS << Name << " section '" << SecName << "' "
<< "contains " << EntriesNum << " entries:\n";
const typename ELFT::Shdr *SymTab =
- unwrapOrError(Obj->getSection(Sec->sh_link));
- StringRef SymTabName = unwrapOrError(Obj->getSectionName(SymTab));
+ unwrapOrError(FileName, Obj->getSection(Sec->sh_link));
+ StringRef SymTabName = unwrapOrError(FileName, Obj->getSectionName(SymTab));
OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16)
<< " Offset: " << format_hex(Sec->sh_offset, 8)
<< " Link: " << Sec->sh_link << " (" << SymTabName << ")\n";
@@ -3570,7 +3786,8 @@ void GNUStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
return;
unsigned Entries = Sec->sh_size / sizeof(Elf_Versym);
- printGNUVersionSectionProlog(OS, "Version symbols", Entries, Obj, Sec);
+ printGNUVersionSectionProlog(OS, "Version symbols", Entries, Obj, Sec,
+ this->FileName);
const uint8_t *VersymBuf =
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
@@ -3642,14 +3859,17 @@ void GNUStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
return;
unsigned VerDefsNum = Sec->sh_info;
- printGNUVersionSectionProlog(OS, "Version definition", VerDefsNum, Obj, Sec);
+ printGNUVersionSectionProlog(OS, "Version definition", VerDefsNum, Obj, Sec,
+ this->FileName);
- const Elf_Shdr *StrTabSec = unwrapOrError(Obj->getSection(Sec->sh_link));
+ const Elf_Shdr *StrTabSec =
+ unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
StringRef StringTable(
reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
(size_t)StrTabSec->sh_size);
- const uint8_t *VerdefBuf = unwrapOrError(Obj->getSectionContents(Sec)).data();
+ const uint8_t *VerdefBuf =
+ unwrapOrError(this->FileName, Obj->getSectionContents(Sec)).data();
const uint8_t *Begin = VerdefBuf;
while (VerDefsNum--) {
@@ -3684,11 +3904,14 @@ void GNUStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
return;
unsigned VerneedNum = Sec->sh_info;
- printGNUVersionSectionProlog(OS, "Version needs", VerneedNum, Obj, Sec);
+ printGNUVersionSectionProlog(OS, "Version needs", VerneedNum, Obj, Sec,
+ this->FileName);
- ArrayRef<uint8_t> SecData = unwrapOrError(Obj->getSectionContents(Sec));
+ ArrayRef<uint8_t> SecData =
+ unwrapOrError(this->FileName, Obj->getSectionContents(Sec));
- const Elf_Shdr *StrTabSec = unwrapOrError(Obj->getSection(Sec->sh_link));
+ const Elf_Shdr *StrTabSec =
+ unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
StringRef StringTable = {
reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
(size_t)StrTabSec->sh_size};
@@ -3745,9 +3968,21 @@ void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) {
// Go over all buckets and and note chain lengths of each bucket (total
// unique chain lengths).
for (size_t B = 0; B < NBucket; B++) {
- for (size_t C = Buckets[B]; C > 0 && C < NChain; C = Chains[C])
+ std::vector<bool> Visited(NChain);
+ for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {
+ if (C == ELF::STN_UNDEF)
+ break;
+ if (Visited[C]) {
+ reportWarning(
+ createError(".hash section is invalid: bucket " + Twine(C) +
+ ": a cycle was detected in the linked chain"),
+ this->FileName);
+ break;
+ }
+ Visited[C] = true;
if (MaxChain <= ++ChainLen[B])
MaxChain++;
+ }
TotalSyms += ChainLen[B];
}
@@ -3829,7 +4064,7 @@ void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
template <class ELFT>
void GNUStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) {
- OS << "GNUStyle::printAddrsig not implemented\n";
+ reportError(createError("--addrsig: not implemented"), this->FileName);
}
static StringRef getGenericNoteTypeName(const uint32_t NT) {
@@ -3850,6 +4085,86 @@ static StringRef getGenericNoteTypeName(const uint32_t NT) {
return "";
}
+static StringRef getCoreNoteTypeName(const uint32_t NT) {
+ static const struct {
+ uint32_t ID;
+ const char *Name;
+ } Notes[] = {
+ {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"},
+ {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"},
+ {ELF::NT_PRPSINFO, "NT_PRPSINFO (prpsinfo structure)"},
+ {ELF::NT_TASKSTRUCT, "NT_TASKSTRUCT (task structure)"},
+ {ELF::NT_AUXV, "NT_AUXV (auxiliary vector)"},
+ {ELF::NT_PSTATUS, "NT_PSTATUS (pstatus structure)"},
+ {ELF::NT_FPREGS, "NT_FPREGS (floating point registers)"},
+ {ELF::NT_PSINFO, "NT_PSINFO (psinfo structure)"},
+ {ELF::NT_LWPSTATUS, "NT_LWPSTATUS (lwpstatus_t structure)"},
+ {ELF::NT_LWPSINFO, "NT_LWPSINFO (lwpsinfo_t structure)"},
+ {ELF::NT_WIN32PSTATUS, "NT_WIN32PSTATUS (win32_pstatus structure)"},
+
+ {ELF::NT_PPC_VMX, "NT_PPC_VMX (ppc Altivec registers)"},
+ {ELF::NT_PPC_VSX, "NT_PPC_VSX (ppc VSX registers)"},
+ {ELF::NT_PPC_TAR, "NT_PPC_TAR (ppc TAR register)"},
+ {ELF::NT_PPC_PPR, "NT_PPC_PPR (ppc PPR register)"},
+ {ELF::NT_PPC_DSCR, "NT_PPC_DSCR (ppc DSCR register)"},
+ {ELF::NT_PPC_EBB, "NT_PPC_EBB (ppc EBB registers)"},
+ {ELF::NT_PPC_PMU, "NT_PPC_PMU (ppc PMU registers)"},
+ {ELF::NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR (ppc checkpointed GPR registers)"},
+ {ELF::NT_PPC_TM_CFPR,
+ "NT_PPC_TM_CFPR (ppc checkpointed floating point registers)"},
+ {ELF::NT_PPC_TM_CVMX,
+ "NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"},
+ {ELF::NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"},
+ {ELF::NT_PPC_TM_SPR, "NT_PPC_TM_SPR (ppc TM special purpose registers)"},
+ {ELF::NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR (ppc checkpointed TAR register)"},
+ {ELF::NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR (ppc checkpointed PPR register)"},
+ {ELF::NT_PPC_TM_CDSCR,
+ "NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)"},
+
+ {ELF::NT_386_TLS, "NT_386_TLS (x86 TLS information)"},
+ {ELF::NT_386_IOPERM, "NT_386_IOPERM (x86 I/O permissions)"},
+ {ELF::NT_X86_XSTATE, "NT_X86_XSTATE (x86 XSAVE extended state)"},
+
+ {ELF::NT_S390_HIGH_GPRS,
+ "NT_S390_HIGH_GPRS (s390 upper register halves)"},
+ {ELF::NT_S390_TIMER, "NT_S390_TIMER (s390 timer register)"},
+ {ELF::NT_S390_TODCMP, "NT_S390_TODCMP (s390 TOD comparator register)"},
+ {ELF::NT_S390_TODPREG,
+ "NT_S390_TODPREG (s390 TOD programmable register)"},
+ {ELF::NT_S390_CTRS, "NT_S390_CTRS (s390 control registers)"},
+ {ELF::NT_S390_PREFIX, "NT_S390_PREFIX (s390 prefix register)"},
+ {ELF::NT_S390_LAST_BREAK,
+ "NT_S390_LAST_BREAK (s390 last breaking event address)"},
+ {ELF::NT_S390_SYSTEM_CALL,
+ "NT_S390_SYSTEM_CALL (s390 system call restart data)"},
+ {ELF::NT_S390_TDB, "NT_S390_TDB (s390 transaction diagnostic block)"},
+ {ELF::NT_S390_VXRS_LOW,
+ "NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)"},
+ {ELF::NT_S390_VXRS_HIGH,
+ "NT_S390_VXRS_HIGH (s390 vector registers 16-31)"},
+ {ELF::NT_S390_GS_CB, "NT_S390_GS_CB (s390 guarded-storage registers)"},
+ {ELF::NT_S390_GS_BC,
+ "NT_S390_GS_BC (s390 guarded-storage broadcast control)"},
+
+ {ELF::NT_ARM_VFP, "NT_ARM_VFP (arm VFP registers)"},
+ {ELF::NT_ARM_TLS, "NT_ARM_TLS (AArch TLS registers)"},
+ {ELF::NT_ARM_HW_BREAK,
+ "NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"},
+ {ELF::NT_ARM_HW_WATCH,
+ "NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"},
+
+ {ELF::NT_FILE, "NT_FILE (mapped files)"},
+ {ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"},
+ {ELF::NT_SIGINFO, "NT_SIGINFO (siginfo_t data)"},
+ };
+
+ for (const auto &Note : Notes)
+ if (Note.ID == NT)
+ return Note.Name;
+
+ return "";
+}
+
static std::string getGNUNoteTypeName(const uint32_t NT) {
static const struct {
uint32_t ID;
@@ -4207,13 +4522,85 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
}
}
+struct CoreFileMapping {
+ uint64_t Start, End, Offset;
+ StringRef Filename;
+};
+
+struct CoreNote {
+ uint64_t PageSize;
+ std::vector<CoreFileMapping> Mappings;
+};
+
+static Expected<CoreNote> readCoreNote(DataExtractor Desc) {
+ // Expected format of the NT_FILE note description:
+ // 1. # of file mappings (call it N)
+ // 2. Page size
+ // 3. N (start, end, offset) triples
+ // 4. N packed filenames (null delimited)
+ // Each field is an Elf_Addr, except for filenames which are char* strings.
+
+ CoreNote Ret;
+ const int Bytes = Desc.getAddressSize();
+
+ if (!Desc.isValidOffsetForAddress(2))
+ return createStringError(object_error::parse_failed,
+ "malformed note: header too short");
+ if (Desc.getData().back() != 0)
+ return createStringError(object_error::parse_failed,
+ "malformed note: not NUL terminated");
+
+ uint64_t DescOffset = 0;
+ uint64_t FileCount = Desc.getAddress(&DescOffset);
+ Ret.PageSize = Desc.getAddress(&DescOffset);
+
+ if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes))
+ return createStringError(object_error::parse_failed,
+ "malformed note: too short for number of files");
+
+ uint64_t FilenamesOffset = 0;
+ DataExtractor Filenames(
+ Desc.getData().drop_front(DescOffset + 3 * FileCount * Bytes),
+ Desc.isLittleEndian(), Desc.getAddressSize());
+
+ Ret.Mappings.resize(FileCount);
+ for (CoreFileMapping &Mapping : Ret.Mappings) {
+ if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1))
+ return createStringError(object_error::parse_failed,
+ "malformed note: too few filenames");
+ Mapping.Start = Desc.getAddress(&DescOffset);
+ Mapping.End = Desc.getAddress(&DescOffset);
+ Mapping.Offset = Desc.getAddress(&DescOffset);
+ Mapping.Filename = Filenames.getCStrRef(&FilenamesOffset);
+ }
+
+ return Ret;
+}
+
+template <typename ELFT>
+static void printCoreNote(raw_ostream &OS, const CoreNote &Note) {
+ // Length of "0x<address>" string.
+ const int FieldWidth = ELFT::Is64Bits ? 18 : 10;
+
+ OS << " Page size: " << format_decimal(Note.PageSize, 0) << '\n';
+ OS << " " << right_justify("Start", FieldWidth) << " "
+ << right_justify("End", FieldWidth) << " "
+ << right_justify("Page Offset", FieldWidth) << '\n';
+ for (const CoreFileMapping &Mapping : Note.Mappings) {
+ OS << " " << format_hex(Mapping.Start, FieldWidth) << " "
+ << format_hex(Mapping.End, FieldWidth) << " "
+ << format_hex(Mapping.Offset, FieldWidth) << "\n "
+ << Mapping.Filename << '\n';
+ }
+}
+
template <class ELFT>
void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
auto PrintHeader = [&](const typename ELFT::Off Offset,
const typename ELFT::Addr Size) {
OS << "Displaying notes found at file offset " << format_hex(Offset, 10)
<< " with length " << format_hex(Size, 10) << ":\n"
- << " Owner Data size\tDescription\n";
+ << " Owner Data size \tDescription\n";
};
auto ProcessNote = [&](const Elf_Note &Note) {
@@ -4221,55 +4608,81 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
ArrayRef<uint8_t> Descriptor = Note.getDesc();
Elf_Word Type = Note.getType();
- OS << " " << Name << std::string(22 - Name.size(), ' ')
+ // Print the note owner/type.
+ OS << " " << left_justify(Name, 20) << ' '
<< format_hex(Descriptor.size(), 10) << '\t';
-
if (Name == "GNU") {
OS << getGNUNoteTypeName(Type) << '\n';
- printGNUNote<ELFT>(OS, Type, Descriptor);
} else if (Name == "FreeBSD") {
OS << getFreeBSDNoteTypeName(Type) << '\n';
} else if (Name == "AMD") {
OS << getAMDNoteTypeName(Type) << '\n';
+ } else if (Name == "AMDGPU") {
+ OS << getAMDGPUNoteTypeName(Type) << '\n';
+ } else {
+ StringRef NoteType = Obj->getHeader()->e_type == ELF::ET_CORE
+ ? getCoreNoteTypeName(Type)
+ : getGenericNoteTypeName(Type);
+ if (!NoteType.empty())
+ OS << NoteType << '\n';
+ else
+ OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
+ }
+
+ // Print the description, or fallback to printing raw bytes for unknown
+ // owners.
+ if (Name == "GNU") {
+ printGNUNote<ELFT>(OS, Type, Descriptor);
+ } else if (Name == "AMD") {
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
if (!N.Type.empty())
OS << " " << N.Type << ":\n " << N.Value << '\n';
} else if (Name == "AMDGPU") {
- OS << getAMDGPUNoteTypeName(Type) << '\n';
const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
if (!N.Type.empty())
OS << " " << N.Type << ":\n " << N.Value << '\n';
- } else {
- StringRef NoteType = getGenericNoteTypeName(Type);
- if (!NoteType.empty())
- OS << NoteType;
- else
- OS << "Unknown note type: (" << format_hex(Type, 10) << ')';
+ } else if (Name == "CORE") {
+ if (Type == ELF::NT_FILE) {
+ DataExtractor DescExtractor(Descriptor,
+ ELFT::TargetEndianness == support::little,
+ sizeof(Elf_Addr));
+ Expected<CoreNote> Note = readCoreNote(DescExtractor);
+ if (Note)
+ printCoreNote<ELFT>(OS, *Note);
+ else
+ reportWarning(Note.takeError(), this->FileName);
+ }
+ } else if (!Descriptor.empty()) {
+ OS << " description data:";
+ for (uint8_t B : Descriptor)
+ OS << " " << format("%02x", B);
+ OS << '\n';
}
- OS << '\n';
};
- if (Obj->getHeader()->e_type == ELF::ET_CORE) {
- for (const auto &P : unwrapOrError(Obj->program_headers())) {
- if (P.p_type != PT_NOTE)
+ ArrayRef<Elf_Shdr> Sections = unwrapOrError(this->FileName, Obj->sections());
+ if (Obj->getHeader()->e_type != ELF::ET_CORE && !Sections.empty()) {
+ for (const auto &S : Sections) {
+ if (S.sh_type != SHT_NOTE)
continue;
- PrintHeader(P.p_offset, P.p_filesz);
+ PrintHeader(S.sh_offset, S.sh_size);
Error Err = Error::success();
- for (const auto &Note : Obj->notes(P, Err))
+ for (const auto &Note : Obj->notes(S, Err))
ProcessNote(Note);
if (Err)
- error(std::move(Err));
+ reportError(std::move(Err), this->FileName);
}
} else {
- for (const auto &S : unwrapOrError(Obj->sections())) {
- if (S.sh_type != SHT_NOTE)
+ for (const auto &P :
+ unwrapOrError(this->FileName, Obj->program_headers())) {
+ if (P.p_type != PT_NOTE)
continue;
- PrintHeader(S.sh_offset, S.sh_size);
+ PrintHeader(P.p_offset, P.p_filesz);
Error Err = Error::success();
- for (const auto &Note : Obj->notes(S, Err))
+ for (const auto &Note : Obj->notes(P, Err))
ProcessNote(Note);
if (Err)
- error(std::move(Err));
+ reportError(std::move(Err), this->FileName);
}
}
}
@@ -4279,6 +4692,294 @@ void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
OS << "printELFLinkerOptions not implemented!\n";
}
+// Used for printing section names in places where possible errors can be
+// ignored.
+static StringRef getSectionName(const SectionRef &Sec) {
+ Expected<StringRef> NameOrErr = Sec.getName();
+ if (NameOrErr)
+ return *NameOrErr;
+ consumeError(NameOrErr.takeError());
+ return "<?>";
+}
+
+// Used for printing symbol names in places where possible errors can be
+// ignored.
+static std::string getSymbolName(const ELFSymbolRef &Sym) {
+ Expected<StringRef> NameOrErr = Sym.getName();
+ if (NameOrErr)
+ return maybeDemangle(*NameOrErr);
+ consumeError(NameOrErr.takeError());
+ return "<?>";
+}
+
+template <class ELFT>
+void DumpStyle<ELFT>::printFunctionStackSize(
+ const ELFObjectFile<ELFT> *Obj, uint64_t SymValue, SectionRef FunctionSec,
+ const StringRef SectionName, DataExtractor Data, uint64_t *Offset) {
+ // This function ignores potentially erroneous input, unless it is directly
+ // related to stack size reporting.
+ SymbolRef FuncSym;
+ for (const ELFSymbolRef &Symbol : Obj->symbols()) {
+ Expected<uint64_t> SymAddrOrErr = Symbol.getAddress();
+ if (!SymAddrOrErr) {
+ consumeError(SymAddrOrErr.takeError());
+ continue;
+ }
+ if (Symbol.getELFType() == ELF::STT_FUNC && *SymAddrOrErr == SymValue) {
+ // Check if the symbol is in the right section.
+ if (FunctionSec.containsSymbol(Symbol)) {
+ FuncSym = Symbol;
+ break;
+ }
+ }
+ }
+
+ std::string FuncName = "?";
+ // A valid SymbolRef has a non-null object file pointer.
+ if (FuncSym.BasicSymbolRef::getObject())
+ FuncName = getSymbolName(FuncSym);
+ else
+ reportWarning(
+ createError("could not identify function symbol for stack size entry"),
+ Obj->getFileName());
+
+ // Extract the size. The expectation is that Offset is pointing to the right
+ // place, i.e. past the function address.
+ uint64_t PrevOffset = *Offset;
+ uint64_t StackSize = Data.getULEB128(Offset);
+ // getULEB128() does not advance Offset if it is not able to extract a valid
+ // integer.
+ if (*Offset == PrevOffset)
+ reportError(
+ createStringError(object_error::parse_failed,
+ "could not extract a valid stack size in section %s",
+ SectionName.data()),
+ Obj->getFileName());
+
+ printStackSizeEntry(StackSize, FuncName);
+}
+
+template <class ELFT>
+void GNUStyle<ELFT>::printStackSizeEntry(uint64_t Size, StringRef FuncName) {
+ OS.PadToColumn(2);
+ OS << format_decimal(Size, 11);
+ OS.PadToColumn(18);
+ OS << FuncName << "\n";
+}
+
+template <class ELFT>
+void DumpStyle<ELFT>::printStackSize(const ELFObjectFile<ELFT> *Obj,
+ RelocationRef Reloc,
+ SectionRef FunctionSec,
+ const StringRef &StackSizeSectionName,
+ const RelocationResolver &Resolver,
+ DataExtractor Data) {
+ // This function ignores potentially erroneous input, unless it is directly
+ // related to stack size reporting.
+ object::symbol_iterator RelocSym = Reloc.getSymbol();
+ uint64_t RelocSymValue = 0;
+ StringRef FileStr = Obj->getFileName();
+ if (RelocSym != Obj->symbol_end()) {
+ // Ensure that the relocation symbol is in the function section, i.e. the
+ // section where the functions whose stack sizes we are reporting are
+ // located.
+ auto SectionOrErr = RelocSym->getSection();
+ if (!SectionOrErr) {
+ reportWarning(
+ createError("cannot identify the section for relocation symbol '" +
+ getSymbolName(*RelocSym) + "'"),
+ FileStr);
+ consumeError(SectionOrErr.takeError());
+ } else if (*SectionOrErr != FunctionSec) {
+ reportWarning(createError("relocation symbol '" +
+ getSymbolName(*RelocSym) +
+ "' is not in the expected section"),
+ FileStr);
+ // Pretend that the symbol is in the correct section and report its
+ // stack size anyway.
+ FunctionSec = **SectionOrErr;
+ }
+
+ Expected<uint64_t> RelocSymValueOrErr = RelocSym->getValue();
+ if (RelocSymValueOrErr)
+ RelocSymValue = *RelocSymValueOrErr;
+ else
+ consumeError(RelocSymValueOrErr.takeError());
+ }
+
+ uint64_t Offset = Reloc.getOffset();
+ if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1))
+ reportError(
+ createStringError(object_error::parse_failed,
+ "found invalid relocation offset into section %s "
+ "while trying to extract a stack size entry",
+ StackSizeSectionName.data()),
+ FileStr);
+
+ uint64_t Addend = Data.getAddress(&Offset);
+ uint64_t SymValue = Resolver(Reloc, RelocSymValue, Addend);
+ this->printFunctionStackSize(Obj, SymValue, FunctionSec, StackSizeSectionName,
+ Data, &Offset);
+}
+
+template <class ELFT>
+void DumpStyle<ELFT>::printNonRelocatableStackSizes(
+ const ELFObjectFile<ELFT> *Obj, std::function<void()> PrintHeader) {
+ // This function ignores potentially erroneous input, unless it is directly
+ // related to stack size reporting.
+ const ELFFile<ELFT> *EF = Obj->getELFFile();
+ StringRef FileStr = Obj->getFileName();
+ for (const SectionRef &Sec : Obj->sections()) {
+ StringRef SectionName = getSectionName(Sec);
+ if (SectionName != ".stack_sizes")
+ continue;
+ PrintHeader();
+ const Elf_Shdr *ElfSec = Obj->getSection(Sec.getRawDataRefImpl());
+ ArrayRef<uint8_t> Contents =
+ unwrapOrError(this->FileName, EF->getSectionContents(ElfSec));
+ DataExtractor Data(Contents, Obj->isLittleEndian(), sizeof(Elf_Addr));
+ // A .stack_sizes section header's sh_link field is supposed to point
+ // to the section that contains the functions whose stack sizes are
+ // described in it.
+ const Elf_Shdr *FunctionELFSec =
+ unwrapOrError(this->FileName, EF->getSection(ElfSec->sh_link));
+ uint64_t Offset = 0;
+ while (Offset < Contents.size()) {
+ // The function address is followed by a ULEB representing the stack
+ // size. Check for an extra byte before we try to process the entry.
+ if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {
+ reportError(
+ createStringError(
+ object_error::parse_failed,
+ "section %s ended while trying to extract a stack size entry",
+ SectionName.data()),
+ FileStr);
+ }
+ uint64_t SymValue = Data.getAddress(&Offset);
+ printFunctionStackSize(Obj, SymValue, Obj->toSectionRef(FunctionELFSec),
+ SectionName, Data, &Offset);
+ }
+ }
+}
+
+template <class ELFT>
+void DumpStyle<ELFT>::printRelocatableStackSizes(
+ const ELFObjectFile<ELFT> *Obj, std::function<void()> PrintHeader) {
+ const ELFFile<ELFT> *EF = Obj->getELFFile();
+
+ // Build a map between stack size sections and their corresponding relocation
+ // sections.
+ llvm::MapVector<SectionRef, SectionRef> StackSizeRelocMap;
+ const SectionRef NullSection{};
+
+ for (const SectionRef &Sec : Obj->sections()) {
+ StringRef SectionName;
+ if (Expected<StringRef> NameOrErr = Sec.getName())
+ SectionName = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
+
+ // A stack size section that we haven't encountered yet is mapped to the
+ // null section until we find its corresponding relocation section.
+ if (SectionName == ".stack_sizes")
+ if (StackSizeRelocMap.count(Sec) == 0) {
+ StackSizeRelocMap[Sec] = NullSection;
+ continue;
+ }
+
+ // Check relocation sections if they are relocating contents of a
+ // stack sizes section.
+ const Elf_Shdr *ElfSec = Obj->getSection(Sec.getRawDataRefImpl());
+ uint32_t SectionType = ElfSec->sh_type;
+ if (SectionType != ELF::SHT_RELA && SectionType != ELF::SHT_REL)
+ continue;
+
+ Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();
+ if (!RelSecOrErr)
+ reportError(createStringError(object_error::parse_failed,
+ "%s: failed to get a relocated section: %s",
+ SectionName.data(),
+ toString(RelSecOrErr.takeError()).c_str()),
+ Obj->getFileName());
+
+ const Elf_Shdr *ContentsSec =
+ Obj->getSection((*RelSecOrErr)->getRawDataRefImpl());
+ Expected<StringRef> ContentsSectionNameOrErr =
+ EF->getSectionName(ContentsSec);
+ if (!ContentsSectionNameOrErr) {
+ consumeError(ContentsSectionNameOrErr.takeError());
+ continue;
+ }
+ if (*ContentsSectionNameOrErr != ".stack_sizes")
+ continue;
+ // Insert a mapping from the stack sizes section to its relocation section.
+ StackSizeRelocMap[Obj->toSectionRef(ContentsSec)] = Sec;
+ }
+
+ for (const auto &StackSizeMapEntry : StackSizeRelocMap) {
+ PrintHeader();
+ const SectionRef &StackSizesSec = StackSizeMapEntry.first;
+ const SectionRef &RelocSec = StackSizeMapEntry.second;
+
+ // Warn about stack size sections without a relocation section.
+ StringRef StackSizeSectionName = getSectionName(StackSizesSec);
+ if (RelocSec == NullSection) {
+ reportWarning(createError("section " + StackSizeSectionName +
+ " does not have a corresponding "
+ "relocation section"),
+ Obj->getFileName());
+ continue;
+ }
+
+ // A .stack_sizes section header's sh_link field is supposed to point
+ // to the section that contains the functions whose stack sizes are
+ // described in it.
+ const Elf_Shdr *StackSizesELFSec =
+ Obj->getSection(StackSizesSec.getRawDataRefImpl());
+ const SectionRef FunctionSec = Obj->toSectionRef(unwrapOrError(
+ this->FileName, EF->getSection(StackSizesELFSec->sh_link)));
+
+ bool (*IsSupportedFn)(uint64_t);
+ RelocationResolver Resolver;
+ std::tie(IsSupportedFn, Resolver) = getRelocationResolver(*Obj);
+ auto Contents = unwrapOrError(this->FileName, StackSizesSec.getContents());
+ DataExtractor Data(Contents, Obj->isLittleEndian(), sizeof(Elf_Addr));
+ for (const RelocationRef &Reloc : RelocSec.relocations()) {
+ if (!IsSupportedFn || !IsSupportedFn(Reloc.getType()))
+ reportError(createStringError(
+ object_error::parse_failed,
+ "unsupported relocation type in section %s: %s",
+ getSectionName(RelocSec).data(),
+ EF->getRelocationTypeName(Reloc.getType()).data()),
+ Obj->getFileName());
+ this->printStackSize(Obj, Reloc, FunctionSec, StackSizeSectionName,
+ Resolver, Data);
+ }
+ }
+}
+
+template <class ELFT>
+void GNUStyle<ELFT>::printStackSizes(const ELFObjectFile<ELFT> *Obj) {
+ bool HeaderHasBeenPrinted = false;
+ auto PrintHeader = [&]() {
+ if (HeaderHasBeenPrinted)
+ return;
+ OS << "\nStack Sizes:\n";
+ OS.PadToColumn(9);
+ OS << "Size";
+ OS.PadToColumn(18);
+ OS << "Function\n";
+ HeaderHasBeenPrinted = true;
+ };
+
+ // For non-relocatable objects, look directly for sections whose name starts
+ // with .stack_sizes and process the contents.
+ if (Obj->isRelocatableObject())
+ this->printRelocatableStackSizes(Obj, PrintHeader);
+ else
+ this->printNonRelocatableStackSizes(Obj, PrintHeader);
+}
+
template <class ELFT>
void GNUStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
size_t Bias = ELFT::Is64Bits ? 8 : 0;
@@ -4402,6 +5103,45 @@ void GNUStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
}
}
+template <class ELFT>
+void GNUStyle<ELFT>::printMipsABIFlags(const ELFObjectFile<ELFT> *ObjF) {
+ const ELFFile<ELFT> *Obj = ObjF->getELFFile();
+ const Elf_Shdr *Shdr =
+ findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.abiflags");
+ if (!Shdr)
+ return;
+
+ ArrayRef<uint8_t> Sec =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr));
+ if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>))
+ reportError(createError(".MIPS.abiflags section has a wrong size"),
+ ObjF->getFileName());
+
+ auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data());
+
+ OS << "MIPS ABI Flags Version: " << Flags->version << "\n\n";
+ OS << "ISA: MIPS" << int(Flags->isa_level);
+ if (Flags->isa_rev > 1)
+ OS << "r" << int(Flags->isa_rev);
+ OS << "\n";
+ OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n";
+ OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n";
+ OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n";
+ OS << "FP ABI: " << printEnum(Flags->fp_abi, makeArrayRef(ElfMipsFpABIType))
+ << "\n";
+ OS << "ISA Extension: "
+ << printEnum(Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)) << "\n";
+ if (Flags->ases == 0)
+ OS << "ASEs: None\n";
+ else
+ // FIXME: Print each flag on a separate line.
+ OS << "ASEs: " << printFlags(Flags->ases, makeArrayRef(ElfMipsASEFlags))
+ << "\n";
+ OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n";
+ OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n";
+ OS << "\n";
+}
+
template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
const Elf_Ehdr *E = Obj->getHeader();
{
@@ -4455,16 +5195,17 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
W.printNumber("ProgramHeaderEntrySize", E->e_phentsize);
W.printNumber("ProgramHeaderCount", E->e_phnum);
W.printNumber("SectionHeaderEntrySize", E->e_shentsize);
- W.printString("SectionHeaderCount", getSectionHeadersNumString(Obj));
+ W.printString("SectionHeaderCount",
+ getSectionHeadersNumString(Obj, this->FileName));
W.printString("StringTableSectionIndex",
- getSectionHeaderTableIndexString(Obj));
+ getSectionHeaderTableIndexString(Obj, this->FileName));
}
}
template <class ELFT>
void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) {
DictScope Lists(W, "Groups");
- std::vector<GroupSection> V = getGroups<ELFT>(Obj);
+ std::vector<GroupSection> V = getGroups<ELFT>(Obj, this->FileName);
DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
for (const GroupSection &G : V) {
DictScope D(W, "Group");
@@ -4499,7 +5240,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
ListScope D(W, "Relocations");
int SectionNumber = -1;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Sec : unwrapOrError(this->FileName, Obj->sections())) {
++SectionNumber;
if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
@@ -4508,7 +5249,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
Sec.sh_type != ELF::SHT_ANDROID_RELR)
continue;
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
+ StringRef Name = unwrapOrError(this->FileName, Obj->getSectionName(&Sec));
W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
W.indent();
@@ -4522,11 +5263,12 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
template <class ELFT>
void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
- const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link));
+ const Elf_Shdr *SymTab =
+ unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
switch (Sec->sh_type) {
case ELF::SHT_REL:
- for (const Elf_Rel &R : unwrapOrError(Obj->rels(Sec))) {
+ for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(Sec))) {
Elf_Rela Rela;
Rela.r_offset = R.r_offset;
Rela.r_info = R.r_info;
@@ -4535,17 +5277,18 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
}
break;
case ELF::SHT_RELA:
- for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec)))
+ for (const Elf_Rela &R : unwrapOrError(this->FileName, Obj->relas(Sec)))
printRelocation(Obj, R, SymTab);
break;
case ELF::SHT_RELR:
case ELF::SHT_ANDROID_RELR: {
- Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec));
+ Elf_Relr_Range Relrs = unwrapOrError(this->FileName, Obj->relrs(Sec));
if (opts::RawRelr) {
for (const Elf_Relr &R : Relrs)
W.startLine() << W.hex(R) << "\n";
} else {
- std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ std::vector<Elf_Rela> RelrRelas =
+ unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
for (const Elf_Rela &R : RelrRelas)
printRelocation(Obj, R, SymTab);
}
@@ -4553,7 +5296,8 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
}
case ELF::SHT_ANDROID_REL:
case ELF::SHT_ANDROID_RELA:
- for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec)))
+ for (const Elf_Rela &R :
+ unwrapOrError(this->FileName, Obj->android_relas(Sec)))
printRelocation(Obj, R, SymTab);
break;
}
@@ -4565,13 +5309,16 @@ void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel,
SmallString<32> RelocName;
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
std::string TargetName;
- const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab));
+ const Elf_Sym *Sym =
+ unwrapOrError(this->FileName, Obj->getRelocationSymbol(&Rel, SymTab));
if (Sym && Sym->getType() == ELF::STT_SECTION) {
const Elf_Shdr *Sec = unwrapOrError(
+ this->FileName,
Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable()));
- TargetName = unwrapOrError(Obj->getSectionName(Sec));
+ TargetName = unwrapOrError(this->FileName, Obj->getSectionName(Sec));
} else if (Sym) {
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab));
+ StringRef StrTable =
+ unwrapOrError(this->FileName, Obj->getStringTableForSymtab(*SymTab));
TargetName = this->dumper()->getFullSymbolName(
Sym, StrTable, SymTab->sh_type == SHT_DYNSYM /* IsDynamic */);
}
@@ -4596,10 +5343,11 @@ void LLVMStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
ListScope SectionsD(W, "Sections");
int SectionIndex = -1;
- ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
+ ArrayRef<Elf_Shdr> Sections = unwrapOrError(this->FileName, Obj->sections());
const ELFObjectFile<ELFT> *ElfObj = this->dumper()->getElfObject();
for (const Elf_Shdr &Sec : Sections) {
- StringRef Name = getSectionName(Sec, *ElfObj, Sections);
+ StringRef Name = unwrapOrError(
+ ElfObj->getFileName(), Obj->getSectionName(&Sec, this->WarningHandler));
DictScope SectionD(W, "Section");
W.printNumber("Index", ++SectionIndex);
W.printNumber("Name", Name, Sec.sh_name);
@@ -4652,19 +5400,25 @@ void LLVMStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
if (opts::SectionSymbols) {
ListScope D(W, "Symbols");
const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec();
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
+ StringRef StrTable =
+ unwrapOrError(this->FileName, Obj->getStringTableForSymtab(*Symtab));
- for (const Elf_Sym &Sym : unwrapOrError(Obj->symbols(Symtab))) {
+ for (const Elf_Sym &Sym :
+ unwrapOrError(this->FileName, Obj->symbols(Symtab))) {
const Elf_Shdr *SymSec = unwrapOrError(
+ this->FileName,
Obj->getSection(&Sym, Symtab, this->dumper()->getShndxTable()));
if (SymSec == &Sec)
- printSymbol(Obj, &Sym, unwrapOrError(Obj->symbols(Symtab)).begin(),
- StrTable, false);
+ printSymbol(
+ Obj, &Sym,
+ unwrapOrError(this->FileName, Obj->symbols(Symtab)).begin(),
+ StrTable, false, false);
}
}
if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) {
- ArrayRef<uint8_t> Data = unwrapOrError(Obj->getSectionContents(&Sec));
+ ArrayRef<uint8_t> Data =
+ unwrapOrError(this->FileName, Obj->getSectionContents(&Sec));
W.printBinaryBlock(
"SectionData",
StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()));
@@ -4675,7 +5429,8 @@ void LLVMStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
template <class ELFT>
void LLVMStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
const Elf_Sym *First, StringRef StrTable,
- bool IsDynamic) {
+ bool IsDynamic,
+ bool /*NonVisibilityBitsUsed*/) {
unsigned SectionIndex = 0;
StringRef SectionName;
this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex);
@@ -4786,7 +5541,8 @@ void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
}
if (DynRelrRegion.Size > 0) {
Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
- std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
+ std::vector<Elf_Rela> RelrRelas =
+ unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
for (const Elf_Rela &Rela : RelrRelas)
printDynamicRelocation(Obj, Rela);
}
@@ -4809,11 +5565,9 @@ template <class ELFT>
void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) {
SmallString<32> RelocName;
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
- std::string SymbolName;
- uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
- const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex;
- SymbolName = maybeDemangle(
- unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())));
+ std::string SymbolName =
+ getSymbolForReloc(Obj, this->FileName, this->dumper(), Rel).Name;
+
if (opts::ExpandRelocs) {
DictScope Group(W, "Relocation");
W.printHex("Offset", Rel.r_offset);
@@ -4842,7 +5596,8 @@ template <class ELFT>
void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
ListScope L(W, "ProgramHeaders");
- for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
+ for (const Elf_Phdr &Phdr :
+ unwrapOrError(this->FileName, Obj->program_headers())) {
DictScope P(W, "ProgramHeader");
W.printHex("Type",
getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
@@ -4860,23 +5615,16 @@ void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) {
template <class ELFT>
void LLVMStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
const Elf_Shdr *Sec) {
- DictScope SS(W, "Version symbols");
+ ListScope SS(W, "VersionSymbols");
if (!Sec)
return;
- StringRef SecName = unwrapOrError(Obj->getSectionName(Sec));
- W.printNumber("Section Name", SecName, Sec->sh_name);
- W.printHex("Address", Sec->sh_addr);
- W.printHex("Offset", Sec->sh_offset);
- W.printNumber("Link", Sec->sh_link);
-
const uint8_t *VersymBuf =
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
const ELFDumper<ELFT> *Dumper = this->dumper();
StringRef StrTable = Dumper->getDynamicStringTable();
// Same number of entries in the dynamic symbol table (DT_SYMTAB).
- ListScope Syms(W, "Symbols");
for (const Elf_Sym &Sym : Dumper->dynamic_symbols()) {
DictScope S(W, "Symbol");
const Elf_Versym *Versym = reinterpret_cast<const Elf_Versym *>(VersymBuf);
@@ -4891,7 +5639,7 @@ void LLVMStyle<ELFT>::printVersionSymbolSection(const ELFFile<ELFT> *Obj,
template <class ELFT>
void LLVMStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
const Elf_Shdr *Sec) {
- DictScope SD(W, "SHT_GNU_verdef");
+ ListScope SD(W, "VersionDefinitions");
if (!Sec)
return;
@@ -4899,7 +5647,8 @@ void LLVMStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size;
const uint8_t *VerdefBuf = SecStartAddress;
- const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link));
+ const Elf_Shdr *StrTab =
+ unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
unsigned VerDefsNum = Sec->sh_info;
while (VerDefsNum--) {
@@ -4938,13 +5687,14 @@ void LLVMStyle<ELFT>::printVersionDefinitionSection(const ELFFile<ELFT> *Obj,
template <class ELFT>
void LLVMStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
const Elf_Shdr *Sec) {
- DictScope SD(W, "SHT_GNU_verneed");
+ ListScope SD(W, "VersionRequirements");
if (!Sec)
return;
const uint8_t *SecData =
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
- const Elf_Shdr *StrTab = unwrapOrError(Obj->getSection(Sec->sh_link));
+ const Elf_Shdr *StrTab =
+ unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
const uint8_t *VerneedBuf = SecData;
unsigned VerneedNum = Sec->sh_info;
@@ -4986,37 +5736,62 @@ void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
ListScope L(W, "CGProfile");
if (!this->dumper()->getDotCGProfileSec())
return;
- auto CGProfile =
- unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>(
- this->dumper()->getDotCGProfileSec()));
+ auto CGProfile = unwrapOrError(
+ this->FileName, Obj->template getSectionContentsAsArray<Elf_CGProfile>(
+ this->dumper()->getDotCGProfileSec()));
for (const Elf_CGProfile &CGPE : CGProfile) {
DictScope D(W, "CGProfileEntry");
- W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from),
- CGPE.cgp_from);
- W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to),
- CGPE.cgp_to);
+ W.printNumber(
+ "From",
+ unwrapOrError(this->FileName,
+ this->dumper()->getStaticSymbolName(CGPE.cgp_from)),
+ CGPE.cgp_from);
+ W.printNumber(
+ "To",
+ unwrapOrError(this->FileName,
+ this->dumper()->getStaticSymbolName(CGPE.cgp_to)),
+ CGPE.cgp_to);
W.printNumber("Weight", CGPE.cgp_weight);
}
}
+static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) {
+ std::vector<uint64_t> Ret;
+ const uint8_t *Cur = Data.begin();
+ const uint8_t *End = Data.end();
+ while (Cur != End) {
+ unsigned Size;
+ const char *Err;
+ Ret.push_back(decodeULEB128(Cur, &Size, End, &Err));
+ if (Err)
+ return createError(Err);
+ Cur += Size;
+ }
+ return Ret;
+}
+
template <class ELFT>
void LLVMStyle<ELFT>::printAddrsig(const ELFFile<ELFT> *Obj) {
ListScope L(W, "Addrsig");
if (!this->dumper()->getDotAddrsigSec())
return;
ArrayRef<uint8_t> Contents = unwrapOrError(
+ this->FileName,
Obj->getSectionContents(this->dumper()->getDotAddrsigSec()));
- const uint8_t *Cur = Contents.begin();
- const uint8_t *End = Contents.end();
- while (Cur != End) {
- unsigned Size;
- const char *Err;
- uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err);
- if (Err)
- reportError(Err);
- W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex),
- SymIndex);
- Cur += Size;
+ Expected<std::vector<uint64_t>> V = toULEB128Array(Contents);
+ if (!V) {
+ reportWarning(V.takeError(), this->FileName);
+ return;
+ }
+
+ for (uint64_t Sym : *V) {
+ Expected<std::string> NameOrErr = this->dumper()->getStaticSymbolName(Sym);
+ if (NameOrErr) {
+ W.printNumber("Sym", *NameOrErr, Sym);
+ continue;
+ }
+ reportWarning(NameOrErr.takeError(), this->FileName);
+ W.printNumber("Sym", "<?>", Sym);
}
}
@@ -5051,6 +5826,17 @@ static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
}
}
+static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
+ W.printNumber("Page Size", Note.PageSize);
+ for (const CoreFileMapping &Mapping : Note.Mappings) {
+ ListScope D(W, "Mapping");
+ W.printHex("Start", Mapping.Start);
+ W.printHex("End", Mapping.End);
+ W.printHex("Offset", Mapping.Offset);
+ W.printString("Filename", Mapping.Filename);
+ }
+}
+
template <class ELFT>
void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
ListScope L(W, "Notes");
@@ -5067,56 +5853,81 @@ void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
ArrayRef<uint8_t> Descriptor = Note.getDesc();
Elf_Word Type = Note.getType();
+ // Print the note owner/type.
W.printString("Owner", Name);
W.printHex("Data size", Descriptor.size());
if (Name == "GNU") {
W.printString("Type", getGNUNoteTypeName(Type));
- printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W);
} else if (Name == "FreeBSD") {
W.printString("Type", getFreeBSDNoteTypeName(Type));
} else if (Name == "AMD") {
W.printString("Type", getAMDNoteTypeName(Type));
- const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
- if (!N.Type.empty())
- W.printString(N.Type, N.Value);
} else if (Name == "AMDGPU") {
W.printString("Type", getAMDGPUNoteTypeName(Type));
- const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
- if (!N.Type.empty())
- W.printString(N.Type, N.Value);
} else {
- StringRef NoteType = getGenericNoteTypeName(Type);
+ StringRef NoteType = Obj->getHeader()->e_type == ELF::ET_CORE
+ ? getCoreNoteTypeName(Type)
+ : getGenericNoteTypeName(Type);
if (!NoteType.empty())
W.printString("Type", NoteType);
else
W.printString("Type",
"Unknown (" + to_string(format_hex(Type, 10)) + ")");
}
+
+ // Print the description, or fallback to printing raw bytes for unknown
+ // owners.
+ if (Name == "GNU") {
+ printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W);
+ } else if (Name == "AMD") {
+ const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
+ if (!N.Type.empty())
+ W.printString(N.Type, N.Value);
+ } else if (Name == "AMDGPU") {
+ const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
+ if (!N.Type.empty())
+ W.printString(N.Type, N.Value);
+ } else if (Name == "CORE") {
+ if (Type == ELF::NT_FILE) {
+ DataExtractor DescExtractor(Descriptor,
+ ELFT::TargetEndianness == support::little,
+ sizeof(Elf_Addr));
+ Expected<CoreNote> Note = readCoreNote(DescExtractor);
+ if (Note)
+ printCoreNoteLLVMStyle(*Note, W);
+ else
+ reportWarning(Note.takeError(), this->FileName);
+ }
+ } else if (!Descriptor.empty()) {
+ W.printBinaryBlock("Description data", Descriptor);
+ }
};
- if (Obj->getHeader()->e_type == ELF::ET_CORE) {
- for (const auto &P : unwrapOrError(Obj->program_headers())) {
- if (P.p_type != PT_NOTE)
+ ArrayRef<Elf_Shdr> Sections = unwrapOrError(this->FileName, Obj->sections());
+ if (Obj->getHeader()->e_type != ELF::ET_CORE && !Sections.empty()) {
+ for (const auto &S : Sections) {
+ if (S.sh_type != SHT_NOTE)
continue;
DictScope D(W, "NoteSection");
- PrintHeader(P.p_offset, P.p_filesz);
+ PrintHeader(S.sh_offset, S.sh_size);
Error Err = Error::success();
- for (const auto &Note : Obj->notes(P, Err))
+ for (const auto &Note : Obj->notes(S, Err))
ProcessNote(Note);
if (Err)
- error(std::move(Err));
+ reportError(std::move(Err), this->FileName);
}
} else {
- for (const auto &S : unwrapOrError(Obj->sections())) {
- if (S.sh_type != SHT_NOTE)
+ for (const auto &P :
+ unwrapOrError(this->FileName, Obj->program_headers())) {
+ if (P.p_type != PT_NOTE)
continue;
DictScope D(W, "NoteSection");
- PrintHeader(S.sh_offset, S.sh_size);
+ PrintHeader(P.p_offset, P.p_filesz);
Error Err = Error::success();
- for (const auto &Note : Obj->notes(S, Err))
+ for (const auto &Note : Obj->notes(P, Err))
ProcessNote(Note);
if (Err)
- error(std::move(Err));
+ reportError(std::move(Err), this->FileName);
}
}
}
@@ -5125,11 +5936,12 @@ template <class ELFT>
void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
ListScope L(W, "LinkerOptions");
- for (const Elf_Shdr &Shdr : unwrapOrError(Obj->sections())) {
+ for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS)
continue;
- ArrayRef<uint8_t> Contents = unwrapOrError(Obj->getSectionContents(&Shdr));
+ ArrayRef<uint8_t> Contents =
+ unwrapOrError(this->FileName, Obj->getSectionContents(&Shdr));
for (const uint8_t *P = Contents.begin(), *E = Contents.end(); P < E; ) {
StringRef Key = StringRef(reinterpret_cast<const char *>(P));
StringRef Value =
@@ -5143,6 +5955,22 @@ void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
}
template <class ELFT>
+void LLVMStyle<ELFT>::printStackSizes(const ELFObjectFile<ELFT> *Obj) {
+ ListScope L(W, "StackSizes");
+ if (Obj->isRelocatableObject())
+ this->printRelocatableStackSizes(Obj, []() {});
+ else
+ this->printNonRelocatableStackSizes(Obj, []() {});
+}
+
+template <class ELFT>
+void LLVMStyle<ELFT>::printStackSizeEntry(uint64_t Size, StringRef FuncName) {
+ DictScope D(W, "Entry");
+ W.printString("Function", FuncName);
+ W.printHex("Size", Size);
+}
+
+template <class ELFT>
void LLVMStyle<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
auto PrintEntry = [&](const Elf_Addr *E) {
W.printHex("Address", Parser.getGotAddress(E));
@@ -5252,3 +6080,41 @@ void LLVMStyle<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
}
}
}
+
+template <class ELFT>
+void LLVMStyle<ELFT>::printMipsABIFlags(const ELFObjectFile<ELFT> *ObjF) {
+ const ELFFile<ELFT> *Obj = ObjF->getELFFile();
+ const Elf_Shdr *Shdr =
+ findSectionByName(*Obj, ObjF->getFileName(), ".MIPS.abiflags");
+ if (!Shdr) {
+ W.startLine() << "There is no .MIPS.abiflags section in the file.\n";
+ return;
+ }
+ ArrayRef<uint8_t> Sec =
+ unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr));
+ if (Sec.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) {
+ W.startLine() << "The .MIPS.abiflags section has a wrong size.\n";
+ return;
+ }
+
+ auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec.data());
+
+ raw_ostream &OS = W.getOStream();
+ DictScope GS(W, "MIPS ABI Flags");
+
+ W.printNumber("Version", Flags->version);
+ W.startLine() << "ISA: ";
+ if (Flags->isa_rev <= 1)
+ OS << format("MIPS%u", Flags->isa_level);
+ else
+ OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);
+ OS << "\n";
+ W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType));
+ W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags));
+ W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType));
+ W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));
+ W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));
+ W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));
+ W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1));
+ W.printHex("Flags 2", Flags->flags2);
+}
diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp
index 32a3866eb2f2..20a60b3df699 100644
--- a/tools/llvm-readobj/MachODumper.cpp
+++ b/tools/llvm-readobj/MachODumper.cpp
@@ -214,6 +214,31 @@ static const EnumEntry<uint32_t> MachOHeaderFlags[] = {
LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE),
};
+static const EnumEntry<unsigned> MachOSectionTypes[] = {
+ { "Regular" , MachO::S_REGULAR },
+ { "ZeroFill" , MachO::S_ZEROFILL },
+ { "CStringLiterals" , MachO::S_CSTRING_LITERALS },
+ { "4ByteLiterals" , MachO::S_4BYTE_LITERALS },
+ { "8ByteLiterals" , MachO::S_8BYTE_LITERALS },
+ { "LiteralPointers" , MachO::S_LITERAL_POINTERS },
+ { "NonLazySymbolPointers" , MachO::S_NON_LAZY_SYMBOL_POINTERS },
+ { "LazySymbolPointers" , MachO::S_LAZY_SYMBOL_POINTERS },
+ { "SymbolStubs" , MachO::S_SYMBOL_STUBS },
+ { "ModInitFuncPointers" , MachO::S_MOD_INIT_FUNC_POINTERS },
+ { "ModTermFuncPointers" , MachO::S_MOD_TERM_FUNC_POINTERS },
+ { "Coalesced" , MachO::S_COALESCED },
+ { "GBZeroFill" , MachO::S_GB_ZEROFILL },
+ { "Interposing" , MachO::S_INTERPOSING },
+ { "16ByteLiterals" , MachO::S_16BYTE_LITERALS },
+ { "DTraceDOF" , MachO::S_DTRACE_DOF },
+ { "LazyDylibSymbolPointers" , MachO::S_LAZY_DYLIB_SYMBOL_POINTERS },
+ { "ThreadLocalRegular" , MachO::S_THREAD_LOCAL_REGULAR },
+ { "ThreadLocalZerofill" , MachO::S_THREAD_LOCAL_ZEROFILL },
+ { "ThreadLocalVariables" , MachO::S_THREAD_LOCAL_VARIABLES },
+ { "ThreadLocalVariablePointers" , MachO::S_THREAD_LOCAL_VARIABLE_POINTERS },
+ { "ThreadLocalInitFunctionPointers", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS }
+};
+
static const EnumEntry<unsigned> MachOSectionAttributes[] = {
{ "LocReloc" , 1 << 0 /*S_ATTR_LOC_RELOC */ },
{ "ExtReloc" , 1 << 1 /*S_ATTR_EXT_RELOC */ },
@@ -440,10 +465,7 @@ void MachODumper::printSectionHeaders(const MachOObjectFile *Obj) {
MachOSection MOSection;
getSection(Obj, Section.getRawDataRefImpl(), MOSection);
DataRefImpl DR = Section.getRawDataRefImpl();
-
- StringRef Name;
- error(Section.getName(Name));
-
+ StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());
ArrayRef<char> RawName = Obj->getSectionRawName(DR);
StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);
ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR);
@@ -459,7 +481,7 @@ void MachODumper::printSectionHeaders(const MachOObjectFile *Obj) {
W.printHex("RelocationOffset", MOSection.RelocationTableOffset);
W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);
W.printEnum("Type", MOSection.Flags & 0xFF,
- makeArrayRef(MachOSectionAttributes));
+ makeArrayRef(MachOSectionTypes));
W.printFlags("Attributes", MOSection.Flags >> 8,
makeArrayRef(MachOSectionAttributes));
W.printHex("Reserved1", MOSection.Reserved1);
@@ -484,7 +506,8 @@ void MachODumper::printSectionHeaders(const MachOObjectFile *Obj) {
}
if (opts::SectionData && !Section.isBSS())
- W.printBinaryBlock("SectionData", unwrapOrError(Section.getContents()));
+ W.printBinaryBlock("SectionData", unwrapOrError(Obj->getFileName(),
+ Section.getContents()));
}
}
@@ -493,9 +516,7 @@ void MachODumper::printRelocations() {
std::error_code EC;
for (const SectionRef &Section : Obj->sections()) {
- StringRef Name;
- error(Section.getName(Name));
-
+ StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());
bool PrintedGroup = false;
for (const RelocationRef &Reloc : Section.relocations()) {
if (!PrintedGroup) {
@@ -535,14 +556,13 @@ void MachODumper::printRelocation(const MachOObjectFile *Obj,
if (Symbol != Obj->symbol_end()) {
Expected<StringRef> TargetNameOrErr = Symbol->getName();
if (!TargetNameOrErr)
- error(errorToErrorCode(TargetNameOrErr.takeError()));
+ reportError(TargetNameOrErr.takeError(), Obj->getFileName());
TargetName = *TargetNameOrErr;
}
} else if (!IsScattered) {
section_iterator SecI = Obj->getRelocationSection(DR);
- if (SecI != Obj->section_end()) {
- error(SecI->getName(TargetName));
- }
+ if (SecI != Obj->section_end())
+ TargetName = unwrapOrError(Obj->getFileName(), SecI->getName());
}
if (TargetName.empty())
TargetName = "-";
@@ -610,10 +630,12 @@ void MachODumper::printSymbol(const SymbolRef &Symbol) {
StringRef SectionName = "";
Expected<section_iterator> SecIOrErr = Symbol.getSection();
- error(errorToErrorCode(SecIOrErr.takeError()));
+ if (!SecIOrErr)
+ reportError(SecIOrErr.takeError(), Obj->getFileName());
+
section_iterator SecI = *SecIOrErr;
if (SecI != Obj->section_end())
- error(SecI->getName(SectionName));
+ SectionName = unwrapOrError(Obj->getFileName(), SecI->getName());
DictScope D(W, "Symbol");
W.printNumber("Name", SymbolName, MOSymbol.StringIndex);
@@ -643,7 +665,11 @@ void MachODumper::printStackMap() const {
object::SectionRef StackMapSection;
for (auto Sec : Obj->sections()) {
StringRef Name;
- Sec.getName(Name);
+ if (Expected<StringRef> NameOrErr = Sec.getName())
+ Name = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
+
if (Name == "__llvm_stackmaps") {
StackMapSection = Sec;
break;
@@ -653,7 +679,8 @@ void MachODumper::printStackMap() const {
if (StackMapSection == object::SectionRef())
return;
- StringRef StackMapContents = unwrapOrError(StackMapSection.getContents());
+ StringRef StackMapContents =
+ unwrapOrError(Obj->getFileName(), StackMapSection.getContents());
ArrayRef<uint8_t> StackMapContentsArray =
arrayRefFromStringRef(StackMapContents);
diff --git a/tools/llvm-readobj/ObjDumper.cpp b/tools/llvm-readobj/ObjDumper.cpp
index 0a9e22c8a71c..9e5ebd99ac37 100644
--- a/tools/llvm-readobj/ObjDumper.cpp
+++ b/tools/llvm-readobj/ObjDumper.cpp
@@ -23,6 +23,10 @@
namespace llvm {
+static inline Error createError(const Twine &Msg) {
+ return createStringError(object::object_error::parse_failed, Msg);
+}
+
ObjDumper::ObjDumper(ScopedPrinter &Writer) : W(Writer) {}
ObjDumper::~ObjDumper() {
@@ -49,8 +53,7 @@ getSectionRefsByNameOrIndex(const object::ObjectFile *Obj,
SecIndex = Obj->isELF() ? 0 : 1;
for (object::SectionRef SecRef : Obj->sections()) {
- StringRef SecName;
- error(SecRef.getName(SecName));
+ StringRef SecName = unwrapOrError(Obj->getFileName(), SecRef.getName());
auto NameIt = SecNames.find(SecName);
if (NameIt != SecNames.end())
NameIt->second = true;
@@ -64,10 +67,15 @@ getSectionRefsByNameOrIndex(const object::ObjectFile *Obj,
for (const std::pair<std::string, bool> &S : SecNames)
if (!S.second)
- reportWarning(formatv("could not find section '{0}'", S.first).str());
+ reportWarning(
+ createError(formatv("could not find section '{0}'", S.first).str()),
+ Obj->getFileName());
+
for (std::pair<unsigned, bool> S : SecIndices)
if (!S.second)
- reportWarning(formatv("could not find section {0}", S.first).str());
+ reportWarning(
+ createError(formatv("could not find section {0}", S.first).str()),
+ Obj->getFileName());
return Ret;
}
@@ -77,14 +85,16 @@ void ObjDumper::printSectionsAsString(const object::ObjectFile *Obj,
bool First = true;
for (object::SectionRef Section :
getSectionRefsByNameOrIndex(Obj, Sections)) {
- StringRef SectionName;
- error(Section.getName(SectionName));
+ StringRef SectionName =
+ unwrapOrError(Obj->getFileName(), Section.getName());
+
if (!First)
W.startLine() << '\n';
First = false;
W.startLine() << "String dump of section '" << SectionName << "':\n";
- StringRef SectionContent = unwrapOrError(Section.getContents());
+ StringRef SectionContent =
+ unwrapOrError(Obj->getFileName(), Section.getContents());
const uint8_t *SecContent = SectionContent.bytes_begin();
const uint8_t *CurrentWord = SecContent;
@@ -110,14 +120,16 @@ void ObjDumper::printSectionsAsHex(const object::ObjectFile *Obj,
bool First = true;
for (object::SectionRef Section :
getSectionRefsByNameOrIndex(Obj, Sections)) {
- StringRef SectionName;
- error(Section.getName(SectionName));
+ StringRef SectionName =
+ unwrapOrError(Obj->getFileName(), Section.getName());
+
if (!First)
W.startLine() << '\n';
First = false;
W.startLine() << "Hex dump of section '" << SectionName << "':\n";
- StringRef SectionContent = unwrapOrError(Section.getContents());
+ StringRef SectionContent =
+ unwrapOrError(Obj->getFileName(), Section.getContents());
const uint8_t *SecContent = SectionContent.bytes_begin();
const uint8_t *SecEnd = SecContent + SectionContent.size();
diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h
index aaabfa2ca2e8..2ba441342499 100644
--- a/tools/llvm-readobj/ObjDumper.h
+++ b/tools/llvm-readobj/ObjDumper.h
@@ -68,15 +68,8 @@ public:
virtual void printAddrsig() {}
virtual void printNotes() {}
virtual void printELFLinkerOptions() {}
-
- // Only implemented for ARM ELF at this time.
- virtual void printAttributes() { }
-
- // Only implemented for MIPS ELF at this time.
- virtual void printMipsPLTGOT() { }
- virtual void printMipsABIFlags() { }
- virtual void printMipsReginfo() { }
- virtual void printMipsOptions() { }
+ virtual void printStackSizes() {}
+ virtual void printArchSpecificInfo() { }
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
diff --git a/tools/llvm-readobj/WasmDumper.cpp b/tools/llvm-readobj/WasmDumper.cpp
index 041a9a15bdb6..dfab9f40d71b 100644
--- a/tools/llvm-readobj/WasmDumper.cpp
+++ b/tools/llvm-readobj/WasmDumper.cpp
@@ -51,6 +51,7 @@ static const EnumEntry<unsigned> WasmSymbolFlags[] = {
ENUM_ENTRY(UNDEFINED),
ENUM_ENTRY(EXPORTED),
ENUM_ENTRY(EXPLICIT_NAME),
+ ENUM_ENTRY(NO_STRIP),
#undef ENUM_ENTRY
};
@@ -90,7 +91,7 @@ void WasmDumper::printRelocation(const SectionRef &Section,
StringRef SymName;
symbol_iterator SI = Reloc.getSymbol();
if (SI != Obj->symbol_end())
- SymName = error(SI->getName());
+ SymName = unwrapOrError(Obj->getFileName(), SI->getName());
bool HasAddend = false;
switch (RelocType) {
@@ -133,8 +134,8 @@ void WasmDumper::printRelocations() {
int SectionNumber = 0;
for (const SectionRef &Section : Obj->sections()) {
bool PrintedGroup = false;
- StringRef Name;
- error(Section.getName(Name));
+ StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());
+
++SectionNumber;
for (const RelocationRef &Reloc : Section.relocations()) {
diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp
index e64b8f157180..fa268ce9d434 100644
--- a/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/tools/llvm-readobj/Win64EHDumper.cpp
@@ -289,7 +289,9 @@ void Dumper::printRuntimeFunction(const Context &Ctx,
resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset);
ArrayRef<uint8_t> Contents;
- error(Ctx.COFF.getSectionContents(XData, Contents));
+ if (Error E = Ctx.COFF.getSectionContents(XData, Contents))
+ reportError(std::move(E), Ctx.COFF.getFileName());
+
if (Contents.empty())
return;
@@ -304,14 +306,19 @@ void Dumper::printRuntimeFunction(const Context &Ctx,
void Dumper::printData(const Context &Ctx) {
for (const auto &Section : Ctx.COFF.sections()) {
StringRef Name;
- Section.getName(Name);
+ if (Expected<StringRef> NameOrErr = Section.getName())
+ Name = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
if (Name != ".pdata" && !Name.startswith(".pdata$"))
continue;
const coff_section *PData = Ctx.COFF.getCOFFSection(Section);
ArrayRef<uint8_t> Contents;
- error(Ctx.COFF.getSectionContents(PData, Contents));
+
+ if (Error E = Ctx.COFF.getSectionContents(PData, Contents))
+ reportError(std::move(E), Ctx.COFF.getFileName());
if (Contents.empty())
continue;
diff --git a/tools/llvm-readobj/WindowsResourceDumper.cpp b/tools/llvm-readobj/WindowsResourceDumper.cpp
index 13989f696d9d..a2fb6aac3f93 100644
--- a/tools/llvm-readobj/WindowsResourceDumper.cpp
+++ b/tools/llvm-readobj/WindowsResourceDumper.cpp
@@ -56,8 +56,12 @@ void Dumper::printEntry(const ResourceEntryRef &Ref) {
if (Ref.checkTypeString()) {
auto NarrowStr = stripUTF16(Ref.getTypeString());
SW.printString("Resource type (string)", NarrowStr);
- } else
- SW.printNumber("Resource type (int)", Ref.getTypeID());
+ } else {
+ SmallString<20> IDStr;
+ raw_svector_ostream OS(IDStr);
+ printResourceTypeName(Ref.getTypeID(), OS);
+ SW.printString("Resource type (int)", IDStr);
+ }
if (Ref.checkNameString()) {
auto NarrowStr = stripUTF16(Ref.getNameString());
diff --git a/tools/llvm-readobj/XCOFFDumper.cpp b/tools/llvm-readobj/XCOFFDumper.cpp
index 6f260f91537f..fe95b6d1b494 100644
--- a/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/tools/llvm-readobj/XCOFFDumper.cpp
@@ -22,6 +22,12 @@ using namespace object;
namespace {
class XCOFFDumper : public ObjDumper {
+ enum {
+ SymbolTypeMask = 0x07,
+ SymbolAlignmentMask = 0xF8,
+ SymbolAlignmentBitOffset = 3
+ };
+
public:
XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
: ObjDumper(Writer), Obj(Obj) {}
@@ -37,11 +43,21 @@ public:
private:
template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
-
- const XCOFFObjectFile &Obj;
+ template <typename T> void printGenericSectionHeader(T &Sec) const;
+ template <typename T> void printOverflowSectionHeader(T &Sec) const;
+ void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
+ void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
+ void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
+ void printSymbol(const SymbolRef &);
// 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;
+
+ void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
+ const XCOFFObjectFile &Obj;
};
} // anonymous namespace
@@ -100,11 +116,315 @@ void XCOFFDumper::printSectionHeaders() {
}
void XCOFFDumper::printRelocations() {
- llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+ if (Obj.is64Bit())
+ llvm_unreachable("64-bit relocation output not implemented!");
+ else
+ printRelocations(Obj.sections32());
+}
+
+static const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
+ ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
+ ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
+ ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
+ ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
+ ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
+#undef ECase
+};
+
+void XCOFFDumper::printRelocations(ArrayRef<XCOFFSectionHeader32> Sections) {
+ if (!opts::ExpandRelocs)
+ report_fatal_error("Unexpanded relocation output not implemented.");
+
+ ListScope LS(W, "Relocations");
+ uint16_t Index = 0;
+ for (const auto &Sec : Sections) {
+ ++Index;
+ // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
+ if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
+ Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
+ continue;
+ auto Relocations = unwrapOrError(Obj.getFileName(), Obj.relocations(Sec));
+ if (Relocations.empty())
+ continue;
+
+ W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
+ << " {\n";
+ for (auto Reloc : Relocations) {
+ StringRef SymbolName = unwrapOrError(
+ Obj.getFileName(), Obj.getSymbolNameByIndex(Reloc.SymbolIndex));
+
+ DictScope RelocScope(W, "Relocation");
+ W.printHex("Virtual Address", Reloc.VirtualAddress);
+ W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
+ W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
+ W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
+ W.printNumber("Length", Reloc.getRelocatedLength());
+ W.printEnum("Type", (uint8_t)Reloc.Type,
+ makeArrayRef(RelocationTypeNameclass));
+ }
+ W.unindent();
+ W.startLine() << "}\n";
+ }
+}
+
+static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
+#undef ECase
+};
+
+void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
+ if (Obj.is64Bit())
+ report_fatal_error(
+ "Printing for File Auxiliary Entry in 64-bit is unimplemented.");
+ StringRef FileName =
+ unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
+ DictScope SymDs(W, "File Auxiliary Entry");
+ W.printNumber("Index",
+ Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
+ W.printString("Name", FileName);
+ W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
+ makeArrayRef(FileStringType));
+}
+
+static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
+ {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),
+ ECase(XMC_GL), ECase(XMC_XO), ECase(XMC_SV),
+ ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI),
+ ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
+ ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),
+ ECase(XMC_UA), ECase(XMC_BS), ECase(XMC_UC),
+ ECase(XMC_TL), ECase(XMC_TE)
+#undef ECase
+};
+
+static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
+#undef ECase
+};
+
+void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
+ assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
+
+ DictScope SymDs(W, "CSECT Auxiliary Entry");
+ W.printNumber("Index",
+ Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
+ if ((AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask) == XCOFF::XTY_LD)
+ W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
+ else
+ W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
+ W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
+ W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
+ // Print out symbol alignment and type.
+ W.printNumber("SymbolAlignmentLog2",
+ (AuxEntPtr->SymbolAlignmentAndType & SymbolAlignmentMask) >>
+ SymbolAlignmentBitOffset);
+ W.printEnum("SymbolType", AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask,
+ makeArrayRef(CsectSymbolTypeClass));
+ W.printEnum("StorageMappingClass",
+ static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
+ makeArrayRef(CsectStorageMappingClass));
+ W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
+ W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
+}
+
+void XCOFFDumper::printSectAuxEntForStat(
+ const XCOFFSectAuxEntForStat *AuxEntPtr) {
+ assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
+
+ DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
+ W.printNumber("Index",
+ Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
+ W.printNumber("SectionLength", AuxEntPtr->SectionLength);
+
+ // Unlike the corresponding fields in the section header, NumberOfRelocEnt
+ // and NumberOfLineNum do not handle values greater than 65535.
+ W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
+ W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
+}
+
+static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
+ ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
+ ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
+ ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
+ ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
+ ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
+ ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
+ ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
+ ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
+ ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
+ ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
+ ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
+ ECase(C_STTLS), ECase(C_EFCN)
+#undef ECase
+};
+
+static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
+ switch (SC) {
+ case XCOFF::C_EXT:
+ case XCOFF::C_WEAKEXT:
+ case XCOFF::C_HIDEXT:
+ case XCOFF::C_STAT:
+ return "Value (RelocatableAddress)";
+ case XCOFF::C_FILE:
+ return "Value (SymbolTableIndex)";
+ case XCOFF::C_FCN:
+ case XCOFF::C_BLOCK:
+ case XCOFF::C_FUN:
+ case XCOFF::C_STSYM:
+ case XCOFF::C_BINCL:
+ case XCOFF::C_EINCL:
+ case XCOFF::C_INFO:
+ case XCOFF::C_BSTAT:
+ case XCOFF::C_LSYM:
+ case XCOFF::C_PSYM:
+ case XCOFF::C_RPSYM:
+ case XCOFF::C_RSYM:
+ case XCOFF::C_ECOML:
+ case XCOFF::C_DWARF:
+ assert(false && "This StorageClass for the symbol is not yet implemented.");
+ return "";
+ default:
+ return "Value";
+ }
+}
+
+static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(TB_C), ECase(TB_CPLUSPLUS)
+#undef ECase
+};
+
+static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
+#undef ECase
+};
+
+void XCOFFDumper::printSymbol(const SymbolRef &S) {
+ if (Obj.is64Bit())
+ report_fatal_error("64-bit support is unimplemented.");
+
+ DataRefImpl SymbolDRI = S.getRawDataRefImpl();
+ const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
+
+ XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
+ uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
+
+ DictScope SymDs(W, "Symbol");
+
+ StringRef SymbolName =
+ unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
+
+ W.printNumber("Index",
+ Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
+ W.printString("Name", SymbolName);
+ W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
+ SymbolEntPtr->Value);
+
+ StringRef SectionName =
+ unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
+
+ W.printString("Section", SectionName);
+ if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
+ W.printEnum("Source Language ID",
+ SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
+ makeArrayRef(CFileLangIdClass));
+ W.printEnum("CPU Version ID",
+ SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
+ makeArrayRef(CFileCpuIdClass));
+ } else
+ W.printHex("Type", SymbolEntPtr->SymbolType);
+
+ W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
+ makeArrayRef(SymStorageClass));
+ W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
+
+ if (NumberOfAuxEntries == 0)
+ return;
+
+ switch (XCOFFSymRef.getStorageClass()) {
+ case XCOFF::C_FILE:
+ // If the symbol is C_FILE and has auxiliary entries...
+ for (int i = 1; i <= NumberOfAuxEntries; i++) {
+ const XCOFFFileAuxEnt *FileAuxEntPtr =
+ reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
+#ifndef NDEBUG
+ Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
+#endif
+ printFileAuxEnt(FileAuxEntPtr);
+ }
+ break;
+ case XCOFF::C_EXT:
+ case XCOFF::C_WEAKEXT:
+ case XCOFF::C_HIDEXT:
+ // If the symbol is for a function, and it has more than 1 auxiliary entry,
+ // then one of them must be function auxiliary entry which we do not
+ // support yet.
+ if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
+ report_fatal_error("Function auxiliary entry printing is unimplemented.");
+
+ // If there is more than 1 auxiliary entry, instead of printing out
+ // error information, print out the raw Auxiliary entry from 1st till
+ // the last - 1. The last one must be a CSECT Auxiliary Entry.
+ for (int i = 1; i < NumberOfAuxEntries; i++) {
+ W.startLine() << "!Unexpected raw auxiliary entry data:\n";
+ W.startLine() << format_bytes(
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
+ XCOFF::SymbolTableEntrySize));
+ }
+
+ // The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
+ printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
+ break;
+ case XCOFF::C_STAT:
+ if (NumberOfAuxEntries > 1)
+ report_fatal_error(
+ "C_STAT symbol should not have more than 1 auxiliary entry.");
+
+ const XCOFFSectAuxEntForStat *StatAuxEntPtr;
+ StatAuxEntPtr =
+ reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
+#ifndef NDEBUG
+ Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
+#endif
+ printSectAuxEntForStat(StatAuxEntPtr);
+ break;
+ case XCOFF::C_DWARF:
+ case XCOFF::C_BLOCK:
+ case XCOFF::C_FCN:
+ report_fatal_error("Symbol table entry printing for this storage class "
+ "type is unimplemented.");
+ break;
+ default:
+ for (int i = 1; i <= NumberOfAuxEntries; i++) {
+ W.startLine() << "!Unexpected raw auxiliary entry data:\n";
+ W.startLine() << format_bytes(
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
+ XCOFF::SymbolTableEntrySize));
+ }
+ break;
+ }
}
void XCOFFDumper::printSymbols() {
- llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+ ListScope Group(W, "Symbols");
+ for (const SymbolRef &S : Obj.symbols())
+ printSymbol(S);
}
void XCOFFDumper::printDynamicSymbols() {
@@ -135,6 +455,39 @@ static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
};
template <typename T>
+void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
+ if (Obj.is64Bit()) {
+ reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
+ "contain an overflow section header.",
+ object_error::parse_failed),
+ Obj.getFileName());
+ }
+
+ W.printString("Name", Sec.getName());
+ W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
+ W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
+ W.printHex("Size", Sec.SectionSize);
+ W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
+ W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
+ W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
+ W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
+ W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
+}
+
+template <typename T>
+void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
+ W.printString("Name", Sec.getName());
+ W.printHex("PhysicalAddress", Sec.PhysicalAddress);
+ W.printHex("VirtualAddress", Sec.VirtualAddress);
+ W.printHex("Size", Sec.SectionSize);
+ W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
+ W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
+ W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
+ W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
+ W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
+}
+
+template <typename T>
void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
ListScope Group(W, "Sections");
@@ -143,27 +496,28 @@ void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
DictScope SecDS(W, "Section");
W.printNumber("Index", Index++);
- W.printString("Name", Sec.getName());
-
- W.printHex("PhysicalAddress", Sec.PhysicalAddress);
- W.printHex("VirtualAddress", Sec.VirtualAddress);
- W.printHex("Size", Sec.SectionSize);
- W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
- W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
- W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
-
- // TODO Need to add overflow handling when NumberOfX == _OVERFLOW_MARKER
- // in 32-bit object files.
- W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
- W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
-
- // The most significant 16-bits represent the DWARF section subtype. For
- // now we just dump the section type flags.
- uint16_t Flags = Sec.Flags & 0xffffu;
- if (Flags & SectionFlagsReservedMask)
- W.printHex("Flags", "Reserved", Flags);
+
+ uint16_t SectionType = Sec.Flags & SectionFlagsTypeMask;
+ switch (SectionType) {
+ case XCOFF::STYP_OVRFLO:
+ printOverflowSectionHeader(Sec);
+ break;
+ case XCOFF::STYP_LOADER:
+ case XCOFF::STYP_EXCEPT:
+ case XCOFF::STYP_TYPCHK:
+ // TODO The interpretation of loader, exception and type check section
+ // headers are different from that of generic section headers. We will
+ // implement them later. We interpret them as generic section headers for
+ // now.
+ default:
+ printGenericSectionHeader(Sec);
+ break;
+ }
+ // For now we just dump the section type portion of the flags.
+ if (SectionType & SectionFlagsReservedMask)
+ W.printHex("Flags", "Reserved", SectionType);
else
- W.printEnum("Type", Flags, makeArrayRef(SectionTypeFlagsNames));
+ W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
}
if (opts::SectionRelocations)
diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp
index 1bd5bb74bf29..4db13897879d 100644
--- a/tools/llvm-readobj/llvm-readobj.cpp
+++ b/tools/llvm-readobj/llvm-readobj.cpp
@@ -231,26 +231,11 @@ namespace opts {
"codeview-subsection-bytes",
cl::desc("Dump raw contents of codeview debug sections and records"));
- // --arm-attributes
- cl::opt<bool> ARMAttributes("arm-attributes",
- cl::desc("Display the ARM attributes section"));
-
- // --mips-plt-got
- cl::opt<bool>
- MipsPLTGOT("mips-plt-got",
- cl::desc("Display the MIPS GOT and PLT GOT sections"));
-
- // --mips-abi-flags
- cl::opt<bool> MipsABIFlags("mips-abi-flags",
- cl::desc("Display the MIPS.abiflags section"));
-
- // --mips-reginfo
- cl::opt<bool> MipsReginfo("mips-reginfo",
- cl::desc("Display the MIPS .reginfo section"));
-
- // --mips-options
- cl::opt<bool> MipsOptions("mips-options",
- cl::desc("Display the MIPS .MIPS.options section"));
+ // --arch-specific
+ cl::opt<bool> ArchSpecificInfo("arch-specific",
+ cl::desc("Displays architecture-specific information, if there is any."));
+ cl::alias ArchSpecifcInfoShort("A", cl::desc("Alias for --arch-specific"),
+ cl::aliasopt(ArchSpecificInfo), cl::NotHidden);
// --coff-imports
cl::opt<bool>
@@ -324,6 +309,11 @@ namespace opts {
PrintStackMap("stackmap",
cl::desc("Display contents of stackmap section"));
+ // --stack-sizes
+ cl::opt<bool>
+ PrintStackSizes("stack-sizes",
+ cl::desc("Display contents of all stack sizes sections"));
+
// --version-info, -V
cl::opt<bool>
VersionInfo("version-info",
@@ -368,63 +358,45 @@ namespace opts {
HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
} // namespace opts
+static StringRef ToolName;
+
namespace llvm {
-LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg) {
+LLVM_ATTRIBUTE_NORETURN static void error(Twine Msg) {
+ // Flush the standard output to print the error at a
+ // proper place.
fouts().flush();
errs() << "\n";
- WithColor::error(errs()) << Msg << "\n";
+ WithColor::error(errs(), ToolName) << Msg << "\n";
exit(1);
}
-void reportError(StringRef Input, Error Err) {
+LLVM_ATTRIBUTE_NORETURN void reportError(Error Err, StringRef Input) {
+ assert(Err);
if (Input == "-")
Input = "<stdin>";
- error(createFileError(Input, std::move(Err)));
+ handleAllErrors(createFileError(Input, std::move(Err)),
+ [&](const ErrorInfoBase &EI) { error(EI.message()); });
+ llvm_unreachable("error() call should never return");
}
-void reportWarning(Twine Msg) {
- fouts().flush();
- errs() << "\n";
- WithColor::warning(errs()) << Msg << "\n";
-}
-
-void warn(Error Err) {
- handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
- reportWarning(EI.message());
- });
-}
-
-void error(Error EC) {
- if (!EC)
- return;
- handleAllErrors(std::move(EC),
- [&](const ErrorInfoBase &EI) { reportError(EI.message()); });
-}
+void reportWarning(Error Err, StringRef Input) {
+ assert(Err);
+ if (Input == "-")
+ Input = "<stdin>";
-void error(std::error_code EC) {
- if (!EC)
- return;
- reportError(EC.message());
+ // Flush the standard output to print the warning at a
+ // proper place.
+ fouts().flush();
+ handleAllErrors(
+ createFileError(Input, std::move(Err)), [&](const ErrorInfoBase &EI) {
+ errs() << "\n";
+ WithColor::warning(errs(), ToolName) << EI.message() << "\n";
+ });
}
} // namespace llvm
-static void reportError(StringRef Input, std::error_code EC) {
- reportError(Input, errorCodeToError(EC));
-}
-
-static bool isMipsArch(unsigned Arch) {
- switch (Arch) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return true;
- default:
- return false;
- }
-}
namespace {
struct ReadObjTypeTableBuilder {
ReadObjTypeTableBuilder()
@@ -471,19 +443,19 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer,
std::unique_ptr<ObjDumper> Dumper;
if (std::error_code EC = createDumper(Obj, Writer, Dumper))
- reportError(FileStr, EC);
+ reportError(errorCodeToError(EC), FileStr);
- Writer.startLine() << "\n";
- if (opts::Output == opts::LLVM) {
+ if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || A) {
+ Writer.startLine() << "\n";
Writer.printString("File", FileStr);
+ }
+ if (opts::Output == opts::LLVM) {
Writer.printString("Format", Obj->getFileFormatName());
Writer.printString("Arch", Triple::getArchTypeName(
(llvm::Triple::ArchType)Obj->getArch()));
Writer.printString("AddressSize",
formatv("{0}bit", 8 * Obj->getBytesInAddress()));
Dumper->printLoadName();
- } else if (opts::Output == opts::GNU && A) {
- Writer.printString("File", FileStr);
}
if (opts::FileHeaders)
@@ -519,19 +491,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer,
if (Obj->isELF()) {
if (opts::ELFLinkerOptions)
Dumper->printELFLinkerOptions();
- if (Obj->getArch() == llvm::Triple::arm)
- if (opts::ARMAttributes)
- Dumper->printAttributes();
- if (isMipsArch(Obj->getArch())) {
- if (opts::MipsPLTGOT)
- Dumper->printMipsPLTGOT();
- if (opts::MipsABIFlags)
- Dumper->printMipsABIFlags();
- if (opts::MipsReginfo)
- Dumper->printMipsReginfo();
- if (opts::MipsOptions)
- Dumper->printMipsOptions();
- }
+ if (opts::ArchSpecificInfo)
+ Dumper->printArchSpecificInfo();
if (opts::SectionGroups)
Dumper->printGroupSections();
if (opts::HashHistogram)
@@ -583,6 +544,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer,
}
if (opts::PrintStackMap)
Dumper->printStackMap();
+ if (opts::PrintStackSizes)
+ Dumper->printStackSizes();
}
/// Dumps each object file in \a Arc;
@@ -591,9 +554,8 @@ static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
for (auto &Child : Arc->children(Err)) {
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
if (!ChildOrErr) {
- if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {
- reportError(Arc->getFileName(), std::move(E));
- }
+ if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
+ reportError(std::move(E), Arc->getFileName());
continue;
}
if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
@@ -601,10 +563,11 @@ static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(&*ChildOrErr.get()))
dumpCOFFImportFile(Imp, Writer);
else
- reportError(Arc->getFileName(), readobj_error::unrecognized_file_format);
+ reportError(errorCodeToError(readobj_error::unrecognized_file_format),
+ Arc->getFileName());
}
if (Err)
- reportError(Arc->getFileName(), std::move(Err));
+ reportError(std::move(Err), Arc->getFileName());
}
/// Dumps each object file in \a MachO Universal Binary;
@@ -614,9 +577,8 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
if (ObjOrErr)
dumpObject(&*ObjOrErr.get(), Writer);
- else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
- reportError(UBinary->getFileName(), ObjOrErr.takeError());
- }
+ else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
+ reportError(ObjOrErr.takeError(), UBinary->getFileName());
else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
dumpArchive(&*AOrErr.get(), Writer);
}
@@ -627,7 +589,7 @@ static void dumpWindowsResourceFile(WindowsResource *WinRes,
ScopedPrinter &Printer) {
WindowsRes::Dumper Dumper(WinRes, Printer);
if (auto Err = Dumper.printData())
- reportError(WinRes->getFileName(), std::move(Err));
+ reportError(std::move(Err), WinRes->getFileName());
}
@@ -636,7 +598,7 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
// Attempt to open the binary.
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
if (!BinaryOrErr)
- reportError(File, BinaryOrErr.takeError());
+ reportError(BinaryOrErr.takeError(), File);
Binary &Binary = *BinaryOrErr.get().getBinary();
if (Archive *Arc = dyn_cast<Archive>(&Binary))
@@ -651,7 +613,8 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary))
dumpWindowsResourceFile(WinRes, Writer);
else
- reportError(File, readobj_error::unrecognized_file_format);
+ reportError(errorCodeToError(readobj_error::unrecognized_file_format),
+ File);
CVTypes.Binaries.push_back(std::move(*BinaryOrErr));
}
@@ -702,6 +665,7 @@ static void registerReadelfAliases() {
int main(int argc, const char *argv[]) {
InitLLVM X(argc, argv);
+ ToolName = argv[0];
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
@@ -727,6 +691,10 @@ int main(int argc, const char *argv[]) {
opts::UnwindInfo = true;
opts::SectionGroups = true;
opts::HashHistogram = true;
+ if (opts::Output == opts::LLVM) {
+ opts::Addrsig = true;
+ opts::PrintStackSizes = true;
+ }
}
if (opts::Headers) {
diff --git a/tools/llvm-readobj/llvm-readobj.h b/tools/llvm-readobj/llvm-readobj.h
index 0e02da4cb847..d9813f5dea62 100644
--- a/tools/llvm-readobj/llvm-readobj.h
+++ b/tools/llvm-readobj/llvm-readobj.h
@@ -21,30 +21,13 @@ namespace llvm {
}
// Various helper functions.
- LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
- void reportError(StringRef Input, Error Err);
- void reportWarning(Twine Msg);
- void warn(llvm::Error Err);
- void error(std::error_code EC);
- void error(llvm::Error EC);
- template <typename T> T error(llvm::Expected<T> &&E) {
- error(E.takeError());
- return std::move(*E);
- }
+ LLVM_ATTRIBUTE_NORETURN void reportError(Error Err, StringRef Input);
+ void reportWarning(Error Err, StringRef Input);
- template <class T> T unwrapOrError(ErrorOr<T> EO) {
- if (EO)
- return *EO;
- reportError(EO.getError().message());
- }
- template <class T> T unwrapOrError(Expected<T> EO) {
+ template <class T> T unwrapOrError(StringRef Input, Expected<T> EO) {
if (EO)
return *EO;
- std::string Buf;
- raw_string_ostream OS(Buf);
- logAllUnhandledErrors(EO.takeError(), OS);
- OS.flush();
- reportError(Buf);
+ reportError(EO.takeError(), Input);
}
} // namespace llvm