summaryrefslogtreecommitdiff
path: root/tools/llvm-readobj
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-readobj')
-rw-r--r--tools/llvm-readobj/ARMEHABIPrinter.h141
-rw-r--r--tools/llvm-readobj/CMakeLists.txt5
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp46
-rw-r--r--tools/llvm-readobj/COFFImportDumper.cpp3
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp476
-rw-r--r--tools/llvm-readobj/ObjDumper.h16
-rw-r--r--tools/llvm-readobj/WasmDumper.cpp23
-rw-r--r--tools/llvm-readobj/WindowsResourceDumper.cpp82
-rw-r--r--tools/llvm-readobj/WindowsResourceDumper.h37
-rw-r--r--tools/llvm-readobj/llvm-readobj.cpp34
10 files changed, 586 insertions, 277 deletions
diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h
index 903a246ccfd8f..4417aa60fe903 100644
--- a/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -35,7 +35,7 @@ class OpcodeDecoder {
uint8_t Value;
void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI);
};
- static const RingEntry Ring[];
+ static ArrayRef<RingEntry> ring();
void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI);
void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI);
@@ -68,43 +68,48 @@ public:
void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);
};
-const OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = {
- { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx },
- { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx },
- { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii },
- { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 },
- { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 },
- { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn },
- { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn },
- { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn },
- { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 },
- { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii },
- { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 },
- { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc },
- { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn },
- { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn },
- { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc },
- { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii },
- { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc },
- { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc },
- { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy },
- { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn },
- { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn },
- { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy },
-};
+inline ArrayRef<OpcodeDecoder::RingEntry> OpcodeDecoder::ring() {
+ static const OpcodeDecoder::RingEntry Ring[] = {
+ {0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx},
+ {0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx},
+ {0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii},
+ {0xff, 0x9d, &OpcodeDecoder::Decode_10011101},
+ {0xff, 0x9f, &OpcodeDecoder::Decode_10011111},
+ {0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn},
+ {0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn},
+ {0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn},
+ {0xff, 0xb0, &OpcodeDecoder::Decode_10110000},
+ {0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii},
+ {0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128},
+ {0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc},
+ {0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn},
+ {0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn},
+ {0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc},
+ {0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii},
+ {0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc},
+ {0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc},
+ {0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy},
+ {0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn},
+ {0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn},
+ {0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy},
+ };
+ return makeArrayRef(Ring);
+}
-void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,
((Opcode & 0x3f) << 2) + 4);
}
-void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,
((Opcode & 0x3f) << 2) + 4);
}
-void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
@@ -116,36 +121,42 @@ void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
PrintGPR(GPRMask);
OS << '\n';
}
-void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode);
}
-void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode);
}
-void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
}
-void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; pop ", Opcode);
PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
OS << '\n';
}
-void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; pop ", Opcode);
PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
OS << '\n';
}
-void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; finish\n", Opcode);
}
-void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
@@ -156,8 +167,8 @@ void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
PrintGPR((Opcode1 & 0x0f));
OS << '\n';
}
-void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ", Opcode);
@@ -173,8 +184,8 @@ void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));
}
-void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
@@ -183,18 +194,20 @@ void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
OS << '\n';
}
-void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; spare\n", Opcode);
}
-void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; pop ", Opcode);
PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
OS << '\n';
}
-void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
@@ -203,8 +216,8 @@ void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
OS << '\n';
}
-void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
SW.startLine()
@@ -214,8 +227,8 @@ void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
PrintRegisters(Opcode1 & 0x0f, "wCGR");
OS << '\n';
}
-void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
@@ -224,8 +237,8 @@ void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
OS << '\n';
}
-void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
- unsigned &OI) {
+inline void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode0 = Opcodes[OI++ ^ 3];
uint8_t Opcode1 = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
@@ -234,28 +247,32 @@ void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
OS << '\n';
}
-void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; spare\n", Opcode);
}
-void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; pop ", Opcode);
PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
OS << '\n';
}
-void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; pop ", Opcode);
PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
OS << '\n';
}
-void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) {
+inline void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes,
+ unsigned &OI) {
uint8_t Opcode = Opcodes[OI++ ^ 3];
SW.startLine() << format("0x%02X ; spare\n", Opcode);
}
-void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
+inline void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
static const char *GPRRegisterNames[16] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"fp", "ip", "sp", "lr", "pc"
@@ -274,7 +291,7 @@ void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
OS << '}';
}
-void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
+inline void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
OS << '{';
bool Comma = false;
for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
@@ -288,13 +305,13 @@ void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
OS << '}';
}
-void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) {
+inline void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset,
+ size_t Length) {
for (unsigned OCI = Offset; OCI < Length + Offset; ) {
bool Decoded = false;
- for (unsigned REI = 0, REE = array_lengthof(Ring);
- REI != REE && !Decoded; ++REI) {
- if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) {
- (this->*Ring[REI].Routine)(Opcodes, OCI);
+ for (const auto &RE : ring()) {
+ if ((Opcodes[OCI ^ 3] & RE.Mask) == RE.Value) {
+ (this->*RE.Routine)(Opcodes, OCI);
Decoded = true;
break;
}
diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt
index f5b1a5b256add..dafc9e10cfa12 100644
--- a/tools/llvm-readobj/CMakeLists.txt
+++ b/tools/llvm-readobj/CMakeLists.txt
@@ -19,6 +19,11 @@ add_llvm_tool(llvm-readobj
ObjDumper.cpp
WasmDumper.cpp
Win64EHDumper.cpp
+ WindowsResourceDumper.cpp
)
add_llvm_tool_symlink(llvm-readelf llvm-readobj)
+
+if(LLVM_INSTALL_BINUTILS_SYMLINKS)
+ add_llvm_tool_symlink(readelf llvm-readobj)
+endif()
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 74c44116b1270..8ac9f1a51cc55 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -31,16 +31,16 @@
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
-#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ObjectFile.h"
@@ -48,17 +48,10 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Win64EH.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstring>
-#include <system_error>
-#include <time.h>
using namespace llvm;
using namespace llvm::object;
@@ -96,8 +89,9 @@ public:
void printCOFFResources() override;
void printCOFFLoadConfig() override;
void printCodeViewDebugInfo() override;
- void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs,
- llvm::codeview::TypeTableBuilder &CVTypes) override;
+ void
+ mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
+ llvm::codeview::MergingTypeTableBuilder &CVTypes) override;
void printStackMap() const override;
private:
void printSymbol(const SymbolRef &Sym);
@@ -1194,8 +1188,8 @@ void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) {
W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset);
}
-void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVIDs,
- TypeTableBuilder &CVTypes) {
+void COFFDumper::mergeCodeViewTypes(MergingTypeTableBuilder &CVIDs,
+ MergingTypeTableBuilder &CVTypes) {
for (const SectionRef &S : Obj->sections()) {
StringRef SectionName;
error(S.getName(SectionName));
@@ -1423,9 +1417,9 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
const coff_aux_weak_external *Aux;
error(getSymbolAuxData(Obj, Symbol, I, Aux));
- ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
+ Expected<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
StringRef LinkedName;
- std::error_code EC = Linked.getError();
+ std::error_code EC = errorToErrorCode(Linked.takeError());
if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) {
LinkedName = "";
error(EC);
@@ -1481,10 +1475,10 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
const coff_aux_clr_token *Aux;
error(getSymbolAuxData(Obj, Symbol, I, Aux));
- ErrorOr<COFFSymbolRef> ReferredSym =
+ Expected<COFFSymbolRef> ReferredSym =
Obj->getSymbol(Aux->SymbolTableIndex);
StringRef ReferredName;
- std::error_code EC = ReferredSym.getError();
+ std::error_code EC = errorToErrorCode(ReferredSym.takeError());
if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) {
ReferredName = "";
error(EC);
@@ -1627,7 +1621,7 @@ void COFFDumper::printCOFFDirectives() {
}
}
-static StringRef getBaseRelocTypeName(uint8_t Type) {
+static std::string getBaseRelocTypeName(uint8_t Type) {
switch (Type) {
case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";
case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";
@@ -1636,11 +1630,7 @@ static StringRef getBaseRelocTypeName(uint8_t Type) {
case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)";
case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
- default: {
- static std::string Result;
- Result = "unknown (" + llvm::utostr(Type) + ")";
- return Result;
- }
+ default: return "unknown (" + llvm::utostr(Type) + ")";
}
}
@@ -1807,13 +1797,13 @@ void COFFDumper::printStackMap() const {
StackMapV2Parser<support::big>(StackMapContentsArray));
}
-void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
- llvm::codeview::TypeTableBuilder &IDTable,
- llvm::codeview::TypeTableBuilder &CVTypes) {
+void llvm::dumpCodeViewMergedTypes(
+ ScopedPrinter &Writer, llvm::codeview::MergingTypeTableBuilder &IDTable,
+ llvm::codeview::MergingTypeTableBuilder &CVTypes) {
// Flatten it first, then run our dumper on it.
SmallString<0> TypeBuf;
- CVTypes.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) {
- TypeBuf.append(Record.begin(), Record.end());
+ CVTypes.ForEachRecord([&](TypeIndex TI, const CVType &Record) {
+ TypeBuf.append(Record.RecordData.begin(), Record.RecordData.end());
});
TypeTableCollection TpiTypes(CVTypes.records());
diff --git a/tools/llvm-readobj/COFFImportDumper.cpp b/tools/llvm-readobj/COFFImportDumper.cpp
index c5b8bf7584627..3b546b3ef508b 100644
--- a/tools/llvm-readobj/COFFImportDumper.cpp
+++ b/tools/llvm-readobj/COFFImportDumper.cpp
@@ -12,9 +12,6 @@
///
//===----------------------------------------------------------------------===//
-#include "Error.h"
-#include "ObjDumper.h"
-#include "llvm-readobj.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 5698420bbcc23..9678667abffe8 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -18,6 +18,7 @@
#include "StackMapPrinter.h"
#include "llvm-readobj.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallString.h"
@@ -33,6 +34,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/StackMapParser.h"
+#include "llvm/Support/AMDGPUMetadata.h"
#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/Casting.h"
@@ -155,8 +157,6 @@ public:
void printMipsReginfo() override;
void printMipsOptions() override;
- void printAMDGPUCodeObjectMetadata() override;
-
void printStackMap() const override;
void printHashHistogram() override;
@@ -820,12 +820,24 @@ static const EnumEntry<unsigned> ElfOSABI[] = {
{"AROS", "AROS", ELF::ELFOSABI_AROS},
{"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},
{"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},
- {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},
- {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX},
- {"ARM", "ARM", ELF::ELFOSABI_ARM},
{"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}
};
+static const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
+ {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA},
+ {"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL},
+ {"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D}
+};
+
+static const EnumEntry<unsigned> ARMElfOSABI[] = {
+ {"ARM", "ARM", ELF::ELFOSABI_ARM}
+};
+
+static const EnumEntry<unsigned> C6000ElfOSABI[] = {
+ {"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},
+ {"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX}
+};
+
static const EnumEntry<unsigned> ElfMachineType[] = {
ENUM_ENT(EM_NONE, "None"),
ENUM_ENT(EM_M32, "WE32100"),
@@ -967,7 +979,7 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
ENUM_ENT(EM_L10M, "EM_L10M"),
ENUM_ENT(EM_K10M, "EM_K10M"),
ENUM_ENT(EM_AARCH64, "AArch64"),
- ENUM_ENT(EM_AVR32, "Atmel AVR 8-bit microcontroller"),
+ ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"),
ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"),
ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"),
ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"),
@@ -1231,6 +1243,20 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6)
};
+static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = {
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_NONE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_R600),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_ARCH_GCN)
+};
+
+static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_RVC),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_SINGLE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_DOUBLE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_FLOAT_ABI_QUAD),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_RISCV_RVE)
+};
+
static const EnumEntry<unsigned> ElfSymOtherFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),
LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),
@@ -1287,15 +1313,16 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
switch (Sec.sh_type) {
case ELF::SHT_SYMTAB:
if (DotSymtabSec != nullptr)
- reportError("Multilpe SHT_SYMTAB");
+ reportError("Multiple SHT_SYMTAB");
DotSymtabSec = &Sec;
break;
case ELF::SHT_DYNSYM:
if (DynSymRegion.Size)
- reportError("Multilpe SHT_DYNSYM");
+ reportError("Multiple SHT_DYNSYM");
DynSymRegion = createDRIFrom(&Sec);
// This is only used (if Elf_Shdr present)for naming section in GNU style
DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
+ DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec));
break;
case ELF::SHT_SYMTAB_SHNDX:
ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
@@ -1312,7 +1339,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer)
break;
case ELF::SHT_GNU_verneed:
if (dot_gnu_version_r_sec != nullptr)
- reportError("Multilpe SHT_GNU_verneed");
+ reportError("Multiple SHT_GNU_verneed");
dot_gnu_version_r_sec = &Sec;
break;
}
@@ -1330,8 +1357,11 @@ template <typename ELFT>
void ELFDumper<ELFT>::parseDynamicTable(
ArrayRef<const Elf_Phdr *> LoadSegments) {
auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
- const Elf_Phdr *const *I = std::upper_bound(
- LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>);
+ const Elf_Phdr *const *I =
+ std::upper_bound(LoadSegments.begin(), LoadSegments.end(), VAddr,
+ [](uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
+ return VAddr < Phdr->p_vaddr;
+ });
if (I == LoadSegments.begin())
report_fatal_error("Virtual address is not in any segment");
--I;
@@ -1487,6 +1517,10 @@ static const char *getTypeString(unsigned Arch, uint64_t Type) {
}
}
switch (Type) {
+ LLVM_READOBJ_TYPE_CASE(ANDROID_REL);
+ LLVM_READOBJ_TYPE_CASE(ANDROID_RELSZ);
+ LLVM_READOBJ_TYPE_CASE(ANDROID_RELA);
+ LLVM_READOBJ_TYPE_CASE(ANDROID_RELASZ);
LLVM_READOBJ_TYPE_CASE(BIND_NOW);
LLVM_READOBJ_TYPE_CASE(DEBUG);
LLVM_READOBJ_TYPE_CASE(FINI);
@@ -1689,6 +1723,8 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) {
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_PREINIT_ARRAYSZ:
+ case DT_ANDROID_RELSZ:
+ case DT_ANDROID_RELASZ:
OS << Value << " (bytes)";
break;
case DT_NEEDED:
@@ -1874,6 +1910,7 @@ public:
MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
Elf_Dyn_Range DynTable, ScopedPrinter &W);
+ void parseStaticGOT();
void parseGOT();
void parsePLT();
@@ -1890,11 +1927,12 @@ private:
std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const;
const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
+ void printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num);
void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
const GOTEntry *It);
void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
const GOTEntry *It, const Elf_Sym *Sym,
- StringRef StrTable, bool IsDynamic);
+ StringRef StrTable);
void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
const GOTEntry *It, StringRef Purpose);
void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
@@ -1929,6 +1967,50 @@ MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
}
}
+template <class ELFT>
+void MipsGOTParser<ELFT>::printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num) {
+ ArrayRef<uint8_t> GOT = unwrapOrError(Obj->getSectionContents(GOTShdr));
+
+ const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
+ const GOTEntry *GotEnd = makeGOTIter(GOT, Num);
+ const GOTEntry *It = GotBegin;
+
+ W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0);
+ {
+ ListScope RS(W, "Reserved entries");
+
+ {
+ DictScope D(W, "Entry");
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
+ W.printString("Purpose", StringRef("Lazy resolver"));
+ }
+
+ if (It != GotEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
+ DictScope D(W, "Entry");
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
+ W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
+ }
+ }
+ {
+ ListScope LS(W, "Local entries");
+ for (; It != GotEnd; ++It) {
+ DictScope D(W, "Entry");
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It);
+ }
+ }
+}
+
+template <class ELFT> void MipsGOTParser<ELFT>::parseStaticGOT() {
+ const Elf_Shdr *GOTShdr = findSectionByName(*Obj, ".got");
+ if (!GOTShdr) {
+ W.startLine() << "Cannot find .got section.\n";
+ return;
+ }
+
+ DictScope GS(W, "Static GOT");
+ printLocalGOT(GOTShdr, GOTShdr->sh_size / sizeof(GOTEntry));
+}
+
template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed GOT description.
@@ -1946,10 +2028,7 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
return;
}
- StringRef StrTable = Dumper->getDynamicStringTable();
- const Elf_Sym *DynSymBegin = Dumper->dynamic_symbols().begin();
- const Elf_Sym *DynSymEnd = Dumper->dynamic_symbols().end();
- std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
+ std::size_t DynSymTotal = Dumper->dynamic_symbols().size();
if (*DtGotSym > DynSymTotal)
report_fatal_error("MIPS_GOTSYM exceeds a number of dynamic symbols");
@@ -1971,45 +2050,19 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(GOT))
report_fatal_error("Number of GOT entries exceeds the size of GOT section");
- const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
- const GOTEntry *GotLocalEnd = makeGOTIter(GOT, *DtLocalGotNum);
- const GOTEntry *It = GotBegin;
-
DictScope GS(W, "Primary GOT");
+ printLocalGOT(GOTShdr, *DtLocalGotNum);
- W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0);
- {
- ListScope RS(W, "Reserved entries");
-
- {
- DictScope D(W, "Entry");
- printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
- W.printString("Purpose", StringRef("Lazy resolver"));
- }
-
- if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
- DictScope D(W, "Entry");
- printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
- W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
- }
- }
- {
- ListScope LS(W, "Local entries");
- for (; It != GotLocalEnd; ++It) {
- DictScope D(W, "Entry");
- printGotEntry(GOTShdr->sh_addr, GotBegin, It);
- }
- }
{
ListScope GS(W, "Global entries");
- const GOTEntry *GotGlobalEnd =
- makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum);
- const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
- for (; It != GotGlobalEnd; ++It) {
+ const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
+ const GOTEntry *GotEnd = makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum);
+ const Elf_Sym *GotDynSym = Dumper->dynamic_symbols().begin() + *DtGotSym;
+ for (auto It = makeGOTIter(GOT, *DtLocalGotNum); It != GotEnd; ++It) {
DictScope D(W, "Entry");
- printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, StrTable,
- true);
+ printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++,
+ Dumper->getDynamicStringTable());
}
}
@@ -2101,9 +2154,11 @@ void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr,
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printGlobalGotEntry(
- uint64_t GotAddr, const GOTEntry *BeginIt, const GOTEntry *It,
- const Elf_Sym *Sym, StringRef StrTable, bool IsDynamic) {
+void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr,
+ const GOTEntry *BeginIt,
+ const GOTEntry *It,
+ const Elf_Sym *Sym,
+ StringRef StrTable) {
printGotEntry(GotAddr, BeginIt, It);
W.printHex("Value", Sym->st_value);
@@ -2115,8 +2170,7 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry(
Dumper->getShndxTable(), SectionName, SectionIndex);
W.printHex("Section", SectionName, SectionIndex);
- std::string FullSymbolName =
- Dumper->getFullSymbolName(Sym, StrTable, IsDynamic);
+ std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);
W.printNumber("Name", FullSymbolName, Sym->st_name);
}
@@ -2160,8 +2214,12 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
}
MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W);
- GOTParser.parseGOT();
- GOTParser.parsePLT();
+ if (dynamic_table().empty())
+ GOTParser.parseStaticGOT();
+ else {
+ GOTParser.parseGOT();
+ GOTParser.parsePLT();
+ }
}
static const EnumEntry<unsigned> ElfMipsISAExtType[] = {
@@ -2326,36 +2384,6 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
}
}
-template <class ELFT> void ELFDumper<ELFT>::printAMDGPUCodeObjectMetadata() {
- const Elf_Shdr *Shdr = findSectionByName(*Obj, ".note");
- if (!Shdr) {
- W.startLine() << "There is no .note section in the file.\n";
- return;
- }
- ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr));
-
- const uint32_t CodeObjectMetadataNoteType = 10;
- for (auto I = reinterpret_cast<const Elf_Word *>(&Sec[0]),
- E = I + Sec.size()/4; I != E;) {
- uint32_t NameSZ = I[0];
- uint32_t DescSZ = I[1];
- uint32_t Type = I[2];
- I += 3;
-
- StringRef Name;
- if (NameSZ) {
- Name = StringRef(reinterpret_cast<const char *>(I), NameSZ - 1);
- I += alignTo<4>(NameSZ)/4;
- }
-
- if (Name == "AMD" && Type == CodeObjectMetadataNoteType) {
- StringRef Desc(reinterpret_cast<const char *>(I), DescSZ);
- W.printString(Desc);
- }
- I += alignTo<4>(DescSZ)/4;
- }
-}
-
template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
const Elf_Shdr *StackMapSection = nullptr;
for (const auto &Sec : unwrapOrError(Obj->sections())) {
@@ -2369,7 +2397,6 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
if (!StackMapSection)
return;
- StringRef StackMapContents;
ArrayRef<uint8_t> StackMapContentsArray =
unwrapOrError(Obj->getSectionContents(StackMapSection));
@@ -2441,34 +2468,91 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
printFields(OS, "Section header string table index:", Str);
}
-template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
- uint32_t SectionIndex = 0;
- bool HasGroups = false;
+namespace {
+struct GroupMember {
+ StringRef Name;
+ uint64_t Index;
+};
+
+struct GroupSection {
+ StringRef Name;
+ StringRef Signature;
+ uint64_t ShName;
+ uint64_t Index;
+ uint32_t Type;
+ std::vector<GroupMember> Members;
+};
+
+template <class ELFT>
+std::vector<GroupSection> getGroups(const ELFFile<ELFT> *Obj) {
+ using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
+ using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
+ using Elf_Word = typename ELFFile<ELFT>::Elf_Word;
+
+ std::vector<GroupSection> Ret;
+ uint64_t I = 0;
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type == ELF::SHT_GROUP) {
- HasGroups = true;
- const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link));
- StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab));
- const Elf_Sym *Signature =
- unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info));
- ArrayRef<Elf_Word> Data = unwrapOrError(
- Obj->template getSectionContentsAsArray<Elf_Word>(&Sec));
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
- OS << "\n" << getGroupType(Data[0]) << " group section ["
- << format_decimal(SectionIndex, 5) << "] `" << Name << "' ["
- << StrTable.data() + Signature->st_name << "] contains "
- << (Data.size() - 1) << " sections:\n"
- << " [Index] Name\n";
- for (auto &Ndx : Data.slice(1)) {
- auto Sec = unwrapOrError(Obj->getSection(Ndx));
- const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
- OS << " [" << format_decimal(Ndx, 5) << "] " << Name
- << "\n";
+ ++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));
+
+ StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
+ StringRef Signature = StrTable.data() + Sym->st_name;
+ Ret.push_back({Name, Signature, Sec.sh_name, I - 1, Data[0], {}});
+
+ 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));
+ GM.push_back({Name, Ndx});
+ }
+ }
+ return Ret;
+}
+
+DenseMap<uint64_t, const GroupSection *>
+mapSectionsToGroups(ArrayRef<GroupSection> Groups) {
+ DenseMap<uint64_t, const GroupSection *> Ret;
+ for (const GroupSection &G : Groups)
+ for (const GroupMember &GM : G.Members)
+ Ret.insert({GM.Index, &G});
+ return Ret;
+}
+
+} // namespace
+
+template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) {
+ std::vector<GroupSection> V = getGroups<ELFT>(Obj);
+ DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
+ for (const GroupSection &G : V) {
+ OS << "\n"
+ << getGroupType(G.Type) << " group section ["
+ << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature
+ << "] contains " << G.Members.size() << " sections:\n"
+ << " [Index] Name\n";
+ for (const GroupMember &GM : G.Members) {
+ const GroupSection *MainGroup = Map[GM.Index];
+ if (MainGroup != &G) {
+ OS.flush();
+ errs() << "Error: section [" << format_decimal(GM.Index, 5)
+ << "] in group section [" << format_decimal(G.Index, 5)
+ << "] already in group section ["
+ << format_decimal(MainGroup->Index, 5) << "]";
+ errs().flush();
+ continue;
}
+ OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n";
}
- ++SectionIndex;
}
- if (!HasGroups)
+
+ if (V.empty())
OS << "There are no section groups in this file.\n";
}
@@ -2539,7 +2623,9 @@ static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) {
template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
bool HasRelocSections = false;
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
+ if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
+ Sec.sh_type != ELF::SHT_ANDROID_REL &&
+ Sec.sh_type != ELF::SHT_ANDROID_RELA)
continue;
HasRelocSections = true;
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
@@ -2548,9 +2634,12 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
OS << "\nRelocation section '" << Name << "' at offset 0x"
<< to_hexString(Offset, false) << " contains " << Entries
<< " entries:\n";
- printRelocHeader(OS, ELFT::Is64Bits, (Sec.sh_type == ELF::SHT_RELA));
+ printRelocHeader(OS, ELFT::Is64Bits,
+ Sec.sh_type == ELF::SHT_RELA ||
+ Sec.sh_type == ELF::SHT_ANDROID_RELA);
const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link));
- if (Sec.sh_type == ELF::SHT_REL) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_REL:
for (const auto &R : unwrapOrError(Obj->rels(&Sec))) {
Elf_Rela Rela;
Rela.r_offset = R.r_offset;
@@ -2558,9 +2647,16 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
Rela.r_addend = 0;
printRelocation(Obj, SymTab, Rela, false);
}
- } else {
+ break;
+ case ELF::SHT_RELA:
for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
printRelocation(Obj, SymTab, R, true);
+ break;
+ case ELF::SHT_ANDROID_REL:
+ case ELF::SHT_ANDROID_RELA:
+ for (const auto &R : unwrapOrError(Obj->android_relas(&Sec)))
+ printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA);
+ break;
}
}
if (!HasRelocSections)
@@ -3310,7 +3406,7 @@ static std::string getGNUNoteTypeName(const uint32_t NT) {
std::string string;
raw_string_ostream OS(string);
OS << format("Unknown note type (0x%08x)", NT);
- return string;
+ return OS.str();
}
static std::string getFreeBSDNoteTypeName(const uint32_t NT) {
@@ -3338,7 +3434,30 @@ static std::string getFreeBSDNoteTypeName(const uint32_t NT) {
std::string string;
raw_string_ostream OS(string);
OS << format("Unknown note type (0x%08x)", NT);
- return string;
+ return OS.str();
+}
+
+static std::string getAMDGPUNoteTypeName(const uint32_t NT) {
+ static const struct {
+ uint32_t ID;
+ const char *Name;
+ } Notes[] = {
+ {ELF::NT_AMD_AMDGPU_HSA_METADATA,
+ "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"},
+ {ELF::NT_AMD_AMDGPU_ISA,
+ "NT_AMD_AMDGPU_ISA (ISA Version)"},
+ {ELF::NT_AMD_AMDGPU_PAL_METADATA,
+ "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"}
+ };
+
+ for (const auto &Note : Notes)
+ if (Note.ID == NT)
+ return std::string(Note.Name);
+
+ std::string string;
+ raw_string_ostream OS(string);
+ OS << format("Unknown note type (0x%08x)", NT);
+ return OS.str();
}
template <typename ELFT>
@@ -3381,6 +3500,39 @@ static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
OS << '\n';
}
+template <typename ELFT>
+static void printAMDGPUNote(raw_ostream &OS, uint32_t NoteType,
+ ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words,
+ size_t Size) {
+ switch (NoteType) {
+ default:
+ return;
+ case ELF::NT_AMD_AMDGPU_HSA_METADATA:
+ OS << " HSA Metadata:\n"
+ << StringRef(reinterpret_cast<const char *>(Words.data()), Size);
+ break;
+ case ELF::NT_AMD_AMDGPU_ISA:
+ OS << " ISA Version:\n"
+ << " "
+ << StringRef(reinterpret_cast<const char *>(Words.data()), Size);
+ break;
+ case ELF::NT_AMD_AMDGPU_PAL_METADATA:
+ const uint32_t *PALMetadataBegin = reinterpret_cast<const uint32_t *>(Words.data());
+ const uint32_t *PALMetadataEnd = PALMetadataBegin + Size;
+ std::vector<uint32_t> PALMetadata(PALMetadataBegin, PALMetadataEnd);
+ std::string PALMetadataString;
+ auto Error = AMDGPU::PALMD::toString(PALMetadata, PALMetadataString);
+ OS << " PAL Metadata:\n";
+ if (Error) {
+ OS << " Invalid";
+ return;
+ }
+ OS << PALMetadataString;
+ break;
+ }
+ OS.flush();
+}
+
template <class ELFT>
void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
const Elf_Ehdr *e = Obj->getHeader();
@@ -3421,6 +3573,9 @@ void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
printGNUNote<ELFT>(OS, Type, Descriptor, DescriptorSize);
} else if (Name == "FreeBSD") {
OS << getFreeBSDNoteTypeName(Type) << '\n';
+ } else if (Name == "AMD") {
+ OS << getAMDGPUNoteTypeName(Type) << '\n';
+ printAMDGPUNote<ELFT>(OS, Type, Descriptor, DescriptorSize);
} else {
OS << "Unknown note type: (" << format_hex(Type, 10) << ')';
}
@@ -3454,13 +3609,22 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
makeArrayRef(ElfDataEncoding));
W.printNumber("FileVersion", e->e_ident[ELF::EI_VERSION]);
- // Handle architecture specific OS/ABI values.
- if (e->e_machine == ELF::EM_AMDGPU &&
- e->e_ident[ELF::EI_OSABI] == ELF::ELFOSABI_AMDGPU_HSA)
- W.printHex("OS/ABI", "AMDGPU_HSA", ELF::ELFOSABI_AMDGPU_HSA);
- else
- W.printEnum("OS/ABI", e->e_ident[ELF::EI_OSABI],
- makeArrayRef(ElfOSABI));
+ auto OSABI = makeArrayRef(ElfOSABI);
+ if (e->e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&
+ e->e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {
+ switch (e->e_machine) {
+ case ELF::EM_AMDGPU:
+ OSABI = makeArrayRef(AMDGPUElfOSABI);
+ break;
+ case ELF::EM_ARM:
+ OSABI = makeArrayRef(ARMElfOSABI);
+ break;
+ case ELF::EM_TI_C6000:
+ OSABI = makeArrayRef(C6000ElfOSABI);
+ break;
+ }
+ }
+ W.printEnum("OS/ABI", e->e_ident[ELF::EI_OSABI], OSABI);
W.printNumber("ABIVersion", e->e_ident[ELF::EI_ABIVERSION]);
W.printBinary("Unused", makeArrayRef(e->e_ident).slice(ELF::EI_PAD));
}
@@ -3475,6 +3639,11 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderMipsFlags),
unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
unsigned(ELF::EF_MIPS_MACH));
+ else if (e->e_machine == EM_AMDGPU)
+ W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderAMDGPUFlags),
+ unsigned(ELF::EF_AMDGPU_ARCH));
+ else if (e->e_machine == EM_RISCV)
+ W.printFlags("Flags", e->e_flags, makeArrayRef(ElfHeaderRISCVFlags));
else
W.printFlags("Flags", e->e_flags);
W.printNumber("HeaderSize", e->e_ehsize);
@@ -3489,36 +3658,32 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) {
template <class ELFT>
void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) {
DictScope Lists(W, "Groups");
- uint32_t SectionIndex = 0;
- bool HasGroups = false;
- for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
- if (Sec.sh_type == ELF::SHT_GROUP) {
- HasGroups = true;
- 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));
- DictScope D(W, "Group");
- StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
- W.printNumber("Name", Name, Sec.sh_name);
- W.printNumber("Index", SectionIndex);
- W.printHex("Type", getGroupType(Data[0]), Data[0]);
- W.startLine() << "Signature: " << StrTable.data() + Sym->st_name << "\n";
- {
- ListScope L(W, "Section(s) in group");
- size_t Member = 1;
- while (Member < Data.size()) {
- auto Sec = unwrapOrError(Obj->getSection(Data[Member]));
- const StringRef Name = unwrapOrError(Obj->getSectionName(Sec));
- W.startLine() << Name << " (" << Data[Member++] << ")\n";
- }
+ std::vector<GroupSection> V = getGroups<ELFT>(Obj);
+ DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
+ for (const GroupSection &G : V) {
+ DictScope D(W, "Group");
+ W.printNumber("Name", G.Name, G.ShName);
+ W.printNumber("Index", G.Index);
+ W.printHex("Type", getGroupType(G.Type), G.Type);
+ W.startLine() << "Signature: " << G.Signature << "\n";
+
+ ListScope L(W, "Section(s) in group");
+ for (const GroupMember &GM : G.Members) {
+ const GroupSection *MainGroup = Map[GM.Index];
+ if (MainGroup != &G) {
+ W.flush();
+ errs() << "Error: " << GM.Name << " (" << GM.Index
+ << ") in a group " + G.Name + " (" << G.Index
+ << ") is already in a group " + MainGroup->Name + " ("
+ << MainGroup->Index << ")\n";
+ errs().flush();
+ continue;
}
+ W.startLine() << GM.Name << " (" << GM.Index << ")\n";
}
- ++SectionIndex;
}
- if (!HasGroups)
+
+ if (V.empty())
W.startLine() << "There are no group sections in the file.\n";
}
@@ -3529,7 +3694,9 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
++SectionNumber;
- if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
+ if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA &&
+ Sec.sh_type != ELF::SHT_ANDROID_REL &&
+ Sec.sh_type != ELF::SHT_ANDROID_RELA)
continue;
StringRef Name = unwrapOrError(Obj->getSectionName(&Sec));
@@ -3562,6 +3729,11 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec)))
printRelocation(Obj, R, SymTab);
break;
+ case ELF::SHT_ANDROID_REL:
+ case ELF::SHT_ANDROID_RELA:
+ for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec)))
+ printRelocation(Obj, R, SymTab);
+ break;
}
}
diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h
index 43883c2d21766..c5b331d944a20 100644
--- a/tools/llvm-readobj/ObjDumper.h
+++ b/tools/llvm-readobj/ObjDumper.h
@@ -19,7 +19,7 @@ class COFFImportFile;
class ObjectFile;
}
namespace codeview {
-class TypeTableBuilder;
+class MergingTypeTableBuilder;
}
class ScopedPrinter;
@@ -58,9 +58,6 @@ public:
virtual void printMipsReginfo() { }
virtual void printMipsOptions() { }
- // Only implemented for AMDGPU ELF at this time.
- virtual void printAMDGPUCodeObjectMetadata() {}
-
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
virtual void printCOFFExports() { }
@@ -70,8 +67,9 @@ public:
virtual void printCOFFResources() {}
virtual void printCOFFLoadConfig() { }
virtual void printCodeViewDebugInfo() { }
- virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs,
- llvm::codeview::TypeTableBuilder &CVTypes) {}
+ virtual void
+ mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
+ llvm::codeview::MergingTypeTableBuilder &CVTypes) {}
// Only implemented for MachO.
virtual void printMachODataInCode() { }
@@ -105,9 +103,9 @@ std::error_code createWasmDumper(const object::ObjectFile *Obj,
void dumpCOFFImportFile(const object::COFFImportFile *File);
-void dumpCodeViewMergedTypes(ScopedPrinter &Writer,
- llvm::codeview::TypeTableBuilder &IDTable,
- llvm::codeview::TypeTableBuilder &TypeTable);
+void dumpCodeViewMergedTypes(
+ ScopedPrinter &Writer, llvm::codeview::MergingTypeTableBuilder &IDTable,
+ llvm::codeview::MergingTypeTableBuilder &TypeTable);
} // namespace llvm
diff --git a/tools/llvm-readobj/WasmDumper.cpp b/tools/llvm-readobj/WasmDumper.cpp
index 266226d59ee87..77711e749aa09 100644
--- a/tools/llvm-readobj/WasmDumper.cpp
+++ b/tools/llvm-readobj/WasmDumper.cpp
@@ -83,9 +83,9 @@ void WasmDumper::printRelocation(const SectionRef &Section,
bool HasAddend = false;
switch (RelocType) {
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
HasAddend = true;
break;
default:
@@ -148,7 +148,7 @@ void WasmDumper::printSections() {
const WasmSection &WasmSec = Obj->getWasmSection(Section);
DictScope SectionD(W, "Section");
W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
- W.printNumber("Size", (uint64_t)WasmSec.Content.size());
+ W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
W.printNumber("Offset", WasmSec.Offset);
switch (WasmSec.Type) {
case wasm::WASM_SEC_CUSTOM:
@@ -156,10 +156,21 @@ void WasmDumper::printSections() {
if (WasmSec.Name == "linking") {
const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
W.printNumber("DataSize", LinkingData.DataSize);
- if (LinkingData.DataAlignment)
- W.printNumber("DataAlignment", LinkingData.DataAlignment);
}
break;
+ case wasm::WASM_SEC_DATA: {
+ ListScope Group(W, "Segments");
+ for (const WasmSegment &Segment : Obj->dataSegments()) {
+ const wasm::WasmDataSegment& Seg = Segment.Data;
+ DictScope Group(W, "Segment");
+ if (!Seg.Name.empty())
+ W.printString("Name", Seg.Name);
+ W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
+ if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
+ W.printNumber("Offset", Seg.Offset.Value.Int32);
+ }
+ break;
+ }
case wasm::WASM_SEC_MEMORY:
ListScope Group(W, "Memories");
for (const wasm::WasmLimits &Memory : Obj->memories()) {
diff --git a/tools/llvm-readobj/WindowsResourceDumper.cpp b/tools/llvm-readobj/WindowsResourceDumper.cpp
new file mode 100644
index 0000000000000..1f568a9636712
--- /dev/null
+++ b/tools/llvm-readobj/WindowsResourceDumper.cpp
@@ -0,0 +1,82 @@
+//===-- WindowsResourceDumper.cpp - Windows Resource printer --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Windows resource (.res) dumper for llvm-readobj.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WindowsResourceDumper.h"
+#include "Error.h"
+#include "llvm/Object/WindowsResource.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+namespace llvm {
+namespace object {
+namespace WindowsRes {
+
+std::string stripUTF16(const ArrayRef<UTF16> &UTF16Str) {
+ std::string Result;
+ Result.reserve(UTF16Str.size());
+
+ for (UTF16 Ch : UTF16Str) {
+ // UTF16Str will have swapped byte order in case of big-endian machines.
+ // Swap it back in such a case.
+ uint16_t ChValue = support::endian::byte_swap(Ch, support::little);
+ if (ChValue <= 0xFF)
+ Result += ChValue;
+ else
+ Result += '?';
+ }
+ return Result;
+}
+
+Error Dumper::printData() {
+ auto EntryPtrOrErr = WinRes->getHeadEntry();
+ if (!EntryPtrOrErr)
+ return EntryPtrOrErr.takeError();
+ auto EntryPtr = *EntryPtrOrErr;
+
+ bool IsEnd = false;
+ while (!IsEnd) {
+ printEntry(EntryPtr);
+
+ if (auto Err = EntryPtr.moveNext(IsEnd))
+ return Err;
+ }
+ return Error::success();
+}
+
+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());
+
+ if (Ref.checkNameString()) {
+ auto NarrowStr = stripUTF16(Ref.getNameString());
+ SW.printString("Resource name (string)", NarrowStr);
+ } else
+ SW.printNumber("Resource name (int)", Ref.getNameID());
+
+ SW.printNumber("Data version", Ref.getDataVersion());
+ SW.printHex("Memory flags", Ref.getMemoryFlags());
+ SW.printNumber("Language ID", Ref.getLanguage());
+ SW.printNumber("Version (major)", Ref.getMajorVersion());
+ SW.printNumber("Version (minor)", Ref.getMinorVersion());
+ SW.printNumber("Characteristics", Ref.getCharacteristics());
+ SW.printNumber("Data size", (uint64_t)Ref.getData().size());
+ SW.printBinary("Data:", Ref.getData());
+ SW.startLine() << "\n";
+}
+
+} // namespace WindowsRes
+} // namespace object
+} // namespace llvm
diff --git a/tools/llvm-readobj/WindowsResourceDumper.h b/tools/llvm-readobj/WindowsResourceDumper.h
new file mode 100644
index 0000000000000..ca6da40466052
--- /dev/null
+++ b/tools/llvm-readobj/WindowsResourceDumper.h
@@ -0,0 +1,37 @@
+//===- WindowsResourceDumper.h - Windows Resource printer -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_READOBJ_WINDOWSRESOURCEDUMPER_H
+#define LLVM_TOOLS_LLVM_READOBJ_WINDOWSRESOURCEDUMPER_H
+
+#include "llvm/Object/WindowsResource.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+namespace llvm {
+namespace object {
+namespace WindowsRes {
+
+class Dumper {
+public:
+ Dumper(WindowsResource *Res, ScopedPrinter &SW) : SW(SW), WinRes(Res) {}
+
+ Error printData();
+
+private:
+ ScopedPrinter &SW;
+ WindowsResource *WinRes;
+
+ void printEntry(const ResourceEntryRef &Ref);
+};
+
+} // namespace WindowsRes
+} // namespace object
+} // namespace llvm
+
+#endif
diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp
index 7bfb18fab12b6..c076582794fe4 100644
--- a/tools/llvm-readobj/llvm-readobj.cpp
+++ b/tools/llvm-readobj/llvm-readobj.cpp
@@ -22,12 +22,13 @@
#include "llvm-readobj.h"
#include "Error.h"
#include "ObjDumper.h"
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "WindowsResourceDumper.h"
+#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFFImportFile.h"
-#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/WindowsResource.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h"
@@ -39,9 +40,6 @@
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/TargetSelect.h"
-#include <string>
-#include <system_error>
using namespace llvm;
using namespace llvm::object;
@@ -198,11 +196,6 @@ namespace opts {
cl::opt<bool> MipsOptions("mips-options",
cl::desc("Display the MIPS .MIPS.options section"));
- // -amdgpu-code-object-metadata
- cl::opt<bool> AMDGPUCodeObjectMetadata(
- "amdgpu-code-object-metadata",
- cl::desc("Display AMDGPU code object metadata"));
-
// -coff-imports
cl::opt<bool>
COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
@@ -356,8 +349,8 @@ struct ReadObjTypeTableBuilder {
: Allocator(), IDTable(Allocator), TypeTable(Allocator) {}
llvm::BumpPtrAllocator Allocator;
- llvm::codeview::TypeTableBuilder IDTable;
- llvm::codeview::TypeTableBuilder TypeTable;
+ llvm::codeview::MergingTypeTableBuilder IDTable;
+ llvm::codeview::MergingTypeTableBuilder TypeTable;
};
}
static ReadObjTypeTableBuilder CVTypes;
@@ -438,9 +431,6 @@ static void dumpObject(const ObjectFile *Obj) {
if (opts::MipsOptions)
Dumper->printMipsOptions();
}
- if (Obj->getArch() == llvm::Triple::amdgcn)
- if (opts::AMDGPUCodeObjectMetadata)
- Dumper->printAMDGPUCodeObjectMetadata();
if (opts::SectionGroups)
Dumper->printGroupSections();
if (opts::HashHistogram)
@@ -522,6 +512,15 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) {
}
}
+/// @brief Dumps \a WinRes, Windows Resource (.res) file;
+static void dumpWindowsResourceFile(WindowsResource *WinRes) {
+ ScopedPrinter Printer{outs()};
+ WindowsRes::Dumper Dumper(WinRes, Printer);
+ if (auto Err = Dumper.printData())
+ reportError(WinRes->getFileName(), std::move(Err));
+}
+
+
/// @brief Opens \a File and dumps it.
static void dumpInput(StringRef File) {
@@ -540,6 +539,8 @@ static void dumpInput(StringRef File) {
dumpObject(Obj);
else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary))
dumpCOFFImportFile(Import);
+ else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary))
+ dumpWindowsResourceFile(WinRes);
else
reportError(File, readobj_error::unrecognized_file_format);
}
@@ -564,8 +565,7 @@ int main(int argc, const char *argv[]) {
if (opts::InputFilenames.size() == 0)
opts::InputFilenames.push_back("-");
- std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
- dumpInput);
+ llvm::for_each(opts::InputFilenames, dumpInput);
if (opts::CodeViewMergedTypes) {
ScopedPrinter W(outs());