diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 | 
| commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
| tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /tools/llvm-readobj | |
| parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) | |
Notes
Diffstat (limited to 'tools/llvm-readobj')
| -rw-r--r-- | tools/llvm-readobj/ARMEHABIPrinter.h | 141 | ||||
| -rw-r--r-- | tools/llvm-readobj/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | tools/llvm-readobj/COFFDumper.cpp | 46 | ||||
| -rw-r--r-- | tools/llvm-readobj/COFFImportDumper.cpp | 3 | ||||
| -rw-r--r-- | tools/llvm-readobj/ELFDumper.cpp | 476 | ||||
| -rw-r--r-- | tools/llvm-readobj/ObjDumper.h | 16 | ||||
| -rw-r--r-- | tools/llvm-readobj/WasmDumper.cpp | 23 | ||||
| -rw-r--r-- | tools/llvm-readobj/WindowsResourceDumper.cpp | 82 | ||||
| -rw-r--r-- | tools/llvm-readobj/WindowsResourceDumper.h | 37 | ||||
| -rw-r--r-- | tools/llvm-readobj/llvm-readobj.cpp | 34 | 
10 files changed, 586 insertions, 277 deletions
diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h index 903a246ccfd8..4417aa60fe90 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 f5b1a5b256ad..dafc9e10cfa1 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 74c44116b127..8ac9f1a51cc5 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 c5b8bf758462..3b546b3ef508 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 5698420bbcc2..9678667abffe 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 43883c2d2176..c5b331d944a2 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 266226d59ee8..77711e749aa0 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 000000000000..1f568a963671 --- /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 000000000000..ca6da4046605 --- /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 7bfb18fab12b..c076582794fe 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());  | 
