summaryrefslogtreecommitdiffstats
path: root/tools/llvm-readobj
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
committerStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
commitdce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch)
treedcebc53f2b182f145a2e659393bf9a0472cedf23 /tools/llvm-readobj
parent220b921aed042f9e520c26cffd8282a94c66c3d5 (diff)
downloadexternal_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'tools/llvm-readobj')
-rw-r--r--tools/llvm-readobj/ARMAttributeParser.cpp102
-rw-r--r--tools/llvm-readobj/ARMEHABIPrinter.h13
-rw-r--r--tools/llvm-readobj/CMakeLists.txt9
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp464
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp94
-rw-r--r--tools/llvm-readobj/StreamWriter.h29
-rw-r--r--tools/llvm-readobj/Win64EHDumper.cpp328
-rw-r--r--tools/llvm-readobj/Win64EHDumper.h62
8 files changed, 620 insertions, 481 deletions
diff --git a/tools/llvm-readobj/ARMAttributeParser.cpp b/tools/llvm-readobj/ARMAttributeParser.cpp
index 5857547..d35cd14 100644
--- a/tools/llvm-readobj/ARMAttributeParser.cpp
+++ b/tools/llvm-readobj/ARMAttributeParser.cpp
@@ -9,6 +9,7 @@
#include "ARMAttributeParser.h"
#include "StreamWriter.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LEB128.h"
@@ -22,11 +23,6 @@ static const EnumEntry<unsigned> TagNames[] = {
{ "Tag_Symbol", ARMBuildAttrs::Symbol },
};
-template <typename type_, size_t size_>
-size_t countof(const type_ (&)[size_]) {
- return size_;
-}
-
namespace llvm {
#define ATTRIBUTE_HANDLER(Attr_) \
{ ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ }
@@ -129,7 +125,8 @@ void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -155,7 +152,8 @@ void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -164,7 +162,8 @@ void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -176,7 +175,8 @@ void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -185,7 +185,8 @@ void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -196,7 +197,8 @@ void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -208,7 +210,8 @@ void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -217,7 +220,8 @@ void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "v6", "Static Base", "TLS", "Unused" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -228,7 +232,8 @@ void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -237,7 +242,8 @@ void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Absolute", "PC-relative", "Not Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -246,7 +252,8 @@ void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "Direct", "GOT-Indirect" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -257,7 +264,8 @@ void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -266,7 +274,8 @@ void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "IEEE-754", "Runtime" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -275,7 +284,8 @@ void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Unsupported", "IEEE-754", "Sign Only" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -284,7 +294,8 @@ void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "IEEE-754" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -294,7 +305,8 @@ void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag,
static const char *Strings[] = { "Not Permitted", "IEEE-754" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -305,7 +317,8 @@ void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -318,7 +331,7 @@ void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data,
uint64_t Value = ParseInteger(Data, Offset);
std::string Description;
- if (Value < countof(Strings))
+ if (Value < array_lengthof(Strings))
Description = std::string(Strings[Value]);
else if (Value <= 12)
Description = std::string("8-byte alignment, ") + utostr(1 << Value)
@@ -339,7 +352,7 @@ void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data,
uint64_t Value = ParseInteger(Data, Offset);
std::string Description;
- if (Value < countof(Strings))
+ if (Value < array_lengthof(Strings))
Description = std::string(Strings[Value]);
else if (Value <= 12)
Description = std::string("8-byte stack alignment, ") + utostr(1 << Value)
@@ -357,7 +370,8 @@ void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -368,7 +382,8 @@ void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -379,7 +394,8 @@ void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -388,7 +404,8 @@ void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "AAPCS", "iWMMX", "Custom" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -401,7 +418,8 @@ void ARMAttributeParser::ABI_optimization_goals(AttrType Tag,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -414,7 +432,8 @@ void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -445,7 +464,8 @@ void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "v6-style" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -454,7 +474,8 @@ void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "If Available", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -463,7 +484,8 @@ void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -472,7 +494,8 @@ void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -483,7 +506,8 @@ void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -492,7 +516,8 @@ void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data,
static const char *Strings[] = { "Not Permitted", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -504,7 +529,8 @@ void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data,
};
uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL;
+ StringRef ValueDesc =
+ (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
PrintAttribute(Tag, Value, ValueDesc);
}
@@ -534,7 +560,7 @@ void ARMAttributeParser::ParseAttributeList(const uint8_t *Data,
Offset += Length;
bool Handled = false;
- for (unsigned AHI = 0, AHE = countof(DisplayRoutines);
+ for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines);
AHI != AHE && !Handled; ++AHI) {
if (DisplayRoutines[AHI].Attribute == Tag) {
(this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag),
diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h
index 75e2bee..7608cfb 100644
--- a/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -12,6 +12,7 @@
#include "Error.h"
#include "StreamWriter.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Support/ARMEHABI.h"
@@ -20,13 +21,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/type_traits.h"
-namespace {
-template <typename type_, size_t N>
-size_t countof(const type_ (&)[N]) {
- return N;
-}
-}
-
namespace llvm {
namespace ARM {
namespace EHABI {
@@ -296,7 +290,8 @@ void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
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 = countof(Ring); REI != REE && !Decoded; ++REI) {
+ 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);
Decoded = true;
@@ -390,7 +385,7 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
}
}
}
- return NULL;
+ return nullptr;
}
template <typename ET>
diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt
index 036185d..b057dcd 100644
--- a/tools/llvm-readobj/CMakeLists.txt
+++ b/tools/llvm-readobj/CMakeLists.txt
@@ -5,12 +5,13 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_tool(llvm-readobj
- llvm-readobj.cpp
- ObjDumper.cpp
+ ARMAttributeParser.cpp
COFFDumper.cpp
ELFDumper.cpp
- MachODumper.cpp
Error.cpp
+ llvm-readobj.cpp
+ MachODumper.cpp
+ ObjDumper.cpp
StreamWriter.cpp
- ARMAttributeParser.cpp
+ Win64EHDumper.cpp
)
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index cd40da7..91f2a57 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -16,6 +16,7 @@
#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
+#include "Win64EHDumper.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Object/COFF.h"
@@ -58,45 +59,24 @@ private:
void printSymbol(const SymbolRef &Sym);
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
void printDataDirectory(uint32_t Index, const std::string &FieldName);
- void printX64UnwindInfo();
template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
void printBaseOfDataField(const pe32_header *Hdr);
void printBaseOfDataField(const pe32plus_header *Hdr);
- void printRuntimeFunction(
- const RuntimeFunction& RTF,
- uint64_t OffsetInSection,
- const std::vector<RelocationRef> &Rels);
-
- void printUnwindInfo(
- const Win64EH::UnwindInfo& UI,
- uint64_t OffsetInSection,
- const std::vector<RelocationRef> &Rels);
-
- void printUnwindCode(const Win64EH::UnwindInfo &UI, ArrayRef<UnwindCode> UCs);
-
void printCodeViewLineTables(const SectionRef &Section);
void cacheRelocations();
- error_code getSectionContents(
- const std::vector<RelocationRef> &Rels,
- uint64_t Offset,
- ArrayRef<uint8_t> &Contents,
- uint64_t &Addr);
-
- error_code getSection(
- const std::vector<RelocationRef> &Rels,
- uint64_t Offset,
- const coff_section **Section,
- uint64_t *AddrPtr);
+ error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
+ SymbolRef &Sym);
+ error_code resolveSymbolName(const coff_section *Section, uint64_t Offset,
+ StringRef &Name);
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
const llvm::object::COFFObjectFile *Obj;
RelocMapTy RelocMap;
- std::vector<RelocationRef> EmptyRelocs;
};
} // namespace
@@ -116,110 +96,33 @@ error_code createCOFFDumper(const object::ObjectFile *Obj, StreamWriter &Writer,
} // namespace llvm
-
-// Returns the name of the unwind code.
-static StringRef getUnwindCodeTypeName(uint8_t Code) {
- switch(Code) {
- default: llvm_unreachable("Invalid unwind code");
- case UOP_PushNonVol: return "PUSH_NONVOL";
- case UOP_AllocLarge: return "ALLOC_LARGE";
- case UOP_AllocSmall: return "ALLOC_SMALL";
- case UOP_SetFPReg: return "SET_FPREG";
- case UOP_SaveNonVol: return "SAVE_NONVOL";
- case UOP_SaveNonVolBig: return "SAVE_NONVOL_FAR";
- case UOP_SaveXMM128: return "SAVE_XMM128";
- case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR";
- case UOP_PushMachFrame: return "PUSH_MACHFRAME";
- }
-}
-
-// Returns the name of a referenced register.
-static StringRef getUnwindRegisterName(uint8_t Reg) {
- switch(Reg) {
- default: llvm_unreachable("Invalid register");
- case 0: return "RAX";
- case 1: return "RCX";
- case 2: return "RDX";
- case 3: return "RBX";
- case 4: return "RSP";
- case 5: return "RBP";
- case 6: return "RSI";
- case 7: return "RDI";
- case 8: return "R8";
- case 9: return "R9";
- case 10: return "R10";
- case 11: return "R11";
- case 12: return "R12";
- case 13: return "R13";
- case 14: return "R14";
- case 15: return "R15";
- }
-}
-
-// Calculates the number of array slots required for the unwind code.
-static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
- switch (UnwindCode.getUnwindOp()) {
- default: llvm_unreachable("Invalid unwind code");
- case UOP_PushNonVol:
- case UOP_AllocSmall:
- case UOP_SetFPReg:
- case UOP_PushMachFrame:
- return 1;
- case UOP_SaveNonVol:
- case UOP_SaveXMM128:
- return 2;
- case UOP_SaveNonVolBig:
- case UOP_SaveXMM128Big:
- return 3;
- case UOP_AllocLarge:
- return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
- }
-}
-
-// Given a symbol sym this functions returns the address and section of it.
-static error_code resolveSectionAndAddress(const COFFObjectFile *Obj,
- const SymbolRef &Sym,
- const coff_section *&ResolvedSection,
- uint64_t &ResolvedAddr) {
- if (error_code EC = Sym.getAddress(ResolvedAddr))
- return EC;
-
- section_iterator iter(Obj->section_begin());
- if (error_code EC = Sym.getSection(iter))
- return EC;
-
- ResolvedSection = Obj->getCOFFSection(*iter);
- return object_error::success;
-}
-
-// Given a vector of relocations for a section and an offset into this section
-// the function returns the symbol used for the relocation at the offset.
-static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
- uint64_t Offset, SymbolRef &Sym) {
- for (std::vector<RelocationRef>::const_iterator RelI = Rels.begin(),
- RelE = Rels.end();
- RelI != RelE; ++RelI) {
- uint64_t Ofs;
- if (error_code EC = RelI->getOffset(Ofs))
+// Given a a section and an offset into this section the function returns the
+// symbol used for the relocation at the offset.
+error_code COFFDumper::resolveSymbol(const coff_section *Section,
+ uint64_t Offset, SymbolRef &Sym) {
+ const auto &Relocations = RelocMap[Section];
+ for (const auto &Relocation : Relocations) {
+ uint64_t RelocationOffset;
+ if (error_code EC = Relocation.getOffset(RelocationOffset))
return EC;
- if (Ofs == Offset) {
- Sym = *RelI->getSymbol();
+ if (RelocationOffset == Offset) {
+ Sym = *Relocation.getSymbol();
return readobj_error::success;
}
}
-
return readobj_error::unknown_symbol;
}
-// Given a vector of relocations for a section and an offset into this section
-// the function returns the name of the symbol used for the relocation at the
-// offset.
-static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
- uint64_t Offset, StringRef &Name) {
- SymbolRef Sym;
- if (error_code EC = resolveSymbol(Rels, Offset, Sym)) return EC;
- if (error_code EC = Sym.getName(Name)) return EC;
+// Given a section and an offset into this section the function returns the name
+// of the symbol used for the relocation at the offset.
+error_code COFFDumper::resolveSymbolName(const coff_section *Section,
+ uint64_t Offset, StringRef &Name) {
+ SymbolRef Symbol;
+ if (error_code EC = resolveSymbol(Section, Offset, Symbol))
+ return EC;
+ if (error_code EC = Symbol.getName(Name))
+ return EC;
return object_error::success;
}
@@ -403,50 +306,6 @@ WeakExternalCharacteristics[] = {
{ "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
};
-static const EnumEntry<unsigned> UnwindFlags[] = {
- { "ExceptionHandler", Win64EH::UNW_ExceptionHandler },
- { "TerminateHandler", Win64EH::UNW_TerminateHandler },
- { "ChainInfo" , Win64EH::UNW_ChainInfo }
-};
-
-static const EnumEntry<unsigned> UnwindOpInfo[] = {
- { "RAX", 0 },
- { "RCX", 1 },
- { "RDX", 2 },
- { "RBX", 3 },
- { "RSP", 4 },
- { "RBP", 5 },
- { "RSI", 6 },
- { "RDI", 7 },
- { "R8", 8 },
- { "R9", 9 },
- { "R10", 10 },
- { "R11", 11 },
- { "R12", 12 },
- { "R13", 13 },
- { "R14", 14 },
- { "R15", 15 }
-};
-
-// Some additional COFF structures not defined by llvm::object.
-namespace {
- struct coff_aux_file_record {
- char FileName[18];
- };
-} // namespace
-
-static uint64_t getOffsetOfLSDA(const Win64EH::UnwindInfo& UI) {
- return static_cast<const char*>(UI.getLanguageSpecificData())
- - reinterpret_cast<const char*>(&UI);
-}
-
-static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UCs) {
- if (UCs.size() < 3)
- return 0;
-
- return UCs[1].FrameOffset + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16);
-}
-
template<typename T>
static error_code getSymbolAuxData(const COFFObjectFile *Obj,
const coff_symbol *Symbol, const T* &Aux) {
@@ -455,69 +314,6 @@ static error_code getSymbolAuxData(const COFFObjectFile *Obj,
return readobj_error::success;
}
-static std::string formatSymbol(const std::vector<RelocationRef> &Rels,
- uint64_t Offset, uint32_t Disp) {
- std::string Buffer;
- raw_string_ostream Str(Buffer);
-
- StringRef Sym;
- if (resolveSymbolName(Rels, Offset, Sym)) {
- Str << format(" (0x%" PRIX64 ")", Offset);
- return Str.str();
- }
-
- Str << Sym;
- if (Disp > 0) {
- Str << format(" +0x%X (0x%" PRIX64 ")", Disp, Offset);
- } else {
- Str << format(" (0x%" PRIX64 ")", Offset);
- }
-
- return Str.str();
-}
-
-// Given a vector of relocations for a section and an offset into this section
-// the function resolves the symbol used for the relocation at the offset and
-// returns the section content and the address inside the content pointed to
-// by the symbol.
-error_code COFFDumper::getSectionContents(
- const std::vector<RelocationRef> &Rels, uint64_t Offset,
- ArrayRef<uint8_t> &Contents, uint64_t &Addr) {
-
- SymbolRef Sym;
- const coff_section *Section;
-
- if (error_code EC = resolveSymbol(Rels, Offset, Sym))
- return EC;
- if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
- return EC;
- if (error_code EC = Obj->getSectionContents(Section, Contents))
- return EC;
-
- return object_error::success;
-}
-
-error_code COFFDumper::getSection(
- const std::vector<RelocationRef> &Rels, uint64_t Offset,
- const coff_section **SectionPtr, uint64_t *AddrPtr) {
-
- SymbolRef Sym;
- if (error_code EC = resolveSymbol(Rels, Offset, Sym))
- return EC;
-
- const coff_section *Section;
- uint64_t Addr;
- if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
- return EC;
-
- if (SectionPtr)
- *SectionPtr = Section;
- if (AddrPtr)
- *AddrPtr = Addr;
-
- return object_error::success;
-}
-
void COFFDumper::cacheRelocations() {
for (const SectionRef &S : Obj->sections()) {
const coff_section *Section = Obj->getCOFFSection(S);
@@ -541,7 +337,7 @@ void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName
void COFFDumper::printFileHeaders() {
// Print COFF header
- const coff_file_header *COFFHeader = 0;
+ const coff_file_header *COFFHeader = nullptr;
if (error(Obj->getCOFFHeader(COFFHeader)))
return;
@@ -564,13 +360,13 @@ void COFFDumper::printFileHeaders() {
// Print PE header. This header does not exist if this is an object file and
// not an executable.
- const pe32_header *PEHeader = 0;
+ const pe32_header *PEHeader = nullptr;
if (error(Obj->getPE32Header(PEHeader)))
return;
if (PEHeader)
printPEHeader<pe32_header>(PEHeader);
- const pe32plus_header *PEPlusHeader = 0;
+ const pe32plus_header *PEPlusHeader = nullptr;
if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
return;
if (PEPlusHeader)
@@ -685,8 +481,8 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
}
StringRef FunctionName;
- if (error(resolveSymbolName(RelocMap[Obj->getCOFFSection(Section)],
- Offset, FunctionName)))
+ if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset,
+ FunctionName)))
return;
W.printString("FunctionName", FunctionName);
if (FunctionLineTables.count(FunctionName) != 0) {
@@ -700,7 +496,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
break;
}
case COFF::DEBUG_STRING_TABLE_SUBSECTION:
- if (PayloadSize == 0 || StringTable.data() != 0 ||
+ if (PayloadSize == 0 || StringTable.data() != nullptr ||
Contents.back() != '\0') {
// Empty or duplicate or non-null-terminated subsection.
error(object_error::parse_failed);
@@ -712,7 +508,8 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
// Holds the translation table from file indices
// to offsets in the string table.
- if (PayloadSize == 0 || FileIndexToStringOffsetTable.data() != 0) {
+ if (PayloadSize == 0 ||
+ FileIndexToStringOffsetTable.data() != nullptr) {
// Empty or duplicate subsection.
error(object_error::parse_failed);
return;
@@ -979,13 +776,16 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
W.printBinary("Unused", makeArrayRef(Aux->Unused));
} else if (Symbol->isFileRecord()) {
- const coff_aux_file_record *Aux;
+ const coff_aux_file *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
break;
DictScope AS(W, "AuxFileRecord");
- W.printString("FileName", StringRef(Aux->FileName));
+ StringRef Name(Aux->FileName,
+ Symbol->NumberOfAuxSymbols * COFF::SymbolSize);
+ W.printString("FileName", Name.rtrim(StringRef("\0", 1)));
+ break;
} else if (Symbol->isSectionDefinition()) {
const coff_aux_section_definition *Aux;
if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
@@ -1045,181 +845,23 @@ void COFFDumper::printUnwindInfo() {
return;
ListScope D(W, "UnwindInformation");
- if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
- W.startLine() << "Unsupported image machine type "
- "(currently only AMD64 is supported).\n";
- return;
- }
-
- printX64UnwindInfo();
-}
-
-void COFFDumper::printX64UnwindInfo() {
- for (const SectionRef &Section : Obj->sections()) {
- StringRef Name;
- if (error(Section.getName(Name)))
- continue;
- if (Name != ".pdata" && !Name.startswith(".pdata$"))
- continue;
-
- const coff_section *PData = Obj->getCOFFSection(Section);
-
- ArrayRef<uint8_t> Contents;
- if (error(Obj->getSectionContents(PData, Contents)) || Contents.empty())
- continue;
-
- ArrayRef<RuntimeFunction> RFs(
- reinterpret_cast<const RuntimeFunction *>(Contents.data()),
- Contents.size() / sizeof(RuntimeFunction));
-
- for (const RuntimeFunction *I = RFs.begin(), *E = RFs.end(); I < E; ++I) {
- const uint64_t OffsetInSection = std::distance(RFs.begin(), I)
- * sizeof(RuntimeFunction);
-
- printRuntimeFunction(*I, OffsetInSection, RelocMap[PData]);
- }
- }
-}
-
-void COFFDumper::printRuntimeFunction(
- const RuntimeFunction& RTF,
- uint64_t OffsetInSection,
- const std::vector<RelocationRef> &Rels) {
-
- DictScope D(W, "RuntimeFunction");
- W.printString("StartAddress",
- formatSymbol(Rels, OffsetInSection + 0, RTF.StartAddress));
- W.printString("EndAddress",
- formatSymbol(Rels, OffsetInSection + 4, RTF.EndAddress));
- W.printString("UnwindInfoAddress",
- formatSymbol(Rels, OffsetInSection + 8, RTF.UnwindInfoOffset));
-
- const coff_section* XData = 0;
- uint64_t UnwindInfoOffset = 0;
- if (error(getSection(Rels, OffsetInSection + 8, &XData, &UnwindInfoOffset)))
- return;
-
- ArrayRef<uint8_t> XContents;
- if (error(Obj->getSectionContents(XData, XContents)) || XContents.empty())
- return;
-
- UnwindInfoOffset += RTF.UnwindInfoOffset;
- if (UnwindInfoOffset > XContents.size())
- return;
-
- const Win64EH::UnwindInfo *UI =
- reinterpret_cast<const Win64EH::UnwindInfo *>(
- XContents.data() + UnwindInfoOffset);
-
- printUnwindInfo(*UI, UnwindInfoOffset, RelocMap[XData]);
-}
-
-void COFFDumper::printUnwindInfo(
- const Win64EH::UnwindInfo& UI,
- uint64_t OffsetInSection,
- const std::vector<RelocationRef> &Rels) {
- DictScope D(W, "UnwindInfo");
- W.printNumber("Version", UI.getVersion());
- W.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags));
- W.printNumber("PrologSize", UI.PrologSize);
- if (UI.getFrameRegister() != 0) {
- W.printEnum("FrameRegister", UI.getFrameRegister(),
- makeArrayRef(UnwindOpInfo));
- W.printHex("FrameOffset", UI.getFrameOffset());
- } else {
- W.printString("FrameRegister", StringRef("-"));
- W.printString("FrameOffset", StringRef("-"));
- }
-
- W.printNumber("UnwindCodeCount", UI.NumCodes);
- {
- ListScope CodesD(W, "UnwindCodes");
- ArrayRef<UnwindCode> UCs(&UI.UnwindCodes[0], UI.NumCodes);
- for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ++I) {
- unsigned UsedSlots = getNumUsedSlots(*I);
- if (UsedSlots > UCs.size()) {
- errs() << "Corrupt unwind data";
- return;
- }
- printUnwindCode(UI, ArrayRef<UnwindCode>(I, E));
- I += UsedSlots - 1;
- }
- }
-
- uint64_t LSDAOffset = OffsetInSection + getOffsetOfLSDA(UI);
- if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
- W.printString("Handler", formatSymbol(Rels, LSDAOffset,
- UI.getLanguageSpecificHandlerOffset()));
- } else if (UI.getFlags() & UNW_ChainInfo) {
- const RuntimeFunction *Chained = UI.getChainedFunctionEntry();
- if (Chained) {
- DictScope D(W, "Chained");
- W.printString("StartAddress", formatSymbol(Rels, LSDAOffset + 0,
- Chained->StartAddress));
- W.printString("EndAddress", formatSymbol(Rels, LSDAOffset + 4,
- Chained->EndAddress));
- W.printString("UnwindInfoAddress", formatSymbol(Rels, LSDAOffset + 8,
- Chained->UnwindInfoOffset));
- }
- }
-}
-
-// Prints one unwind code. Because an unwind code can occupy up to 3 slots in
-// the unwind codes array, this function requires that the correct number of
-// slots is provided.
-void COFFDumper::printUnwindCode(const Win64EH::UnwindInfo& UI,
- ArrayRef<UnwindCode> UCs) {
- assert(UCs.size() >= getNumUsedSlots(UCs[0]));
-
- W.startLine() << format("0x%02X: ", unsigned(UCs[0].u.CodeOffset))
- << getUnwindCodeTypeName(UCs[0].getUnwindOp());
-
- uint32_t AllocSize = 0;
-
- switch (UCs[0].getUnwindOp()) {
- case UOP_PushNonVol:
- outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo());
+ switch (Header->Machine) {
+ case COFF::IMAGE_FILE_MACHINE_AMD64: {
+ Win64EH::Dumper Dumper(W);
+ Win64EH::Dumper::SymbolResolver Resolver =
+ [](const object::coff_section *Section, uint64_t Offset,
+ SymbolRef &Symbol, void *user_data) -> error_code {
+ COFFDumper *Dumper = reinterpret_cast<COFFDumper*>(user_data);
+ return Dumper->resolveSymbol(Section, Offset, Symbol);
+ };
+ Win64EH::Dumper::Context Ctx(*Obj, Resolver, this);
+ Dumper.printData(Ctx);
break;
-
- case UOP_AllocLarge:
- if (UCs[0].getOpInfo() == 0) {
- AllocSize = UCs[1].FrameOffset * 8;
- } else {
- AllocSize = getLargeSlotValue(UCs);
- }
- outs() << " size=" << AllocSize;
- break;
- case UOP_AllocSmall:
- outs() << " size=" << ((UCs[0].getOpInfo() + 1) * 8);
- break;
- case UOP_SetFPReg:
- if (UI.getFrameRegister() == 0) {
- outs() << " reg=<invalid>";
- } else {
- outs() << " reg=" << getUnwindRegisterName(UI.getFrameRegister())
- << format(", offset=0x%X", UI.getFrameOffset() * 16);
- }
- break;
- case UOP_SaveNonVol:
- outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo())
- << format(", offset=0x%X", UCs[1].FrameOffset * 8);
- break;
- case UOP_SaveNonVolBig:
- outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo())
- << format(", offset=0x%X", getLargeSlotValue(UCs));
- break;
- case UOP_SaveXMM128:
- outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
- << format(", offset=0x%X", UCs[1].FrameOffset * 16);
- break;
- case UOP_SaveXMM128Big:
- outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
- << format(", offset=0x%X", getLargeSlotValue(UCs));
- break;
- case UOP_PushMachFrame:
- outs() << " errcode=" << (UCs[0].getOpInfo() == 0 ? "no" : "yes");
+ }
+ default:
+ W.printEnum("unsupported Image Machine", Header->Machine,
+ makeArrayRef(ImageFileMachineType));
break;
}
-
- outs() << "\n";
}
+
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 4cd3393..de4c207 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -437,6 +437,29 @@ static const EnumEntry<unsigned> ElfSegmentFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, PF_R)
};
+static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R6),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6)
+};
+
template<class ELFT>
void ELFDumper<ELFT>::printFileHeaders() {
const typename ELFO::Elf_Ehdr *Header = Obj->getHeader();
@@ -464,7 +487,11 @@ void ELFDumper<ELFT>::printFileHeaders() {
W.printHex ("Entry", Header->e_entry);
W.printHex ("ProgramHeaderOffset", Header->e_phoff);
W.printHex ("SectionHeaderOffset", Header->e_shoff);
- W.printFlags ("Flags", Header->e_flags);
+ if (Header->e_machine == EM_MIPS)
+ W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags),
+ unsigned(ELF::EF_MIPS_ARCH));
+ else
+ W.printFlags("Flags", Header->e_flags);
W.printNumber("HeaderSize", Header->e_ehsize);
W.printNumber("ProgramHeaderEntrySize", Header->e_phentsize);
W.printNumber("ProgramHeaderCount", Header->e_phnum);
@@ -652,7 +679,8 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) {
std::string FullSymbolName(SymbolName);
if (Symbol.isDynamic()) {
bool IsDefault;
- ErrorOr<StringRef> Version = Obj->getSymbolVersion(0, &*Symbol, IsDefault);
+ ErrorOr<StringRef> Version = Obj->getSymbolVersion(nullptr, &*Symbol,
+ IsDefault);
if (Version) {
FullSymbolName += (IsDefault ? "@@" : "@");
FullSymbolName += *Version;
@@ -712,6 +740,8 @@ static const char *getTypeString(uint64_t Type) {
LLVM_READOBJ_TYPE_CASE(VERNEED);
LLVM_READOBJ_TYPE_CASE(VERNEEDNUM);
LLVM_READOBJ_TYPE_CASE(VERSYM);
+ LLVM_READOBJ_TYPE_CASE(RELCOUNT);
+ LLVM_READOBJ_TYPE_CASE(GNU_HASH);
LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION);
LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS);
LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS);
@@ -727,6 +757,57 @@ static const char *getTypeString(uint64_t Type) {
#undef LLVM_READOBJ_TYPE_CASE
+#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \
+ { #enum, prefix##_##enum }
+
+static const EnumEntry<unsigned> ElfDynamicDTFlags[] = {
+ LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN),
+ LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC),
+ LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL),
+ LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW),
+ LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)
+};
+
+static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT),
+ LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF),
+ LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE)
+};
+
+#undef LLVM_READOBJ_DT_FLAG_ENT
+
+template <typename T, typename TFlag>
+void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
+ typedef EnumEntry<TFlag> FlagEntry;
+ typedef SmallVector<FlagEntry, 10> FlagVector;
+ FlagVector SetFlags;
+
+ for (const auto &Flag : Flags) {
+ if (Flag.Value == 0)
+ continue;
+
+ if ((Value & Flag.Value) == Flag.Value)
+ SetFlags.push_back(Flag);
+ }
+
+ for (const auto &Flag : SetFlags) {
+ OS << Flag.Name << " ";
+ }
+}
+
template <class ELFT>
static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
bool Is64, raw_ostream &OS) {
@@ -755,14 +836,15 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_DEBUG:
case DT_VERNEED:
case DT_VERSYM:
+ case DT_GNU_HASH:
case DT_NULL:
- case DT_MIPS_FLAGS:
case DT_MIPS_BASE_ADDRESS:
case DT_MIPS_GOTSYM:
case DT_MIPS_RLD_MAP:
case DT_MIPS_PLTGOT:
OS << format("0x%" PRIX64, Value);
break;
+ case DT_RELCOUNT:
case DT_VERNEEDNUM:
case DT_MIPS_RLD_VERSION:
case DT_MIPS_LOCAL_GOTNO:
@@ -792,6 +874,12 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_RUNPATH:
OS << O->getDynamicString(Value);
break;
+ case DT_MIPS_FLAGS:
+ printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
+ break;
+ case DT_FLAGS:
+ printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
+ break;
}
}
diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h
index c40077a..9282dcc 100644
--- a/tools/llvm-readobj/StreamWriter.h
+++ b/tools/llvm-readobj/StreamWriter.h
@@ -81,9 +81,9 @@ public:
ArrayRef<EnumEntry<TEnum> > EnumValues) {
StringRef Name;
bool Found = false;
- for (size_t i = 0; i < EnumValues.size(); ++i) {
- if (EnumValues[i].Value == Value) {
- Name = EnumValues[i].Name;
+ for (const auto &EnumItem : EnumValues) {
+ if (EnumItem.Value == Value) {
+ Name = EnumItem.Name;
Found = true;
break;
}
@@ -103,25 +103,22 @@ public:
typedef SmallVector<FlagEntry, 10> FlagVector;
FlagVector SetFlags;
- for (typename ArrayRef<FlagEntry>::const_iterator I = Flags.begin(),
- E = Flags.end(); I != E; ++I) {
- if (I->Value == 0)
+ for (const auto &Flag : Flags) {
+ if (Flag.Value == 0)
continue;
- bool IsEnum = (I->Value & EnumMask) != 0;
- if ((!IsEnum && (Value & I->Value) == I->Value) ||
- (IsEnum && (Value & EnumMask) == I->Value)) {
- SetFlags.push_back(*I);
+ bool IsEnum = (Flag.Value & EnumMask) != 0;
+ if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
+ (IsEnum && (Value & EnumMask) == Flag.Value)) {
+ SetFlags.push_back(Flag);
}
}
std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
startLine() << Label << " [ (" << hex(Value) << ")\n";
- for (typename FlagVector::const_iterator I = SetFlags.begin(),
- E = SetFlags.end();
- I != E; ++I) {
- startLine() << " " << I->Name << " (" << hex(I->Value) << ")\n";
+ for (const auto &Flag : SetFlags) {
+ startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
}
startLine() << "]\n";
}
@@ -176,10 +173,10 @@ public:
void printList(StringRef Label, const SmallVectorImpl<T_> &List) {
startLine() << Label << ": [";
bool Comma = false;
- for (unsigned LI = 0, LE = List.size(); LI != LE; ++LI) {
+ for (const auto &Item : List) {
if (Comma)
OS << ", ";
- OS << List[LI];
+ OS << Item;
Comma = true;
}
OS << "]\n";
diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp
new file mode 100644
index 0000000..c64d362
--- /dev/null
+++ b/tools/llvm-readobj/Win64EHDumper.cpp
@@ -0,0 +1,328 @@
+//===- Win64EHDumper.cpp - Win64 EH Printer ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Win64EHDumper.h"
+#include "llvm-readobj.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::Win64EH;
+
+static const EnumEntry<unsigned> UnwindFlags[] = {
+ { "ExceptionHandler", UNW_ExceptionHandler },
+ { "TerminateHandler", UNW_TerminateHandler },
+ { "ChainInfo" , UNW_ChainInfo }
+};
+
+static const EnumEntry<unsigned> UnwindOpInfo[] = {
+ { "RAX", 0 },
+ { "RCX", 1 },
+ { "RDX", 2 },
+ { "RBX", 3 },
+ { "RSP", 4 },
+ { "RBP", 5 },
+ { "RSI", 6 },
+ { "RDI", 7 },
+ { "R8", 8 },
+ { "R9", 9 },
+ { "R10", 10 },
+ { "R11", 11 },
+ { "R12", 12 },
+ { "R13", 13 },
+ { "R14", 14 },
+ { "R15", 15 }
+};
+
+static uint64_t getOffsetOfLSDA(const UnwindInfo& UI) {
+ return static_cast<const char*>(UI.getLanguageSpecificData())
+ - reinterpret_cast<const char*>(&UI);
+}
+
+static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UC) {
+ if (UC.size() < 3)
+ return 0;
+ return UC[1].FrameOffset + (static_cast<uint32_t>(UC[2].FrameOffset) << 16);
+}
+
+// Returns the name of the unwind code.
+static StringRef getUnwindCodeTypeName(uint8_t Code) {
+ switch (Code) {
+ default: llvm_unreachable("Invalid unwind code");
+ case UOP_PushNonVol: return "PUSH_NONVOL";
+ case UOP_AllocLarge: return "ALLOC_LARGE";
+ case UOP_AllocSmall: return "ALLOC_SMALL";
+ case UOP_SetFPReg: return "SET_FPREG";
+ case UOP_SaveNonVol: return "SAVE_NONVOL";
+ case UOP_SaveNonVolBig: return "SAVE_NONVOL_FAR";
+ case UOP_SaveXMM128: return "SAVE_XMM128";
+ case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR";
+ case UOP_PushMachFrame: return "PUSH_MACHFRAME";
+ }
+}
+
+// Returns the name of a referenced register.
+static StringRef getUnwindRegisterName(uint8_t Reg) {
+ switch (Reg) {
+ default: llvm_unreachable("Invalid register");
+ case 0: return "RAX";
+ case 1: return "RCX";
+ case 2: return "RDX";
+ case 3: return "RBX";
+ case 4: return "RSP";
+ case 5: return "RBP";
+ case 6: return "RSI";
+ case 7: return "RDI";
+ case 8: return "R8";
+ case 9: return "R9";
+ case 10: return "R10";
+ case 11: return "R11";
+ case 12: return "R12";
+ case 13: return "R13";
+ case 14: return "R14";
+ case 15: return "R15";
+ }
+}
+
+// Calculates the number of array slots required for the unwind code.
+static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
+ switch (UnwindCode.getUnwindOp()) {
+ default: llvm_unreachable("Invalid unwind code");
+ case UOP_PushNonVol:
+ case UOP_AllocSmall:
+ case UOP_SetFPReg:
+ case UOP_PushMachFrame:
+ return 1;
+ case UOP_SaveNonVol:
+ case UOP_SaveXMM128:
+ return 2;
+ case UOP_SaveNonVolBig:
+ case UOP_SaveXMM128Big:
+ return 3;
+ case UOP_AllocLarge:
+ return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
+ }
+}
+
+static std::string formatSymbol(const Dumper::Context &Ctx,
+ const coff_section *Section, uint64_t Offset,
+ uint32_t Displacement) {
+ std::string Buffer;
+ raw_string_ostream OS(Buffer);
+
+ StringRef Name;
+ SymbolRef Symbol;
+ if (Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData) ||
+ Symbol.getName(Name)) {
+ OS << format(" (0x%" PRIX64 ")", Offset);
+ return OS.str();
+ }
+
+ OS << Name;
+ if (Displacement > 0)
+ OS << format(" +0x%X (0x%" PRIX64 ")", Displacement, Offset);
+ else
+ OS << format(" (0x%" PRIX64 ")", Offset);
+ return OS.str();
+}
+
+static error_code resolveRelocation(const Dumper::Context &Ctx,
+ const coff_section *Section,
+ uint64_t Offset,
+ const coff_section *&ResolvedSection,
+ uint64_t &ResolvedAddress) {
+ SymbolRef Symbol;
+ if (error_code EC = Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData))
+ return EC;
+
+ if (error_code EC = Symbol.getAddress(ResolvedAddress))
+ return EC;
+
+ section_iterator SI = Ctx.COFF.section_begin();
+ if (error_code EC = Symbol.getSection(SI))
+ return EC;
+
+ ResolvedSection = Ctx.COFF.getCOFFSection(*SI);
+ return object_error::success;
+}
+
+namespace llvm {
+namespace Win64EH {
+void Dumper::printRuntimeFunctionEntry(const Context &Ctx,
+ const coff_section *Section,
+ uint64_t Offset,
+ const RuntimeFunction &RF) {
+ SW.printString("StartAddress",
+ formatSymbol(Ctx, Section, Offset + 0, RF.StartAddress));
+ SW.printString("EndAddress",
+ formatSymbol(Ctx, Section, Offset + 4, RF.EndAddress));
+ SW.printString("UnwindInfoAddress",
+ formatSymbol(Ctx, Section, Offset + 8, RF.UnwindInfoOffset));
+}
+
+// Prints one unwind code. Because an unwind code can occupy up to 3 slots in
+// the unwind codes array, this function requires that the correct number of
+// slots is provided.
+void Dumper::printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC) {
+ assert(UC.size() >= getNumUsedSlots(UC[0]));
+
+ SW.startLine() << format("0x%02X: ", unsigned(UC[0].u.CodeOffset))
+ << getUnwindCodeTypeName(UC[0].getUnwindOp());
+
+ switch (UC[0].getUnwindOp()) {
+ case UOP_PushNonVol:
+ OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo());
+ break;
+
+ case UOP_AllocLarge:
+ OS << " size="
+ << ((UC[0].getOpInfo() == 0) ? UC[1].FrameOffset * 8
+ : getLargeSlotValue(UC));
+ break;
+
+ case UOP_AllocSmall:
+ OS << " size=" << (UC[0].getOpInfo() + 1) * 8;
+ break;
+
+ case UOP_SetFPReg:
+ if (UI.getFrameRegister() == 0)
+ OS << " reg=<invalid>";
+ else
+ OS << " reg=" << getUnwindRegisterName(UI.getFrameRegister())
+ << format(", offset=0x%X", UI.getFrameOffset() * 16);
+ break;
+
+ case UOP_SaveNonVol:
+ OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo())
+ << format(", offset=0x%X", UC[1].FrameOffset * 8);
+ break;
+
+ case UOP_SaveNonVolBig:
+ OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo())
+ << format(", offset=0x%X", getLargeSlotValue(UC));
+ break;
+
+ case UOP_SaveXMM128:
+ OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo())
+ << format(", offset=0x%X", UC[1].FrameOffset * 16);
+ break;
+
+ case UOP_SaveXMM128Big:
+ OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo())
+ << format(", offset=0x%X", getLargeSlotValue(UC));
+ break;
+
+ case UOP_PushMachFrame:
+ OS << " errcode=" << (UC[0].getOpInfo() == 0 ? "no" : "yes");
+ break;
+ }
+
+ OS << "\n";
+}
+
+void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section,
+ off_t Offset, const UnwindInfo &UI) {
+ DictScope UIS(SW, "UnwindInfo");
+ SW.printNumber("Version", UI.getVersion());
+ SW.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags));
+ SW.printNumber("PrologSize", UI.PrologSize);
+ if (UI.getFrameRegister()) {
+ SW.printEnum("FrameRegister", UI.getFrameRegister(),
+ makeArrayRef(UnwindOpInfo));
+ SW.printHex("FrameOffset", UI.getFrameOffset());
+ } else {
+ SW.printString("FrameRegister", StringRef("-"));
+ SW.printString("FrameOffset", StringRef("-"));
+ }
+
+ SW.printNumber("UnwindCodeCount", UI.NumCodes);
+ {
+ ListScope UCS(SW, "UnwindCodes");
+ ArrayRef<UnwindCode> UC(&UI.UnwindCodes[0], UI.NumCodes);
+ for (const UnwindCode *UCI = UC.begin(), *UCE = UC.end(); UCI < UCE; ++UCI) {
+ unsigned UsedSlots = getNumUsedSlots(*UCI);
+ if (UsedSlots > UC.size()) {
+ errs() << "corrupt unwind data";
+ return;
+ }
+
+ printUnwindCode(UI, ArrayRef<UnwindCode>(UCI, UCE));
+ UCI = UCI + UsedSlots - 1;
+ }
+ }
+
+ uint64_t LSDAOffset = Offset + getOffsetOfLSDA(UI);
+ if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
+ SW.printString("Handler",
+ formatSymbol(Ctx, Section, LSDAOffset,
+ UI.getLanguageSpecificHandlerOffset()));
+ } else if (UI.getFlags() & UNW_ChainInfo) {
+ if (const RuntimeFunction *Chained = UI.getChainedFunctionEntry()) {
+ DictScope CS(SW, "Chained");
+ printRuntimeFunctionEntry(Ctx, Section, LSDAOffset, *Chained);
+ }
+ }
+}
+
+void Dumper::printRuntimeFunction(const Context &Ctx,
+ const coff_section *Section,
+ uint64_t SectionOffset,
+ const RuntimeFunction &RF) {
+ DictScope RFS(SW, "RuntimeFunction");
+ printRuntimeFunctionEntry(Ctx, Section, SectionOffset, RF);
+
+ const coff_section *XData;
+ uint64_t Offset;
+ if (error(resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset)))
+ return;
+
+ ArrayRef<uint8_t> Contents;
+ if (error(Ctx.COFF.getSectionContents(XData, Contents)) || Contents.empty())
+ return;
+
+ Offset = Offset + RF.UnwindInfoOffset;
+ if (Offset > Contents.size())
+ return;
+
+ const auto UI = reinterpret_cast<const UnwindInfo*>(Contents.data() + Offset);
+ printUnwindInfo(Ctx, XData, Offset, *UI);
+}
+
+void Dumper::printData(const Context &Ctx) {
+ for (const auto &Section : Ctx.COFF.sections()) {
+ StringRef Name;
+ if (error(Section.getName(Name)))
+ continue;
+
+ if (Name != ".pdata" && !Name.startswith(".pdata$"))
+ continue;
+
+ const coff_section *PData = Ctx.COFF.getCOFFSection(Section);
+ ArrayRef<uint8_t> Contents;
+ if (error(Ctx.COFF.getSectionContents(PData, Contents)) || Contents.empty())
+ continue;
+
+ const RuntimeFunction *Entries =
+ reinterpret_cast<const RuntimeFunction *>(Contents.data());
+ const size_t Count = Contents.size() / sizeof(RuntimeFunction);
+ ArrayRef<RuntimeFunction> RuntimeFunctions(Entries, Count);
+
+ size_t Index = 0;
+ for (const auto &RF : RuntimeFunctions) {
+ printRuntimeFunction(Ctx, Ctx.COFF.getCOFFSection(Section),
+ Index * sizeof(RuntimeFunction), RF);
+ ++Index;
+ }
+ }
+}
+}
+}
+
diff --git a/tools/llvm-readobj/Win64EHDumper.h b/tools/llvm-readobj/Win64EHDumper.h
new file mode 100644
index 0000000..2eac810
--- /dev/null
+++ b/tools/llvm-readobj/Win64EHDumper.h
@@ -0,0 +1,62 @@
+//===- Win64EHDumper.h - Win64 EH Printing ----------------------*- 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_READOBJ_WIN64EHPRINTER_H
+#define LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H
+
+#include "StreamWriter.h"
+#include "llvm/Support/Win64EH.h"
+
+namespace llvm {
+namespace object {
+class COFFObjectFile;
+class SymbolRef;
+struct coff_section;
+}
+
+namespace Win64EH {
+class Dumper {
+ StreamWriter &SW;
+ raw_ostream &OS;
+
+public:
+ typedef error_code (*SymbolResolver)(const object::coff_section *, uint64_t,
+ object::SymbolRef &, void *);
+
+ struct Context {
+ const object::COFFObjectFile &COFF;
+ SymbolResolver ResolveSymbol;
+ void *UserData;
+
+ Context(const object::COFFObjectFile &COFF, SymbolResolver Resolver,
+ void *UserData)
+ : COFF(COFF), ResolveSymbol(Resolver), UserData(UserData) {}
+ };
+
+private:
+ void printRuntimeFunctionEntry(const Context &Ctx,
+ const object::coff_section *Section,
+ uint64_t SectionOffset,
+ const RuntimeFunction &RF);
+ void printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC);
+ void printUnwindInfo(const Context &Ctx, const object::coff_section *Section,
+ off_t Offset, const UnwindInfo &UI);
+ void printRuntimeFunction(const Context &Ctx,
+ const object::coff_section *Section,
+ uint64_t SectionOffset, const RuntimeFunction &RF);
+
+public:
+ Dumper(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {}
+
+ void printData(const Context &Ctx);
+};
+}
+}
+
+#endif