2013-04-04 02:31:38 +08:00
|
|
|
//===-- COFFDumper.cpp - COFF-specific dumper -------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// \brief This file implements the COFF-specific dumper for llvm-readobj.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-06-13 01:38:55 +08:00
|
|
|
#include "ARMWinEHPrinter.h"
|
2016-01-14 03:32:35 +08:00
|
|
|
#include "CodeView.h"
|
2013-04-04 02:31:38 +08:00
|
|
|
#include "Error.h"
|
2014-01-13 16:04:33 +08:00
|
|
|
#include "ObjDumper.h"
|
2015-06-27 07:56:53 +08:00
|
|
|
#include "StackMapPrinter.h"
|
2014-05-26 04:26:45 +08:00
|
|
|
#include "Win64EHDumper.h"
|
2016-05-03 08:28:04 +08:00
|
|
|
#include "llvm-readobj.h"
|
2013-04-04 02:31:38 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
2014-11-20 01:10:39 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2016-05-28 13:21:57 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/ByteStream.h"
|
2016-01-14 07:44:57 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
2016-01-15 03:20:17 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/Line.h"
|
2016-05-14 08:02:53 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
|
2016-05-24 07:41:13 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
|
2016-05-03 08:28:04 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
2016-05-05 08:34:33 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
|
2016-01-14 07:44:57 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
2016-05-14 08:02:53 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
|
2013-04-04 02:31:38 +08:00
|
|
|
#include "llvm/Object/COFF.h"
|
|
|
|
#include "llvm/Object/ObjectFile.h"
|
2014-01-13 16:04:33 +08:00
|
|
|
#include "llvm/Support/COFF.h"
|
2013-04-04 02:31:38 +08:00
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2013-12-19 19:37:14 +08:00
|
|
|
#include "llvm/Support/DataExtractor.h"
|
2013-04-04 02:31:38 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2016-05-03 08:28:04 +08:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
2013-04-04 02:31:38 +08:00
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
#include "llvm/Support/Win64EH.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
2016-04-06 04:45:04 +08:00
|
|
|
#include <cstring>
|
2014-06-13 01:38:55 +08:00
|
|
|
#include <system_error>
|
2016-04-06 04:45:04 +08:00
|
|
|
#include <time.h>
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::object;
|
2016-01-14 03:32:35 +08:00
|
|
|
using namespace llvm::codeview;
|
2016-01-14 07:44:57 +08:00
|
|
|
using namespace llvm::support;
|
2013-04-04 02:31:38 +08:00
|
|
|
using namespace llvm::Win64EH;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class COFFDumper : public ObjDumper {
|
|
|
|
public:
|
2016-05-24 07:41:13 +08:00
|
|
|
friend class COFFObjectDumpDelegate;
|
2016-05-03 08:28:04 +08:00
|
|
|
COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
|
2016-05-05 08:34:33 +08:00
|
|
|
: ObjDumper(Writer), Obj(Obj),
|
[codeview] Improve readability of type record assembly
Adds the method MCStreamer::EmitBinaryData, which is usually an alias
for EmitBytes. In the MCAsmStreamer case, it is overridden to emit hex
dump output like this:
.byte 0x0e, 0x00, 0x08, 0x10
.byte 0x03, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x10, 0x00, 0x00
Also, when verbose asm comments are enabled, this patch prints the dump
output for each comment before its record, like this:
# ArgList (0x1000) {
# TypeLeafKind: LF_ARGLIST (0x1201)
# NumArgs: 0
# Arguments [
# ]
# }
.byte 0x06, 0x00, 0x01, 0x12
.byte 0x00, 0x00, 0x00, 0x00
This should make debugging easier and testing more convenient.
Reviewers: aaboud
Subscribers: majnemer, zturner, amccarth, aaboud, llvm-commits
Differential Revision: http://reviews.llvm.org/D20711
llvm-svn: 271313
2016-06-01 02:45:36 +08:00
|
|
|
CVTD(&Writer, opts::CodeViewSubsectionBytes) {}
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-08-31 00:48:34 +08:00
|
|
|
void printFileHeaders() override;
|
|
|
|
void printSections() override;
|
|
|
|
void printRelocations() override;
|
|
|
|
void printSymbols() override;
|
|
|
|
void printDynamicSymbols() override;
|
|
|
|
void printUnwindInfo() override;
|
2014-10-03 01:02:18 +08:00
|
|
|
void printCOFFImports() override;
|
2015-01-04 05:35:09 +08:00
|
|
|
void printCOFFExports() override;
|
2014-10-08 03:37:52 +08:00
|
|
|
void printCOFFDirectives() override;
|
2014-11-19 08:18:07 +08:00
|
|
|
void printCOFFBaseReloc() override;
|
2016-06-03 01:10:43 +08:00
|
|
|
void printCOFFDebugDirectory() override;
|
2015-12-17 02:28:12 +08:00
|
|
|
void printCodeViewDebugInfo() override;
|
2016-05-14 08:02:53 +08:00
|
|
|
void
|
|
|
|
mergeCodeViewTypes(llvm::codeview::MemoryTypeTableBuilder &CVTypes) override;
|
2015-06-27 07:56:53 +08:00
|
|
|
void printStackMap() const override;
|
2013-04-04 02:31:38 +08:00
|
|
|
private:
|
2014-03-18 14:53:02 +08:00
|
|
|
void printSymbol(const SymbolRef &Sym);
|
2016-01-15 01:51:57 +08:00
|
|
|
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc,
|
|
|
|
uint64_t Bias = 0);
|
2013-07-20 07:23:29 +08:00
|
|
|
void printDataDirectory(uint32_t Index, const std::string &FieldName);
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-11-05 14:24:35 +08:00
|
|
|
void printDOSHeader(const dos_header *DH);
|
2014-01-26 12:15:52 +08:00
|
|
|
template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
|
|
|
|
void printBaseOfDataField(const pe32_header *Hdr);
|
|
|
|
void printBaseOfDataField(const pe32plus_header *Hdr);
|
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
void printCodeViewSymbolSection(StringRef SectionName, const SectionRef &Section);
|
|
|
|
void printCodeViewTypeSection(StringRef SectionName, const SectionRef &Section);
|
|
|
|
StringRef getTypeName(TypeIndex Ty);
|
2016-01-15 08:11:21 +08:00
|
|
|
StringRef getFileNameForFileOffset(uint32_t FileOffset);
|
|
|
|
void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
|
2016-05-03 04:30:47 +08:00
|
|
|
void printTypeIndex(StringRef FieldName, TypeIndex TI) {
|
|
|
|
// Forward to CVTypeDumper for simplicity.
|
|
|
|
CVTD.printTypeIndex(FieldName, TI);
|
|
|
|
}
|
2013-12-19 19:37:14 +08:00
|
|
|
|
2014-10-24 06:25:31 +08:00
|
|
|
void printCodeViewSymbolsSubsection(StringRef Subsection,
|
|
|
|
const SectionRef &Section,
|
2016-01-15 01:51:54 +08:00
|
|
|
StringRef SectionContents);
|
2014-10-24 06:25:31 +08:00
|
|
|
|
2016-01-16 02:06:25 +08:00
|
|
|
void printCodeViewFileChecksums(StringRef Subsection);
|
|
|
|
|
2016-01-15 03:20:17 +08:00
|
|
|
void printCodeViewInlineeLines(StringRef Subsection);
|
|
|
|
|
2016-05-24 02:49:06 +08:00
|
|
|
void printRelocatedField(StringRef Label, const coff_section *Sec,
|
|
|
|
uint32_t RelocOffset, uint32_t Offset,
|
|
|
|
StringRef *RelocSym = nullptr);
|
|
|
|
|
2016-01-15 01:51:54 +08:00
|
|
|
void printRelocatedField(StringRef Label, const coff_section *Sec,
|
|
|
|
StringRef SectionContents, const ulittle32_t *Field,
|
|
|
|
StringRef *RelocSym = nullptr);
|
|
|
|
|
2016-01-15 01:51:57 +08:00
|
|
|
void printBinaryBlockWithRelocs(StringRef Label, const SectionRef &Sec,
|
|
|
|
StringRef SectionContents, StringRef Block);
|
|
|
|
|
2016-01-15 08:11:21 +08:00
|
|
|
/// Given a .debug$S section, find the string table and file checksum table.
|
|
|
|
void initializeFileAndStringTables(StringRef Data);
|
|
|
|
|
2013-04-04 02:31:38 +08:00
|
|
|
void cacheRelocations();
|
|
|
|
|
2014-06-13 11:07:50 +08:00
|
|
|
std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
|
|
|
|
SymbolRef &Sym);
|
|
|
|
std::error_code resolveSymbolName(const coff_section *Section,
|
|
|
|
uint64_t Offset, StringRef &Name);
|
2016-01-15 01:51:54 +08:00
|
|
|
std::error_code resolveSymbolName(const coff_section *Section,
|
|
|
|
StringRef SectionContents,
|
|
|
|
const void *RelocPtr, StringRef &Name);
|
2014-10-09 10:16:38 +08:00
|
|
|
void printImportedSymbols(iterator_range<imported_symbol_iterator> Range);
|
2014-11-13 11:22:54 +08:00
|
|
|
void printDelayImportedSymbols(
|
|
|
|
const DelayImportDirectoryEntryRef &I,
|
|
|
|
iterator_range<imported_symbol_iterator> Range);
|
2014-10-03 08:41:58 +08:00
|
|
|
|
2013-04-04 02:31:38 +08:00
|
|
|
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
|
|
|
|
|
|
|
|
const llvm::object::COFFObjectFile *Obj;
|
2015-07-06 22:26:07 +08:00
|
|
|
bool RelocCached = false;
|
2013-04-04 02:31:38 +08:00
|
|
|
RelocMapTy RelocMap;
|
2016-01-15 08:11:21 +08:00
|
|
|
StringRef CVFileChecksumTable;
|
2014-10-07 00:59:44 +08:00
|
|
|
StringRef CVStringTable;
|
2016-01-14 03:32:35 +08:00
|
|
|
|
2016-05-03 04:30:47 +08:00
|
|
|
CVTypeDumper CVTD;
|
2013-04-04 02:31:38 +08:00
|
|
|
};
|
|
|
|
|
2016-05-24 07:41:13 +08:00
|
|
|
class COFFObjectDumpDelegate : public SymbolDumpDelegate {
|
|
|
|
public:
|
|
|
|
COFFObjectDumpDelegate(COFFDumper &CD, const SectionRef &SR,
|
|
|
|
const COFFObjectFile *Obj, StringRef SectionContents)
|
2016-05-24 11:32:34 +08:00
|
|
|
: CD(CD), SR(SR), SectionContents(SectionContents) {
|
2016-05-24 07:41:13 +08:00
|
|
|
Sec = Obj->getCOFFSection(SR);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override {
|
|
|
|
return Record.data() - SectionContents.bytes_begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
void printRelocatedField(StringRef Label, uint32_t RelocOffset,
|
|
|
|
uint32_t Offset, StringRef *RelocSym) override {
|
|
|
|
CD.printRelocatedField(Label, Sec, RelocOffset, Offset, RelocSym);
|
|
|
|
}
|
|
|
|
|
|
|
|
void printBinaryBlockWithRelocs(StringRef Label,
|
|
|
|
ArrayRef<uint8_t> Block) override {
|
|
|
|
StringRef SBlock(reinterpret_cast<const char *>(Block.data()),
|
|
|
|
Block.size());
|
|
|
|
if (opts::CodeViewSubsectionBytes)
|
|
|
|
CD.printBinaryBlockWithRelocs(Label, SR, SectionContents, SBlock);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef getFileNameForFileOffset(uint32_t FileOffset) override {
|
|
|
|
return CD.getFileNameForFileOffset(FileOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef getStringTable() override { return CD.CVStringTable; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
COFFDumper &CD;
|
|
|
|
const SectionRef &SR;
|
|
|
|
const coff_section *Sec;
|
|
|
|
StringRef SectionContents;
|
|
|
|
};
|
|
|
|
|
2016-05-05 08:34:33 +08:00
|
|
|
} // end namespace
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2014-06-13 11:07:50 +08:00
|
|
|
std::error_code createCOFFDumper(const object::ObjectFile *Obj,
|
2016-05-03 08:28:04 +08:00
|
|
|
ScopedPrinter &Writer,
|
2014-06-13 11:07:50 +08:00
|
|
|
std::unique_ptr<ObjDumper> &Result) {
|
2013-04-04 02:31:38 +08:00
|
|
|
const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj);
|
|
|
|
if (!COFFObj)
|
|
|
|
return readobj_error::unsupported_obj_file_format;
|
|
|
|
|
|
|
|
Result.reset(new COFFDumper(COFFObj, Writer));
|
|
|
|
return readobj_error::success;
|
|
|
|
}
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
} // namespace llvm
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-05-26 04:26:37 +08:00
|
|
|
// Given a a section and an offset into this section the function returns the
|
|
|
|
// symbol used for the relocation at the offset.
|
2014-06-13 11:07:50 +08:00
|
|
|
std::error_code COFFDumper::resolveSymbol(const coff_section *Section,
|
|
|
|
uint64_t Offset, SymbolRef &Sym) {
|
2015-07-06 22:26:07 +08:00
|
|
|
cacheRelocations();
|
2014-05-26 04:26:37 +08:00
|
|
|
const auto &Relocations = RelocMap[Section];
|
2016-05-29 14:18:08 +08:00
|
|
|
auto SymI = Obj->symbol_end();
|
2014-05-26 04:26:37 +08:00
|
|
|
for (const auto &Relocation : Relocations) {
|
2015-06-30 07:29:12 +08:00
|
|
|
uint64_t RelocationOffset = Relocation.getOffset();
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-05-26 04:26:37 +08:00
|
|
|
if (RelocationOffset == Offset) {
|
2016-05-29 14:18:08 +08:00
|
|
|
SymI = Relocation.getSymbol();
|
|
|
|
break;
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
}
|
2016-05-29 14:18:08 +08:00
|
|
|
if (SymI == Obj->symbol_end())
|
|
|
|
return readobj_error::unknown_symbol;
|
|
|
|
Sym = *SymI;
|
|
|
|
return readobj_error::success;
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
2014-05-26 04:26:37 +08:00
|
|
|
// Given a section and an offset into this section the function returns the name
|
|
|
|
// of the symbol used for the relocation at the offset.
|
2014-06-13 11:07:50 +08:00
|
|
|
std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,
|
|
|
|
uint64_t Offset,
|
|
|
|
StringRef &Name) {
|
2014-05-26 04:26:37 +08:00
|
|
|
SymbolRef Symbol;
|
2014-06-13 11:07:50 +08:00
|
|
|
if (std::error_code EC = resolveSymbol(Section, Offset, Symbol))
|
2014-05-26 04:26:37 +08:00
|
|
|
return EC;
|
2016-04-21 05:24:34 +08:00
|
|
|
Expected<StringRef> NameOrErr = Symbol.getName();
|
|
|
|
if (!NameOrErr)
|
|
|
|
return errorToErrorCode(NameOrErr.takeError());
|
2015-07-03 04:55:21 +08:00
|
|
|
Name = *NameOrErr;
|
2015-06-09 23:20:42 +08:00
|
|
|
return std::error_code();
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
2016-01-15 01:51:54 +08:00
|
|
|
// Helper for when you have a pointer to real data and you want to know about
|
|
|
|
// relocations against it.
|
|
|
|
std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,
|
|
|
|
StringRef SectionContents,
|
|
|
|
const void *RelocPtr,
|
|
|
|
StringRef &Name) {
|
|
|
|
assert(SectionContents.data() < RelocPtr &&
|
|
|
|
RelocPtr < SectionContents.data() + SectionContents.size() &&
|
|
|
|
"pointer to relocated object is not in section");
|
|
|
|
uint64_t Offset = ptrdiff_t(reinterpret_cast<const char *>(RelocPtr) -
|
|
|
|
SectionContents.data());
|
|
|
|
return resolveSymbolName(Section, Offset, Name);
|
|
|
|
}
|
|
|
|
|
2016-05-24 02:49:06 +08:00
|
|
|
void COFFDumper::printRelocatedField(StringRef Label, const coff_section *Sec,
|
|
|
|
uint32_t RelocOffset, uint32_t Offset,
|
|
|
|
StringRef *RelocSym) {
|
|
|
|
StringRef SymStorage;
|
|
|
|
StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
|
|
|
|
if (!resolveSymbolName(Sec, RelocOffset, Symbol))
|
|
|
|
W.printSymbolOffset(Label, Symbol, Offset);
|
|
|
|
else
|
|
|
|
W.printHex(Label, RelocOffset);
|
|
|
|
}
|
|
|
|
|
2016-01-15 01:51:54 +08:00
|
|
|
void COFFDumper::printRelocatedField(StringRef Label, const coff_section *Sec,
|
|
|
|
StringRef SectionContents,
|
|
|
|
const ulittle32_t *Field,
|
|
|
|
StringRef *RelocSym) {
|
|
|
|
StringRef SymStorage;
|
|
|
|
StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
|
|
|
|
if (!resolveSymbolName(Sec, SectionContents, Field, Symbol))
|
|
|
|
W.printSymbolOffset(Label, Symbol, *Field);
|
|
|
|
else
|
|
|
|
W.printHex(Label, *Field);
|
|
|
|
}
|
|
|
|
|
2016-01-15 01:51:57 +08:00
|
|
|
void COFFDumper::printBinaryBlockWithRelocs(StringRef Label,
|
|
|
|
const SectionRef &Sec,
|
|
|
|
StringRef SectionContents,
|
|
|
|
StringRef Block) {
|
|
|
|
W.printBinaryBlock(Label, Block);
|
|
|
|
|
|
|
|
assert(SectionContents.begin() < Block.begin() &&
|
|
|
|
SectionContents.end() >= Block.end() &&
|
|
|
|
"Block is not contained in SectionContents");
|
|
|
|
uint64_t OffsetStart = Block.data() - SectionContents.data();
|
|
|
|
uint64_t OffsetEnd = OffsetStart + Block.size();
|
|
|
|
|
2016-05-24 07:41:13 +08:00
|
|
|
W.flush();
|
2016-01-15 01:51:57 +08:00
|
|
|
cacheRelocations();
|
|
|
|
ListScope D(W, "BlockRelocations");
|
|
|
|
const coff_section *Section = Obj->getCOFFSection(Sec);
|
|
|
|
const auto &Relocations = RelocMap[Section];
|
|
|
|
for (const auto &Relocation : Relocations) {
|
|
|
|
uint64_t RelocationOffset = Relocation.getOffset();
|
|
|
|
if (OffsetStart <= RelocationOffset && RelocationOffset < OffsetEnd)
|
|
|
|
printRelocation(Sec, Relocation, OffsetStart);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
|
2013-04-04 02:31:38 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ),
|
2014-03-11 11:08:37 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ),
|
2013-04-04 02:31:38 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5 ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {
|
2013-04-04 02:31:38 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI )
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
|
2013-06-13 03:10:33 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ),
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
|
2014-01-27 12:22:24 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ),
|
2013-06-13 03:10:33 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ),
|
2014-06-27 11:11:18 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER ),
|
2013-06-13 03:10:33 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ),
|
2014-06-27 11:11:18 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_GUARD_CF ),
|
2013-06-13 03:10:33 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::SectionCharacteristics>
|
2013-04-04 02:31:38 +08:00
|
|
|
ImageSectionCharacteristics[] = {
|
2015-07-31 00:47:56 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD ),
|
2013-04-04 02:31:38 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ ),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE )
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = {
|
2013-04-04 02:31:38 +08:00
|
|
|
{ "Null" , COFF::IMAGE_SYM_TYPE_NULL },
|
|
|
|
{ "Void" , COFF::IMAGE_SYM_TYPE_VOID },
|
|
|
|
{ "Char" , COFF::IMAGE_SYM_TYPE_CHAR },
|
|
|
|
{ "Short" , COFF::IMAGE_SYM_TYPE_SHORT },
|
|
|
|
{ "Int" , COFF::IMAGE_SYM_TYPE_INT },
|
|
|
|
{ "Long" , COFF::IMAGE_SYM_TYPE_LONG },
|
|
|
|
{ "Float" , COFF::IMAGE_SYM_TYPE_FLOAT },
|
|
|
|
{ "Double", COFF::IMAGE_SYM_TYPE_DOUBLE },
|
|
|
|
{ "Struct", COFF::IMAGE_SYM_TYPE_STRUCT },
|
|
|
|
{ "Union" , COFF::IMAGE_SYM_TYPE_UNION },
|
|
|
|
{ "Enum" , COFF::IMAGE_SYM_TYPE_ENUM },
|
|
|
|
{ "MOE" , COFF::IMAGE_SYM_TYPE_MOE },
|
|
|
|
{ "Byte" , COFF::IMAGE_SYM_TYPE_BYTE },
|
|
|
|
{ "Word" , COFF::IMAGE_SYM_TYPE_WORD },
|
|
|
|
{ "UInt" , COFF::IMAGE_SYM_TYPE_UINT },
|
|
|
|
{ "DWord" , COFF::IMAGE_SYM_TYPE_DWORD }
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = {
|
2013-04-04 02:31:38 +08:00
|
|
|
{ "Null" , COFF::IMAGE_SYM_DTYPE_NULL },
|
|
|
|
{ "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER },
|
|
|
|
{ "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION },
|
|
|
|
{ "Array" , COFF::IMAGE_SYM_DTYPE_ARRAY }
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = {
|
2013-04-04 02:31:38 +08:00
|
|
|
{ "EndOfFunction" , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION },
|
|
|
|
{ "Null" , COFF::IMAGE_SYM_CLASS_NULL },
|
|
|
|
{ "Automatic" , COFF::IMAGE_SYM_CLASS_AUTOMATIC },
|
|
|
|
{ "External" , COFF::IMAGE_SYM_CLASS_EXTERNAL },
|
|
|
|
{ "Static" , COFF::IMAGE_SYM_CLASS_STATIC },
|
|
|
|
{ "Register" , COFF::IMAGE_SYM_CLASS_REGISTER },
|
|
|
|
{ "ExternalDef" , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF },
|
|
|
|
{ "Label" , COFF::IMAGE_SYM_CLASS_LABEL },
|
|
|
|
{ "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL },
|
|
|
|
{ "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT },
|
|
|
|
{ "Argument" , COFF::IMAGE_SYM_CLASS_ARGUMENT },
|
|
|
|
{ "StructTag" , COFF::IMAGE_SYM_CLASS_STRUCT_TAG },
|
|
|
|
{ "MemberOfUnion" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION },
|
|
|
|
{ "UnionTag" , COFF::IMAGE_SYM_CLASS_UNION_TAG },
|
|
|
|
{ "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION },
|
|
|
|
{ "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC },
|
|
|
|
{ "EnumTag" , COFF::IMAGE_SYM_CLASS_ENUM_TAG },
|
|
|
|
{ "MemberOfEnum" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM },
|
|
|
|
{ "RegisterParam" , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM },
|
|
|
|
{ "BitField" , COFF::IMAGE_SYM_CLASS_BIT_FIELD },
|
|
|
|
{ "Block" , COFF::IMAGE_SYM_CLASS_BLOCK },
|
|
|
|
{ "Function" , COFF::IMAGE_SYM_CLASS_FUNCTION },
|
|
|
|
{ "EndOfStruct" , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT },
|
|
|
|
{ "File" , COFF::IMAGE_SYM_CLASS_FILE },
|
|
|
|
{ "Section" , COFF::IMAGE_SYM_CLASS_SECTION },
|
|
|
|
{ "WeakExternal" , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL },
|
|
|
|
{ "CLRToken" , COFF::IMAGE_SYM_CLASS_CLR_TOKEN }
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {
|
2013-04-04 02:31:38 +08:00
|
|
|
{ "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES },
|
|
|
|
{ "Any" , COFF::IMAGE_COMDAT_SELECT_ANY },
|
|
|
|
{ "SameSize" , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE },
|
|
|
|
{ "ExactMatch" , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH },
|
|
|
|
{ "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE },
|
|
|
|
{ "Largest" , COFF::IMAGE_COMDAT_SELECT_LARGEST },
|
|
|
|
{ "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST }
|
|
|
|
};
|
|
|
|
|
2016-06-03 01:10:43 +08:00
|
|
|
static const EnumEntry<COFF::DebugType> ImageDebugType[] = {
|
|
|
|
{ "Unknown" , COFF::IMAGE_DEBUG_TYPE_UNKNOWN },
|
|
|
|
{ "COFF" , COFF::IMAGE_DEBUG_TYPE_COFF },
|
|
|
|
{ "CodeView" , COFF::IMAGE_DEBUG_TYPE_CODEVIEW },
|
|
|
|
{ "FPO" , COFF::IMAGE_DEBUG_TYPE_FPO },
|
|
|
|
{ "Misc" , COFF::IMAGE_DEBUG_TYPE_MISC },
|
|
|
|
{ "Exception" , COFF::IMAGE_DEBUG_TYPE_EXCEPTION },
|
|
|
|
{ "Fixup" , COFF::IMAGE_DEBUG_TYPE_FIXUP },
|
|
|
|
{ "OmapToSrc" , COFF::IMAGE_DEBUG_TYPE_OMAP_TO_SRC },
|
|
|
|
{ "OmapFromSrc", COFF::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC },
|
|
|
|
{ "Borland" , COFF::IMAGE_DEBUG_TYPE_BORLAND },
|
2016-06-03 01:32:11 +08:00
|
|
|
{ "Reserved10" , COFF::IMAGE_DEBUG_TYPE_RESERVED10 },
|
2016-06-03 01:10:43 +08:00
|
|
|
{ "CLSID" , COFF::IMAGE_DEBUG_TYPE_CLSID },
|
|
|
|
{ "VCFeature" , COFF::IMAGE_DEBUG_TYPE_VC_FEATURE },
|
|
|
|
{ "POGO" , COFF::IMAGE_DEBUG_TYPE_POGO },
|
|
|
|
{ "ILTCG" , COFF::IMAGE_DEBUG_TYPE_ILTCG },
|
|
|
|
{ "MPX" , COFF::IMAGE_DEBUG_TYPE_MPX },
|
2016-06-03 01:32:11 +08:00
|
|
|
{ "Repro" , COFF::IMAGE_DEBUG_TYPE_REPRO },
|
2016-06-03 01:10:43 +08:00
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<COFF::WeakExternalCharacteristics>
|
2013-04-04 02:31:38 +08:00
|
|
|
WeakExternalCharacteristics[] = {
|
|
|
|
{ "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
|
|
|
|
{ "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY },
|
|
|
|
{ "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<uint32_t> SubSectionTypes[] = {
|
2016-01-14 03:32:35 +08:00
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, StringTable),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FileChecksums),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FrameData),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, InlineeLines),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeImports),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeExports),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, ILLines),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FuncMDTokenMap),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, TypeMDTokenMap),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, MergedAssemblyInput),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA),
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<uint32_t> FrameDataFlags[] = {
|
2016-01-14 03:32:35 +08:00
|
|
|
LLVM_READOBJ_ENUM_ENT(FrameData, HasSEH),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(FrameData, HasEH),
|
|
|
|
LLVM_READOBJ_ENUM_ENT(FrameData, IsFunctionStart),
|
|
|
|
};
|
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static const EnumEntry<uint8_t> FileChecksumKindNames[] = {
|
2016-01-16 02:06:25 +08:00
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, None),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, MD5),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA1),
|
|
|
|
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA256),
|
|
|
|
};
|
|
|
|
|
2014-06-13 11:07:50 +08:00
|
|
|
template <typename T>
|
2016-04-06 04:45:04 +08:00
|
|
|
static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,
|
2014-09-10 20:51:52 +08:00
|
|
|
COFFSymbolRef Symbol,
|
|
|
|
uint8_t AuxSymbolIdx, const T *&Aux) {
|
2013-04-04 02:31:38 +08:00
|
|
|
ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol);
|
2014-09-10 20:51:52 +08:00
|
|
|
AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize());
|
2013-04-04 02:31:38 +08:00
|
|
|
Aux = reinterpret_cast<const T*>(AuxData.data());
|
|
|
|
return readobj_error::success;
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::cacheRelocations() {
|
2015-07-06 22:26:07 +08:00
|
|
|
if (RelocCached)
|
|
|
|
return;
|
|
|
|
RelocCached = true;
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const SectionRef &S : Obj->sections()) {
|
|
|
|
const coff_section *Section = Obj->getCOFFSection(S);
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const RelocationRef &Reloc : S.relocations())
|
2014-03-14 22:22:49 +08:00
|
|
|
RelocMap[Section].push_back(Reloc);
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
// Sort relocations by address.
|
|
|
|
std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
|
|
|
|
relocAddressLess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-20 07:23:29 +08:00
|
|
|
void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
|
|
|
|
const data_directory *Data;
|
|
|
|
if (Obj->getDataDirectory(Index, Data))
|
|
|
|
return;
|
|
|
|
W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
|
|
|
|
W.printHex(FieldName + "Size", Data->Size);
|
|
|
|
}
|
|
|
|
|
2013-04-04 02:31:38 +08:00
|
|
|
void COFFDumper::printFileHeaders() {
|
2014-09-10 20:51:52 +08:00
|
|
|
time_t TDS = Obj->getTimeDateStamp();
|
2013-04-04 02:31:38 +08:00
|
|
|
char FormattedTime[20] = { };
|
|
|
|
strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
|
|
|
|
|
|
|
|
{
|
|
|
|
DictScope D(W, "ImageFileHeader");
|
2014-09-10 20:51:52 +08:00
|
|
|
W.printEnum ("Machine", Obj->getMachine(),
|
2013-04-04 02:31:38 +08:00
|
|
|
makeArrayRef(ImageFileMachineType));
|
2014-09-10 20:51:52 +08:00
|
|
|
W.printNumber("SectionCount", Obj->getNumberOfSections());
|
|
|
|
W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp());
|
|
|
|
W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable());
|
|
|
|
W.printNumber("SymbolCount", Obj->getNumberOfSymbols());
|
|
|
|
W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader());
|
|
|
|
W.printFlags ("Characteristics", Obj->getCharacteristics(),
|
2013-04-04 02:31:38 +08:00
|
|
|
makeArrayRef(ImageFileCharacteristics));
|
|
|
|
}
|
2013-06-13 03:10:33 +08:00
|
|
|
|
|
|
|
// Print PE header. This header does not exist if this is an object file and
|
|
|
|
// not an executable.
|
2014-04-25 12:24:47 +08:00
|
|
|
const pe32_header *PEHeader = nullptr;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Obj->getPE32Header(PEHeader));
|
2014-01-26 12:15:52 +08:00
|
|
|
if (PEHeader)
|
|
|
|
printPEHeader<pe32_header>(PEHeader);
|
|
|
|
|
2014-04-25 12:24:47 +08:00
|
|
|
const pe32plus_header *PEPlusHeader = nullptr;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Obj->getPE32PlusHeader(PEPlusHeader));
|
2014-01-26 12:15:52 +08:00
|
|
|
if (PEPlusHeader)
|
|
|
|
printPEHeader<pe32plus_header>(PEPlusHeader);
|
2014-11-05 14:24:35 +08:00
|
|
|
|
|
|
|
if (const dos_header *DH = Obj->getDOSHeader())
|
|
|
|
printDOSHeader(DH);
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printDOSHeader(const dos_header *DH) {
|
|
|
|
DictScope D(W, "DOSHeader");
|
|
|
|
W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic)));
|
|
|
|
W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage);
|
|
|
|
W.printNumber("FileSizeInPages", DH->FileSizeInPages);
|
|
|
|
W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems);
|
|
|
|
W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs);
|
|
|
|
W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs);
|
|
|
|
W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs);
|
|
|
|
W.printNumber("InitialRelativeSS", DH->InitialRelativeSS);
|
|
|
|
W.printNumber("InitialSP", DH->InitialSP);
|
|
|
|
W.printNumber("Checksum", DH->Checksum);
|
|
|
|
W.printNumber("InitialIP", DH->InitialIP);
|
|
|
|
W.printNumber("InitialRelativeCS", DH->InitialRelativeCS);
|
|
|
|
W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable);
|
|
|
|
W.printNumber("OverlayNumber", DH->OverlayNumber);
|
|
|
|
W.printNumber("OEMid", DH->OEMid);
|
|
|
|
W.printNumber("OEMinfo", DH->OEMinfo);
|
|
|
|
W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader);
|
2014-01-26 12:15:52 +08:00
|
|
|
}
|
2013-06-13 03:10:33 +08:00
|
|
|
|
2014-01-26 12:15:52 +08:00
|
|
|
template <class PEHeader>
|
|
|
|
void COFFDumper::printPEHeader(const PEHeader *Hdr) {
|
|
|
|
DictScope D(W, "ImageOptionalHeader");
|
|
|
|
W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
|
|
|
|
W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
|
|
|
|
W.printNumber("SizeOfCode", Hdr->SizeOfCode);
|
|
|
|
W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
|
|
|
|
W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
|
|
|
|
W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
|
|
|
|
W.printHex ("BaseOfCode", Hdr->BaseOfCode);
|
|
|
|
printBaseOfDataField(Hdr);
|
|
|
|
W.printHex ("ImageBase", Hdr->ImageBase);
|
|
|
|
W.printNumber("SectionAlignment", Hdr->SectionAlignment);
|
|
|
|
W.printNumber("FileAlignment", Hdr->FileAlignment);
|
|
|
|
W.printNumber("MajorOperatingSystemVersion",
|
|
|
|
Hdr->MajorOperatingSystemVersion);
|
|
|
|
W.printNumber("MinorOperatingSystemVersion",
|
|
|
|
Hdr->MinorOperatingSystemVersion);
|
|
|
|
W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
|
|
|
|
W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
|
|
|
|
W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
|
|
|
|
W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
|
|
|
|
W.printNumber("SizeOfImage", Hdr->SizeOfImage);
|
|
|
|
W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
|
|
|
|
W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
|
2014-11-18 10:45:28 +08:00
|
|
|
W.printFlags ("Characteristics", Hdr->DLLCharacteristics,
|
2014-01-26 12:15:52 +08:00
|
|
|
makeArrayRef(PEDLLCharacteristics));
|
|
|
|
W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
|
|
|
|
W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
|
|
|
|
W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
|
|
|
|
W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
|
|
|
|
W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
|
|
|
|
|
|
|
|
if (Hdr->NumberOfRvaAndSize > 0) {
|
|
|
|
DictScope D(W, "DataDirectory");
|
|
|
|
static const char * const directory[] = {
|
|
|
|
"ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
|
|
|
|
"CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
|
|
|
|
"GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
|
|
|
|
"DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
|
|
|
|
};
|
|
|
|
|
2016-06-03 01:10:43 +08:00
|
|
|
for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i)
|
2014-01-26 12:15:52 +08:00
|
|
|
printDataDirectory(i, directory[i]);
|
2016-06-03 01:10:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printCOFFDebugDirectory() {
|
|
|
|
ListScope LS(W, "DebugDirectory");
|
|
|
|
for (const debug_directory &D : Obj->debug_directories()) {
|
|
|
|
char FormattedTime[20] = {};
|
|
|
|
time_t TDS = D.TimeDateStamp;
|
|
|
|
strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
|
|
|
|
DictScope S(W, "DebugEntry");
|
|
|
|
W.printHex("Characteristics", D.Characteristics);
|
|
|
|
W.printHex("TimeDateStamp", FormattedTime, D.TimeDateStamp);
|
|
|
|
W.printHex("MajorVersion", D.MajorVersion);
|
|
|
|
W.printHex("MinorVersion", D.MinorVersion);
|
|
|
|
W.printEnum("Type", D.Type, makeArrayRef(ImageDebugType));
|
|
|
|
W.printHex("SizeOfData", D.SizeOfData);
|
|
|
|
W.printHex("AddressOfRawData", D.AddressOfRawData);
|
|
|
|
W.printHex("PointerToRawData", D.PointerToRawData);
|
|
|
|
if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) {
|
|
|
|
const debug_pdb_info *PDBInfo;
|
|
|
|
StringRef PDBFileName;
|
|
|
|
error(Obj->getDebugPDBInfo(&D, PDBInfo, PDBFileName));
|
|
|
|
DictScope PDBScope(W, "PDBInfo");
|
|
|
|
W.printHex("PDBSignature", PDBInfo->Signature);
|
|
|
|
W.printBinary("PDBGUID", makeArrayRef(PDBInfo->Guid));
|
|
|
|
W.printNumber("PDBAge", PDBInfo->Age);
|
|
|
|
W.printString("PDBFileName", PDBFileName);
|
|
|
|
} else {
|
|
|
|
// FIXME: Type values of 12 and 13 are commonly observed but are not in
|
|
|
|
// the documented type enum. Figure out what they mean.
|
|
|
|
ArrayRef<uint8_t> RawData;
|
|
|
|
error(
|
|
|
|
Obj->getRvaAndSizeAsBytes(D.AddressOfRawData, D.SizeOfData, RawData));
|
|
|
|
W.printBinaryBlock("RawData", RawData);
|
2013-07-20 07:23:29 +08:00
|
|
|
}
|
2013-06-13 03:10:33 +08:00
|
|
|
}
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
2014-01-26 12:15:52 +08:00
|
|
|
void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
|
|
|
|
W.printHex("BaseOfData", Hdr->BaseOfData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
|
|
|
|
|
2015-12-17 02:28:12 +08:00
|
|
|
void COFFDumper::printCodeViewDebugInfo() {
|
2016-01-14 03:32:35 +08:00
|
|
|
// Print types first to build CVUDTNames, then print symbols.
|
2015-12-17 02:28:12 +08:00
|
|
|
for (const SectionRef &S : Obj->sections()) {
|
2016-01-14 03:32:35 +08:00
|
|
|
StringRef SectionName;
|
|
|
|
error(S.getName(SectionName));
|
|
|
|
if (SectionName == ".debug$T")
|
|
|
|
printCodeViewTypeSection(SectionName, S);
|
|
|
|
}
|
|
|
|
for (const SectionRef &S : Obj->sections()) {
|
|
|
|
StringRef SectionName;
|
|
|
|
error(S.getName(SectionName));
|
|
|
|
if (SectionName == ".debug$S")
|
|
|
|
printCodeViewSymbolSection(SectionName, S);
|
2015-12-17 02:28:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-15 08:11:21 +08:00
|
|
|
void COFFDumper::initializeFileAndStringTables(StringRef Data) {
|
|
|
|
while (!Data.empty() && (CVFileChecksumTable.data() == nullptr ||
|
|
|
|
CVStringTable.data() == nullptr)) {
|
|
|
|
// The section consists of a number of subsection in the following format:
|
|
|
|
// |SubSectionType|SubSectionSize|Contents...|
|
|
|
|
uint32_t SubType, SubSectionSize;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, SubType));
|
|
|
|
error(consume(Data, SubSectionSize));
|
2016-01-15 08:11:21 +08:00
|
|
|
if (SubSectionSize > Data.size())
|
|
|
|
return error(object_error::parse_failed);
|
|
|
|
switch (ModuleSubstreamKind(SubType)) {
|
|
|
|
case ModuleSubstreamKind::FileChecksums:
|
|
|
|
CVFileChecksumTable = Data.substr(0, SubSectionSize);
|
|
|
|
break;
|
|
|
|
case ModuleSubstreamKind::StringTable:
|
|
|
|
CVStringTable = Data.substr(0, SubSectionSize);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-05-29 04:04:48 +08:00
|
|
|
uint32_t PaddedSize = alignTo(SubSectionSize, 4);
|
|
|
|
if (PaddedSize > Data.size())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
Data = Data.drop_front(PaddedSize);
|
2016-01-15 08:11:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
|
|
|
|
const SectionRef &Section) {
|
|
|
|
StringRef SectionContents;
|
|
|
|
error(Section.getContents(SectionContents));
|
|
|
|
StringRef Data = SectionContents;
|
2013-12-19 19:37:14 +08:00
|
|
|
|
|
|
|
SmallVector<StringRef, 10> FunctionNames;
|
|
|
|
StringMap<StringRef> FunctionLineTables;
|
|
|
|
|
2015-02-19 03:32:05 +08:00
|
|
|
ListScope D(W, "CodeViewDebugInfo");
|
2016-01-14 03:32:35 +08:00
|
|
|
// Print the section to allow correlation with printSections.
|
|
|
|
W.printNumber("Section", SectionName, Obj->getSectionID(Section));
|
|
|
|
|
|
|
|
uint32_t Magic;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, Magic));
|
2016-01-14 03:32:35 +08:00
|
|
|
W.printHex("Magic", Magic);
|
|
|
|
if (Magic != COFF::DEBUG_SECTION_MAGIC)
|
|
|
|
return error(object_error::parse_failed);
|
|
|
|
|
2016-01-15 08:11:21 +08:00
|
|
|
initializeFileAndStringTables(Data);
|
|
|
|
|
2016-06-03 11:25:59 +08:00
|
|
|
// TODO: Convert this over to using ModuleSubstreamVisitor.
|
2016-01-14 03:32:35 +08:00
|
|
|
while (!Data.empty()) {
|
|
|
|
// The section consists of a number of subsection in the following format:
|
|
|
|
// |SubSectionType|SubSectionSize|Contents...|
|
|
|
|
uint32_t SubType, SubSectionSize;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, SubType));
|
|
|
|
error(consume(Data, SubSectionSize));
|
2016-01-14 03:32:35 +08:00
|
|
|
|
|
|
|
ListScope S(W, "Subsection");
|
|
|
|
W.printEnum("SubSectionType", SubType, makeArrayRef(SubSectionTypes));
|
|
|
|
W.printHex("SubSectionSize", SubSectionSize);
|
|
|
|
|
|
|
|
// Get the contents of the subsection.
|
|
|
|
if (SubSectionSize > Data.size())
|
|
|
|
return error(object_error::parse_failed);
|
|
|
|
StringRef Contents = Data.substr(0, SubSectionSize);
|
|
|
|
|
|
|
|
// Add SubSectionSize to the current offset and align that offset to find
|
|
|
|
// the next subsection.
|
|
|
|
size_t SectionOffset = Data.data() - SectionContents.data();
|
|
|
|
size_t NextOffset = SectionOffset + SubSectionSize;
|
2016-01-15 05:06:47 +08:00
|
|
|
NextOffset = alignTo(NextOffset, 4);
|
2016-05-29 04:04:50 +08:00
|
|
|
if (NextOffset > SectionContents.size())
|
|
|
|
return error(object_error::parse_failed);
|
2016-01-14 03:32:35 +08:00
|
|
|
Data = SectionContents.drop_front(NextOffset);
|
|
|
|
|
|
|
|
// Optionally print the subsection bytes in case our parsing gets confused
|
|
|
|
// later.
|
|
|
|
if (opts::CodeViewSubsectionBytes)
|
2016-01-16 06:09:13 +08:00
|
|
|
printBinaryBlockWithRelocs("SubSectionContents", Section, SectionContents,
|
|
|
|
Contents);
|
2016-01-14 03:32:35 +08:00
|
|
|
|
|
|
|
switch (ModuleSubstreamKind(SubType)) {
|
|
|
|
case ModuleSubstreamKind::Symbols:
|
2016-01-15 01:51:54 +08:00
|
|
|
printCodeViewSymbolsSubsection(Contents, Section, SectionContents);
|
2016-01-14 03:32:35 +08:00
|
|
|
break;
|
2016-01-15 03:20:17 +08:00
|
|
|
|
|
|
|
case ModuleSubstreamKind::InlineeLines:
|
|
|
|
printCodeViewInlineeLines(Contents);
|
|
|
|
break;
|
|
|
|
|
2016-01-16 02:06:25 +08:00
|
|
|
case ModuleSubstreamKind::FileChecksums:
|
|
|
|
printCodeViewFileChecksums(Contents);
|
|
|
|
break;
|
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
case ModuleSubstreamKind::Lines: {
|
|
|
|
// Holds a PC to file:line table. Some data to parse this subsection is
|
|
|
|
// stored in the other subsections, so just check sanity and store the
|
|
|
|
// pointers for deferred processing.
|
|
|
|
|
|
|
|
if (SubSectionSize < 12) {
|
|
|
|
// There should be at least three words to store two function
|
|
|
|
// relocations and size of the code.
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
return;
|
|
|
|
}
|
2013-12-19 19:37:14 +08:00
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
StringRef LinkageName;
|
|
|
|
error(resolveSymbolName(Obj->getCOFFSection(Section), SectionOffset,
|
|
|
|
LinkageName));
|
|
|
|
W.printString("LinkageName", LinkageName);
|
|
|
|
if (FunctionLineTables.count(LinkageName) != 0) {
|
|
|
|
// Saw debug info for this function already?
|
2013-12-19 19:37:14 +08:00
|
|
|
error(object_error::parse_failed);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
FunctionLineTables[LinkageName] = Contents;
|
|
|
|
FunctionNames.push_back(LinkageName);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ModuleSubstreamKind::FrameData: {
|
2016-01-16 06:09:13 +08:00
|
|
|
// First four bytes is a relocation against the function.
|
|
|
|
const uint32_t *CodePtr;
|
|
|
|
error(consumeObject(Contents, CodePtr));
|
2016-01-14 03:32:35 +08:00
|
|
|
StringRef LinkageName;
|
2016-01-16 06:09:13 +08:00
|
|
|
error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,
|
|
|
|
CodePtr, LinkageName));
|
|
|
|
W.printString("LinkageName", LinkageName);
|
|
|
|
|
|
|
|
// To find the active frame description, search this array for the
|
|
|
|
// smallest PC range that includes the current PC.
|
|
|
|
while (!Contents.empty()) {
|
|
|
|
const FrameData *FD;
|
|
|
|
error(consumeObject(Contents, FD));
|
2016-05-29 03:45:49 +08:00
|
|
|
|
|
|
|
if (FD->FrameFunc >= CVStringTable.size())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
|
|
|
|
StringRef FrameFunc =
|
|
|
|
CVStringTable.drop_front(FD->FrameFunc).split('\0').first;
|
|
|
|
|
2016-01-16 06:09:13 +08:00
|
|
|
DictScope S(W, "FrameData");
|
|
|
|
W.printHex("RvaStart", FD->RvaStart);
|
|
|
|
W.printHex("CodeSize", FD->CodeSize);
|
|
|
|
W.printHex("LocalSize", FD->LocalSize);
|
|
|
|
W.printHex("ParamsSize", FD->ParamsSize);
|
|
|
|
W.printHex("MaxStackSize", FD->MaxStackSize);
|
2016-05-29 03:45:49 +08:00
|
|
|
W.printString("FrameFunc", FrameFunc);
|
2016-01-16 06:09:13 +08:00
|
|
|
W.printHex("PrologSize", FD->PrologSize);
|
|
|
|
W.printHex("SavedRegsSize", FD->SavedRegsSize);
|
|
|
|
W.printFlags("Flags", FD->Flags, makeArrayRef(FrameDataFlags));
|
2013-12-19 19:37:14 +08:00
|
|
|
}
|
2016-01-14 03:32:35 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-12-19 19:37:14 +08:00
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
// Do nothing for unrecognized subsections.
|
|
|
|
default:
|
|
|
|
break;
|
2013-12-19 19:37:14 +08:00
|
|
|
}
|
2016-01-16 06:09:13 +08:00
|
|
|
W.flush();
|
2013-12-19 19:37:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Dump the line tables now that we've read all the subsections and know all
|
|
|
|
// the required information.
|
|
|
|
for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
|
|
|
|
StringRef Name = FunctionNames[I];
|
|
|
|
ListScope S(W, "FunctionLineTable");
|
2015-12-15 09:23:55 +08:00
|
|
|
W.printString("LinkageName", Name);
|
2013-12-19 19:37:14 +08:00
|
|
|
|
|
|
|
DataExtractor DE(FunctionLineTables[Name], true, 4);
|
2015-07-09 08:19:51 +08:00
|
|
|
uint32_t Offset = 6; // Skip relocations.
|
|
|
|
uint16_t Flags = DE.getU16(&Offset);
|
|
|
|
W.printHex("Flags", Flags);
|
2016-01-29 08:49:42 +08:00
|
|
|
bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns;
|
2013-12-19 19:37:14 +08:00
|
|
|
uint32_t FunctionSize = DE.getU32(&Offset);
|
|
|
|
W.printHex("CodeSize", FunctionSize);
|
|
|
|
while (DE.isValidOffset(Offset)) {
|
|
|
|
// For each range of lines with the same filename, we have a segment
|
|
|
|
// in the line table. The filename string is accessed using double
|
|
|
|
// indirection to the string table subsection using the index subsection.
|
|
|
|
uint32_t OffsetInIndex = DE.getU32(&Offset),
|
2016-01-13 09:05:16 +08:00
|
|
|
NumLines = DE.getU32(&Offset),
|
2015-07-10 02:14:31 +08:00
|
|
|
FullSegmentSize = DE.getU32(&Offset);
|
|
|
|
|
2016-01-13 09:05:16 +08:00
|
|
|
uint32_t ColumnOffset = Offset + 8 * NumLines;
|
|
|
|
DataExtractor ColumnDE(DE.getData(), true, 4);
|
|
|
|
|
2015-07-10 02:14:31 +08:00
|
|
|
if (FullSegmentSize !=
|
2016-01-13 09:05:16 +08:00
|
|
|
12 + 8 * NumLines + (HasColumnInformation ? 4 * NumLines : 0)) {
|
2015-07-10 02:14:31 +08:00
|
|
|
error(object_error::parse_failed);
|
|
|
|
return;
|
|
|
|
}
|
2015-07-09 12:27:36 +08:00
|
|
|
|
2013-12-19 19:37:14 +08:00
|
|
|
ListScope S(W, "FilenameSegment");
|
2016-01-15 08:11:21 +08:00
|
|
|
printFileNameForOffset("Filename", OffsetInIndex);
|
2016-01-13 09:05:16 +08:00
|
|
|
for (unsigned LineIdx = 0;
|
|
|
|
LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
|
2013-12-19 19:37:14 +08:00
|
|
|
// Then go the (PC, LineNumber) pairs. The line number is stored in the
|
|
|
|
// least significant 31 bits of the respective word in the table.
|
2016-01-13 09:05:16 +08:00
|
|
|
uint32_t PC = DE.getU32(&Offset), LineData = DE.getU32(&Offset);
|
2013-12-19 19:37:14 +08:00
|
|
|
if (PC >= FunctionSize) {
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
char Buffer[32];
|
|
|
|
format("+0x%X", PC).snprint(Buffer, 32);
|
2016-01-13 09:05:16 +08:00
|
|
|
ListScope PCScope(W, Buffer);
|
2016-02-05 01:57:12 +08:00
|
|
|
LineInfo LI(LineData);
|
|
|
|
if (LI.isAlwaysStepInto())
|
|
|
|
W.printString("StepInto", StringRef("Always"));
|
|
|
|
else if (LI.isNeverStepInto())
|
|
|
|
W.printString("StepInto", StringRef("Never"));
|
|
|
|
else
|
|
|
|
W.printNumber("LineNumberStart", LI.getStartLine());
|
|
|
|
W.printNumber("LineNumberEndDelta", LI.getLineDelta());
|
|
|
|
W.printBoolean("IsStatement", LI.isStatement());
|
2016-01-13 09:05:16 +08:00
|
|
|
if (HasColumnInformation &&
|
|
|
|
ColumnDE.isValidOffsetForDataOfSize(ColumnOffset, 4)) {
|
|
|
|
uint16_t ColStart = ColumnDE.getU16(&ColumnOffset);
|
2015-07-09 08:19:51 +08:00
|
|
|
W.printNumber("ColStart", ColStart);
|
2016-01-13 09:05:16 +08:00
|
|
|
uint16_t ColEnd = ColumnDE.getU16(&ColumnOffset);
|
2015-07-09 08:19:51 +08:00
|
|
|
W.printNumber("ColEnd", ColEnd);
|
|
|
|
}
|
|
|
|
}
|
2016-01-13 09:05:16 +08:00
|
|
|
// Skip over the column data.
|
|
|
|
if (HasColumnInformation) {
|
|
|
|
for (unsigned LineIdx = 0;
|
|
|
|
LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
|
|
|
|
DE.getU32(&Offset);
|
|
|
|
}
|
|
|
|
}
|
2013-12-19 19:37:14 +08:00
|
|
|
}
|
|
|
|
}
|
2016-01-14 03:32:35 +08:00
|
|
|
}
|
|
|
|
|
2014-10-24 06:25:31 +08:00
|
|
|
void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
|
|
|
|
const SectionRef &Section,
|
2016-01-15 01:51:54 +08:00
|
|
|
StringRef SectionContents) {
|
2016-05-24 07:41:13 +08:00
|
|
|
ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
|
|
|
|
Subsection.bytes_end());
|
|
|
|
auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
|
|
|
|
SectionContents);
|
2016-01-14 03:32:35 +08:00
|
|
|
|
2016-05-24 07:41:13 +08:00
|
|
|
CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes);
|
2016-06-10 13:09:12 +08:00
|
|
|
ByteStream<> Stream(BinaryData);
|
2016-05-28 13:21:57 +08:00
|
|
|
CVSymbolArray Symbols;
|
|
|
|
StreamReader Reader(Stream);
|
|
|
|
if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
|
|
|
|
consumeError(std::move(EC));
|
|
|
|
W.flush();
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
}
|
2016-01-14 03:32:35 +08:00
|
|
|
|
2016-05-28 13:21:57 +08:00
|
|
|
if (!CVSD.dump(Symbols)) {
|
2016-01-16 06:09:13 +08:00
|
|
|
W.flush();
|
2016-05-24 07:41:13 +08:00
|
|
|
error(object_error::parse_failed);
|
2016-01-14 03:32:35 +08:00
|
|
|
}
|
2016-01-16 06:09:13 +08:00
|
|
|
W.flush();
|
2016-01-14 03:32:35 +08:00
|
|
|
}
|
|
|
|
|
2016-01-16 02:06:25 +08:00
|
|
|
void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
|
|
|
|
StringRef Data = Subsection;
|
|
|
|
while (!Data.empty()) {
|
|
|
|
DictScope S(W, "FileChecksum");
|
|
|
|
const FileChecksum *FC;
|
|
|
|
error(consumeObject(Data, FC));
|
|
|
|
if (FC->FileNameOffset >= CVStringTable.size())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
StringRef Filename =
|
|
|
|
CVStringTable.drop_front(FC->FileNameOffset).split('\0').first;
|
|
|
|
W.printHex("Filename", Filename, FC->FileNameOffset);
|
|
|
|
W.printHex("ChecksumSize", FC->ChecksumSize);
|
|
|
|
W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind),
|
|
|
|
makeArrayRef(FileChecksumKindNames));
|
|
|
|
if (FC->ChecksumSize >= Data.size())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
StringRef ChecksumBytes = Data.substr(0, FC->ChecksumSize);
|
|
|
|
W.printBinary("ChecksumBytes", ChecksumBytes);
|
2016-01-19 04:55:24 +08:00
|
|
|
unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) -
|
|
|
|
sizeof(FileChecksum);
|
2016-05-29 03:45:58 +08:00
|
|
|
if (PaddedSize > Data.size())
|
|
|
|
error(object_error::parse_failed);
|
2016-01-16 02:06:25 +08:00
|
|
|
Data = Data.drop_front(PaddedSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-15 03:20:17 +08:00
|
|
|
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
|
|
|
|
StringRef Data = Subsection;
|
|
|
|
uint32_t Signature;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, Signature));
|
2016-01-15 03:20:17 +08:00
|
|
|
bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
|
|
|
|
|
|
|
|
while (!Data.empty()) {
|
|
|
|
const InlineeSourceLine *ISL;
|
|
|
|
error(consumeObject(Data, ISL));
|
|
|
|
DictScope S(W, "InlineeSourceLine");
|
|
|
|
printTypeIndex("Inlinee", ISL->Inlinee);
|
2016-01-15 08:11:21 +08:00
|
|
|
printFileNameForOffset("FileID", ISL->FileID);
|
2016-01-15 03:20:17 +08:00
|
|
|
W.printNumber("SourceLineNum", ISL->SourceLineNum);
|
|
|
|
|
|
|
|
if (HasExtraFiles) {
|
|
|
|
uint32_t ExtraFileCount;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, ExtraFileCount));
|
2016-01-15 03:20:17 +08:00
|
|
|
W.printNumber("ExtraFileCount", ExtraFileCount);
|
|
|
|
ListScope ExtraFiles(W, "ExtraFiles");
|
|
|
|
for (unsigned I = 0; I < ExtraFileCount; ++I) {
|
|
|
|
uint32_t FileID;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, FileID));
|
2016-01-15 08:11:21 +08:00
|
|
|
printFileNameForOffset("FileID", FileID);
|
2016-01-15 03:20:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-15 08:11:21 +08:00
|
|
|
StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) {
|
|
|
|
// The file checksum subsection should precede all references to it.
|
|
|
|
if (!CVFileChecksumTable.data() || !CVStringTable.data())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
// Check if the file checksum table offset is valid.
|
|
|
|
if (FileOffset >= CVFileChecksumTable.size())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
|
|
|
|
// The string table offset comes first before the file checksum.
|
|
|
|
StringRef Data = CVFileChecksumTable.drop_front(FileOffset);
|
|
|
|
uint32_t StringOffset;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, StringOffset));
|
2016-01-15 08:11:21 +08:00
|
|
|
|
|
|
|
// Check if the string table offset is valid.
|
|
|
|
if (StringOffset >= CVStringTable.size())
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
|
|
|
|
// Return the null-terminated string.
|
|
|
|
return CVStringTable.drop_front(StringOffset).split('\0').first;
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) {
|
|
|
|
W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset);
|
|
|
|
}
|
|
|
|
|
2016-05-14 08:02:53 +08:00
|
|
|
void COFFDumper::mergeCodeViewTypes(MemoryTypeTableBuilder &CVTypes) {
|
|
|
|
for (const SectionRef &S : Obj->sections()) {
|
|
|
|
StringRef SectionName;
|
|
|
|
error(S.getName(SectionName));
|
|
|
|
if (SectionName == ".debug$T") {
|
|
|
|
StringRef Data;
|
|
|
|
error(S.getContents(Data));
|
2016-05-29 03:17:48 +08:00
|
|
|
uint32_t Magic;
|
|
|
|
error(consume(Data, Magic));
|
2016-05-14 08:02:53 +08:00
|
|
|
if (Magic != 4)
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
|
|
|
|
Data.size());
|
2016-06-10 13:09:12 +08:00
|
|
|
ByteStream<> Stream(Bytes);
|
2016-05-28 13:21:57 +08:00
|
|
|
CVTypeArray Types;
|
|
|
|
StreamReader Reader(Stream);
|
|
|
|
if (auto EC = Reader.readArray(Types, Reader.getLength())) {
|
|
|
|
consumeError(std::move(EC));
|
|
|
|
W.flush();
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mergeTypeStreams(CVTypes, Types))
|
2016-05-14 08:02:53 +08:00
|
|
|
return error(object_error::parse_failed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
|
|
|
|
const SectionRef &Section) {
|
|
|
|
ListScope D(W, "CodeViewTypes");
|
|
|
|
W.printNumber("Section", SectionName, Obj->getSectionID(Section));
|
2016-05-03 07:45:03 +08:00
|
|
|
|
2016-01-14 03:32:35 +08:00
|
|
|
StringRef Data;
|
|
|
|
error(Section.getContents(Data));
|
2016-05-03 02:10:00 +08:00
|
|
|
if (opts::CodeViewSubsectionBytes)
|
|
|
|
W.printBinaryBlock("Data", Data);
|
2016-05-03 04:30:47 +08:00
|
|
|
|
2016-05-04 06:18:17 +08:00
|
|
|
uint32_t Magic;
|
2016-05-13 01:45:44 +08:00
|
|
|
error(consume(Data, Magic));
|
2016-05-05 03:39:28 +08:00
|
|
|
W.printHex("Magic", Magic);
|
2016-05-04 06:18:17 +08:00
|
|
|
if (Magic != COFF::DEBUG_SECTION_MAGIC)
|
2016-05-05 03:39:28 +08:00
|
|
|
return error(object_error::parse_failed);
|
2016-01-14 03:32:35 +08:00
|
|
|
|
2016-06-17 02:09:04 +08:00
|
|
|
if (!CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) {
|
2016-05-05 08:34:33 +08:00
|
|
|
W.flush();
|
2016-06-17 02:09:04 +08:00
|
|
|
error(object_error::parse_failed);
|
2016-05-05 03:39:28 +08:00
|
|
|
}
|
|
|
|
}
|
2016-01-14 03:32:35 +08:00
|
|
|
|
2013-04-04 02:31:38 +08:00
|
|
|
void COFFDumper::printSections() {
|
|
|
|
ListScope SectionsD(W, "Sections");
|
|
|
|
int SectionNumber = 0;
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const SectionRef &Sec : Obj->sections()) {
|
2013-04-04 02:31:38 +08:00
|
|
|
++SectionNumber;
|
2014-03-18 14:53:02 +08:00
|
|
|
const coff_section *Section = Obj->getCOFFSection(Sec);
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
StringRef Name;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Sec.getName(Name));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
DictScope D(W, "Section");
|
|
|
|
W.printNumber("Number", SectionNumber);
|
|
|
|
W.printBinary("Name", Name, Section->Name);
|
|
|
|
W.printHex ("VirtualSize", Section->VirtualSize);
|
|
|
|
W.printHex ("VirtualAddress", Section->VirtualAddress);
|
|
|
|
W.printNumber("RawDataSize", Section->SizeOfRawData);
|
|
|
|
W.printHex ("PointerToRawData", Section->PointerToRawData);
|
|
|
|
W.printHex ("PointerToRelocations", Section->PointerToRelocations);
|
|
|
|
W.printHex ("PointerToLineNumbers", Section->PointerToLinenumbers);
|
|
|
|
W.printNumber("RelocationCount", Section->NumberOfRelocations);
|
|
|
|
W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);
|
|
|
|
W.printFlags ("Characteristics", Section->Characteristics,
|
|
|
|
makeArrayRef(ImageSectionCharacteristics),
|
|
|
|
COFF::SectionCharacteristics(0x00F00000));
|
|
|
|
|
|
|
|
if (opts::SectionRelocations) {
|
|
|
|
ListScope D(W, "Relocations");
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const RelocationRef &Reloc : Sec.relocations())
|
|
|
|
printRelocation(Sec, Reloc);
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (opts::SectionSymbols) {
|
|
|
|
ListScope D(W, "Symbols");
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const SymbolRef &Symbol : Obj->symbols()) {
|
2014-10-08 23:28:58 +08:00
|
|
|
if (!Sec.containsSymbol(Symbol))
|
2013-04-04 02:31:38 +08:00
|
|
|
continue;
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
printSymbol(Symbol);
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 06:32:16 +08:00
|
|
|
if (opts::SectionData &&
|
|
|
|
!(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
|
2013-04-04 02:31:38 +08:00
|
|
|
StringRef Data;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Sec.getContents(Data));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
W.printBinaryBlock("SectionData", Data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printRelocations() {
|
|
|
|
ListScope D(W, "Relocations");
|
|
|
|
|
|
|
|
int SectionNumber = 0;
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const SectionRef &Section : Obj->sections()) {
|
2013-04-04 02:31:38 +08:00
|
|
|
++SectionNumber;
|
|
|
|
StringRef Name;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Section.getName(Name));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
bool PrintedGroup = false;
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const RelocationRef &Reloc : Section.relocations()) {
|
2013-04-04 02:31:38 +08:00
|
|
|
if (!PrintedGroup) {
|
|
|
|
W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
|
|
|
|
W.indent();
|
|
|
|
PrintedGroup = true;
|
|
|
|
}
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
printRelocation(Section, Reloc);
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (PrintedGroup) {
|
|
|
|
W.unindent();
|
|
|
|
W.startLine() << "}\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
void COFFDumper::printRelocation(const SectionRef &Section,
|
2016-01-15 01:51:57 +08:00
|
|
|
const RelocationRef &Reloc, uint64_t Bias) {
|
|
|
|
uint64_t Offset = Reloc.getOffset() - Bias;
|
2015-06-30 09:53:01 +08:00
|
|
|
uint64_t RelocType = Reloc.getType();
|
2013-04-04 02:31:38 +08:00
|
|
|
SmallString<32> RelocName;
|
|
|
|
StringRef SymbolName;
|
2015-06-30 12:08:37 +08:00
|
|
|
Reloc.getTypeName(RelocName);
|
2014-03-14 22:22:49 +08:00
|
|
|
symbol_iterator Symbol = Reloc.getSymbol();
|
2015-07-03 04:55:21 +08:00
|
|
|
if (Symbol != Obj->symbol_end()) {
|
2016-04-21 05:24:34 +08:00
|
|
|
Expected<StringRef> SymbolNameOrErr = Symbol->getName();
|
|
|
|
error(errorToErrorCode(SymbolNameOrErr.takeError()));
|
2015-07-03 04:55:21 +08:00
|
|
|
SymbolName = *SymbolNameOrErr;
|
|
|
|
}
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2013-04-12 12:01:52 +08:00
|
|
|
if (opts::ExpandRelocs) {
|
|
|
|
DictScope Group(W, "Relocation");
|
|
|
|
W.printHex("Offset", Offset);
|
|
|
|
W.printNumber("Type", RelocName, RelocType);
|
2014-11-13 15:42:11 +08:00
|
|
|
W.printString("Symbol", SymbolName.empty() ? "-" : SymbolName);
|
2013-04-12 12:01:52 +08:00
|
|
|
} else {
|
|
|
|
raw_ostream& OS = W.startLine();
|
|
|
|
OS << W.hex(Offset)
|
|
|
|
<< " " << RelocName
|
2014-11-13 15:42:11 +08:00
|
|
|
<< " " << (SymbolName.empty() ? "-" : SymbolName)
|
2013-04-12 12:01:52 +08:00
|
|
|
<< "\n";
|
|
|
|
}
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printSymbols() {
|
|
|
|
ListScope Group(W, "Symbols");
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
for (const SymbolRef &Symbol : Obj->symbols())
|
|
|
|
printSymbol(Symbol);
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static ErrorOr<StringRef>
|
2014-11-17 19:17:17 +08:00
|
|
|
getSectionName(const llvm::object::COFFObjectFile *Obj, int32_t SectionNumber,
|
|
|
|
const coff_section *Section) {
|
2014-09-20 08:25:06 +08:00
|
|
|
if (Section) {
|
|
|
|
StringRef SectionName;
|
2014-11-17 19:17:17 +08:00
|
|
|
if (std::error_code EC = Obj->getSectionName(Section, SectionName))
|
|
|
|
return EC;
|
2014-09-20 08:25:06 +08:00
|
|
|
return SectionName;
|
|
|
|
}
|
|
|
|
if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
|
2014-11-17 19:17:17 +08:00
|
|
|
return StringRef("IMAGE_SYM_DEBUG");
|
2014-09-20 08:25:06 +08:00
|
|
|
if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE)
|
2014-11-17 19:17:17 +08:00
|
|
|
return StringRef("IMAGE_SYM_ABSOLUTE");
|
2014-09-20 08:25:06 +08:00
|
|
|
if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED)
|
2014-11-17 19:17:17 +08:00
|
|
|
return StringRef("IMAGE_SYM_UNDEFINED");
|
|
|
|
return StringRef("");
|
2014-09-20 08:25:06 +08:00
|
|
|
}
|
|
|
|
|
2014-03-18 14:53:02 +08:00
|
|
|
void COFFDumper::printSymbol(const SymbolRef &Sym) {
|
2013-04-04 02:31:38 +08:00
|
|
|
DictScope D(W, "Symbol");
|
|
|
|
|
2014-09-10 20:51:52 +08:00
|
|
|
COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym);
|
2013-04-04 02:31:38 +08:00
|
|
|
const coff_section *Section;
|
2014-09-10 20:51:52 +08:00
|
|
|
if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) {
|
2013-04-04 02:31:38 +08:00
|
|
|
W.startLine() << "Invalid section number: " << EC.message() << "\n";
|
|
|
|
W.flush();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef SymbolName;
|
|
|
|
if (Obj->getSymbolName(Symbol, SymbolName))
|
|
|
|
SymbolName = "";
|
|
|
|
|
2014-11-17 19:17:17 +08:00
|
|
|
StringRef SectionName = "";
|
|
|
|
ErrorOr<StringRef> Res =
|
|
|
|
getSectionName(Obj, Symbol.getSectionNumber(), Section);
|
|
|
|
if (Res)
|
|
|
|
SectionName = *Res;
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
W.printString("Name", SymbolName);
|
2014-09-10 20:51:52 +08:00
|
|
|
W.printNumber("Value", Symbol.getValue());
|
|
|
|
W.printNumber("Section", SectionName, Symbol.getSectionNumber());
|
|
|
|
W.printEnum ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType));
|
|
|
|
W.printEnum ("ComplexType", Symbol.getComplexType(),
|
2013-04-04 02:31:38 +08:00
|
|
|
makeArrayRef(ImageSymDType));
|
2014-09-10 20:51:52 +08:00
|
|
|
W.printEnum ("StorageClass", Symbol.getStorageClass(),
|
2013-04-04 02:31:38 +08:00
|
|
|
makeArrayRef(ImageSymClass));
|
2014-09-10 20:51:52 +08:00
|
|
|
W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols());
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-09-10 20:51:52 +08:00
|
|
|
for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
|
|
|
|
if (Symbol.isFunctionDefinition()) {
|
2013-04-04 02:31:38 +08:00
|
|
|
const coff_aux_function_definition *Aux;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(getSymbolAuxData(Obj, Symbol, I, Aux));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
DictScope AS(W, "AuxFunctionDef");
|
|
|
|
W.printNumber("TagIndex", Aux->TagIndex);
|
|
|
|
W.printNumber("TotalSize", Aux->TotalSize);
|
2014-03-19 12:33:27 +08:00
|
|
|
W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
|
2013-04-04 02:31:38 +08:00
|
|
|
W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
|
|
|
|
|
2014-10-31 13:07:00 +08:00
|
|
|
} else if (Symbol.isAnyUndefined()) {
|
2014-03-19 12:33:27 +08:00
|
|
|
const coff_aux_weak_external *Aux;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(getSymbolAuxData(Obj, Symbol, I, Aux));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-09-10 20:51:52 +08:00
|
|
|
ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
|
2013-04-04 02:31:38 +08:00
|
|
|
StringRef LinkedName;
|
2014-09-10 20:51:52 +08:00
|
|
|
std::error_code EC = Linked.getError();
|
|
|
|
if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) {
|
2013-04-04 02:31:38 +08:00
|
|
|
LinkedName = "";
|
|
|
|
error(EC);
|
|
|
|
}
|
|
|
|
|
|
|
|
DictScope AS(W, "AuxWeakExternal");
|
|
|
|
W.printNumber("Linked", LinkedName, Aux->TagIndex);
|
|
|
|
W.printEnum ("Search", Aux->Characteristics,
|
|
|
|
makeArrayRef(WeakExternalCharacteristics));
|
|
|
|
|
2014-09-10 20:51:52 +08:00
|
|
|
} else if (Symbol.isFileRecord()) {
|
|
|
|
const char *FileName;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(getSymbolAuxData(Obj, Symbol, I, FileName));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2013-04-22 16:35:11 +08:00
|
|
|
DictScope AS(W, "AuxFileRecord");
|
2014-04-14 10:37:23 +08:00
|
|
|
|
2014-09-10 20:51:52 +08:00
|
|
|
StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() *
|
|
|
|
Obj->getSymbolTableEntrySize());
|
2014-04-14 10:37:23 +08:00
|
|
|
W.printString("FileName", Name.rtrim(StringRef("\0", 1)));
|
2014-04-16 12:15:29 +08:00
|
|
|
break;
|
2014-09-10 20:51:52 +08:00
|
|
|
} else if (Symbol.isSectionDefinition()) {
|
2013-04-04 02:31:38 +08:00
|
|
|
const coff_aux_section_definition *Aux;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(getSymbolAuxData(Obj, Symbol, I, Aux));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-09-16 03:42:42 +08:00
|
|
|
int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
|
|
|
|
|
2013-04-04 02:31:38 +08:00
|
|
|
DictScope AS(W, "AuxSectionDef");
|
|
|
|
W.printNumber("Length", Aux->Length);
|
|
|
|
W.printNumber("RelocationCount", Aux->NumberOfRelocations);
|
|
|
|
W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
|
|
|
|
W.printHex("Checksum", Aux->CheckSum);
|
2014-09-16 03:42:42 +08:00
|
|
|
W.printNumber("Number", AuxNumber);
|
2013-04-04 02:31:38 +08:00
|
|
|
W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
|
|
|
|
|
2013-04-22 16:34:59 +08:00
|
|
|
if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
|
2013-04-04 02:31:38 +08:00
|
|
|
&& Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
|
|
|
|
const coff_section *Assoc;
|
2014-11-17 19:17:17 +08:00
|
|
|
StringRef AssocName = "";
|
|
|
|
std::error_code EC = Obj->getSection(AuxNumber, Assoc);
|
|
|
|
ErrorOr<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc);
|
|
|
|
if (Res)
|
|
|
|
AssocName = *Res;
|
|
|
|
if (!EC)
|
|
|
|
EC = Res.getError();
|
|
|
|
if (EC) {
|
2013-04-04 02:31:38 +08:00
|
|
|
AssocName = "";
|
|
|
|
error(EC);
|
|
|
|
}
|
|
|
|
|
2014-09-16 03:42:42 +08:00
|
|
|
W.printNumber("AssocSection", AssocName, AuxNumber);
|
2013-04-04 02:31:38 +08:00
|
|
|
}
|
2014-09-10 20:51:52 +08:00
|
|
|
} else if (Symbol.isCLRToken()) {
|
2013-04-04 02:31:38 +08:00
|
|
|
const coff_aux_clr_token *Aux;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(getSymbolAuxData(Obj, Symbol, I, Aux));
|
2013-04-04 02:31:38 +08:00
|
|
|
|
2014-09-10 20:51:52 +08:00
|
|
|
ErrorOr<COFFSymbolRef> ReferredSym =
|
|
|
|
Obj->getSymbol(Aux->SymbolTableIndex);
|
2014-03-17 09:46:52 +08:00
|
|
|
StringRef ReferredName;
|
2014-09-10 20:51:52 +08:00
|
|
|
std::error_code EC = ReferredSym.getError();
|
|
|
|
if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) {
|
2014-03-17 09:46:52 +08:00
|
|
|
ReferredName = "";
|
|
|
|
error(EC);
|
|
|
|
}
|
|
|
|
|
2013-04-04 02:31:38 +08:00
|
|
|
DictScope AS(W, "AuxCLRToken");
|
|
|
|
W.printNumber("AuxType", Aux->AuxType);
|
|
|
|
W.printNumber("Reserved", Aux->Reserved);
|
2014-03-17 09:46:52 +08:00
|
|
|
W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex);
|
2013-04-04 02:31:38 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
W.startLine() << "<unhandled auxiliary record>\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printUnwindInfo() {
|
|
|
|
ListScope D(W, "UnwindInformation");
|
2014-09-10 20:51:52 +08:00
|
|
|
switch (Obj->getMachine()) {
|
2014-05-26 04:26:45 +08:00
|
|
|
case COFF::IMAGE_FILE_MACHINE_AMD64: {
|
|
|
|
Win64EH::Dumper Dumper(W);
|
2014-06-13 11:07:50 +08:00
|
|
|
Win64EH::Dumper::SymbolResolver
|
|
|
|
Resolver = [](const object::coff_section *Section, uint64_t Offset,
|
|
|
|
SymbolRef &Symbol, void *user_data) -> std::error_code {
|
|
|
|
COFFDumper *Dumper = reinterpret_cast<COFFDumper *>(user_data);
|
|
|
|
return Dumper->resolveSymbol(Section, Offset, Symbol);
|
|
|
|
};
|
2014-05-26 05:37:59 +08:00
|
|
|
Win64EH::Dumper::Context Ctx(*Obj, Resolver, this);
|
2014-05-26 04:26:45 +08:00
|
|
|
Dumper.printData(Ctx);
|
2013-04-04 02:31:38 +08:00
|
|
|
break;
|
2014-05-26 04:26:45 +08:00
|
|
|
}
|
2014-06-04 23:47:15 +08:00
|
|
|
case COFF::IMAGE_FILE_MACHINE_ARMNT: {
|
|
|
|
ARM::WinEH::Decoder Decoder(W);
|
|
|
|
Decoder.dumpProcedureData(*Obj);
|
|
|
|
break;
|
|
|
|
}
|
2014-05-26 04:26:45 +08:00
|
|
|
default:
|
2014-09-10 20:51:52 +08:00
|
|
|
W.printEnum("unsupported Image Machine", Obj->getMachine(),
|
2014-05-26 04:26:45 +08:00
|
|
|
makeArrayRef(ImageFileMachineType));
|
2013-04-04 02:31:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-05-26 04:26:45 +08:00
|
|
|
|
2014-10-09 10:16:38 +08:00
|
|
|
void COFFDumper::printImportedSymbols(
|
|
|
|
iterator_range<imported_symbol_iterator> Range) {
|
|
|
|
for (const ImportedSymbolRef &I : Range) {
|
2014-10-03 08:41:58 +08:00
|
|
|
StringRef Sym;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getSymbolName(Sym));
|
2014-10-03 08:41:58 +08:00
|
|
|
uint16_t Ordinal;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getOrdinal(Ordinal));
|
2014-10-03 08:41:58 +08:00
|
|
|
W.printNumber("Symbol", Sym, Ordinal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-13 11:22:54 +08:00
|
|
|
void COFFDumper::printDelayImportedSymbols(
|
|
|
|
const DelayImportDirectoryEntryRef &I,
|
|
|
|
iterator_range<imported_symbol_iterator> Range) {
|
|
|
|
int Index = 0;
|
|
|
|
for (const ImportedSymbolRef &S : Range) {
|
|
|
|
DictScope Import(W, "Import");
|
|
|
|
StringRef Sym;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(S.getSymbolName(Sym));
|
2014-11-13 11:22:54 +08:00
|
|
|
uint16_t Ordinal;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(S.getOrdinal(Ordinal));
|
2014-11-13 11:22:54 +08:00
|
|
|
W.printNumber("Symbol", Sym, Ordinal);
|
|
|
|
uint64_t Addr;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getImportAddress(Index++, Addr));
|
2014-11-13 11:22:54 +08:00
|
|
|
W.printHex("Address", Addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-03 01:02:18 +08:00
|
|
|
void COFFDumper::printCOFFImports() {
|
2014-10-03 08:41:58 +08:00
|
|
|
// Regular imports
|
2014-10-09 10:16:38 +08:00
|
|
|
for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {
|
2014-10-03 01:02:18 +08:00
|
|
|
DictScope Import(W, "Import");
|
|
|
|
StringRef Name;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getName(Name));
|
2014-10-03 01:02:18 +08:00
|
|
|
W.printString("Name", Name);
|
|
|
|
uint32_t Addr;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getImportLookupTableRVA(Addr));
|
2014-10-03 01:02:18 +08:00
|
|
|
W.printHex("ImportLookupTableRVA", Addr);
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getImportAddressTableRVA(Addr));
|
2014-10-03 01:02:18 +08:00
|
|
|
W.printHex("ImportAddressTableRVA", Addr);
|
2014-10-09 10:16:38 +08:00
|
|
|
printImportedSymbols(I.imported_symbols());
|
2014-10-03 08:41:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delay imports
|
2014-10-09 10:16:38 +08:00
|
|
|
for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {
|
2014-10-03 08:41:58 +08:00
|
|
|
DictScope Import(W, "DelayImport");
|
|
|
|
StringRef Name;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getName(Name));
|
2014-10-03 08:41:58 +08:00
|
|
|
W.printString("Name", Name);
|
2014-10-04 02:07:18 +08:00
|
|
|
const delay_import_directory_table_entry *Table;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getDelayImportTable(Table));
|
2014-10-04 02:07:18 +08:00
|
|
|
W.printHex("Attributes", Table->Attributes);
|
|
|
|
W.printHex("ModuleHandle", Table->ModuleHandle);
|
|
|
|
W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
|
|
|
|
W.printHex("ImportNameTable", Table->DelayImportNameTable);
|
|
|
|
W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable);
|
|
|
|
W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable);
|
2014-11-13 11:22:54 +08:00
|
|
|
printDelayImportedSymbols(I, I.imported_symbols());
|
2014-10-03 01:02:18 +08:00
|
|
|
}
|
|
|
|
}
|
2014-10-08 03:37:52 +08:00
|
|
|
|
2015-01-04 05:35:09 +08:00
|
|
|
void COFFDumper::printCOFFExports() {
|
|
|
|
for (const ExportDirectoryEntryRef &E : Obj->export_directories()) {
|
|
|
|
DictScope Export(W, "Export");
|
|
|
|
|
|
|
|
StringRef Name;
|
|
|
|
uint32_t Ordinal, RVA;
|
|
|
|
|
2015-07-20 11:23:55 +08:00
|
|
|
error(E.getSymbolName(Name));
|
|
|
|
error(E.getOrdinal(Ordinal));
|
|
|
|
error(E.getExportRVA(RVA));
|
2015-01-04 05:35:09 +08:00
|
|
|
|
|
|
|
W.printNumber("Ordinal", Ordinal);
|
|
|
|
W.printString("Name", Name);
|
|
|
|
W.printHex("RVA", RVA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-08 03:37:52 +08:00
|
|
|
void COFFDumper::printCOFFDirectives() {
|
|
|
|
for (const SectionRef &Section : Obj->sections()) {
|
|
|
|
StringRef Contents;
|
|
|
|
StringRef Name;
|
|
|
|
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Section.getName(Name));
|
2014-10-08 03:37:52 +08:00
|
|
|
if (Name != ".drectve")
|
|
|
|
continue;
|
|
|
|
|
2015-07-20 11:23:55 +08:00
|
|
|
error(Section.getContents(Contents));
|
2014-10-08 03:37:52 +08:00
|
|
|
|
|
|
|
W.printString("Directive(s)", Contents);
|
|
|
|
}
|
|
|
|
}
|
2014-11-19 08:18:07 +08:00
|
|
|
|
2016-04-06 04:45:04 +08:00
|
|
|
static StringRef getBaseRelocTypeName(uint8_t Type) {
|
2014-11-19 08:18:07 +08:00
|
|
|
switch (Type) {
|
|
|
|
case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";
|
|
|
|
case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";
|
|
|
|
case COFF::IMAGE_REL_BASED_LOW: return "LOW";
|
|
|
|
case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";
|
|
|
|
case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
|
2015-01-17 04:16:09 +08:00
|
|
|
case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)";
|
2014-11-19 08:18:07 +08:00
|
|
|
case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
|
2014-11-20 01:10:39 +08:00
|
|
|
default: return "unknown (" + llvm::utostr(Type) + ")";
|
2014-11-19 08:18:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void COFFDumper::printCOFFBaseReloc() {
|
|
|
|
ListScope D(W, "BaseReloc");
|
|
|
|
for (const BaseRelocRef &I : Obj->base_relocs()) {
|
|
|
|
uint8_t Type;
|
|
|
|
uint32_t RVA;
|
2015-07-20 11:23:55 +08:00
|
|
|
error(I.getRVA(RVA));
|
|
|
|
error(I.getType(Type));
|
2014-11-19 08:18:07 +08:00
|
|
|
DictScope Import(W, "Entry");
|
|
|
|
W.printString("Type", getBaseRelocTypeName(Type));
|
|
|
|
W.printHex("Address", RVA);
|
|
|
|
}
|
|
|
|
}
|
2015-06-27 07:56:53 +08:00
|
|
|
|
|
|
|
void COFFDumper::printStackMap() const {
|
|
|
|
object::SectionRef StackMapSection;
|
|
|
|
for (auto Sec : Obj->sections()) {
|
|
|
|
StringRef Name;
|
|
|
|
Sec.getName(Name);
|
|
|
|
if (Name == ".llvm_stackmaps") {
|
|
|
|
StackMapSection = Sec;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StackMapSection == object::SectionRef())
|
|
|
|
return;
|
|
|
|
|
|
|
|
StringRef StackMapContents;
|
|
|
|
StackMapSection.getContents(StackMapContents);
|
|
|
|
ArrayRef<uint8_t> StackMapContentsArray(
|
|
|
|
reinterpret_cast<const uint8_t*>(StackMapContents.data()),
|
|
|
|
StackMapContents.size());
|
|
|
|
|
|
|
|
if (Obj->isLittleEndian())
|
|
|
|
prettyPrintStackMap(
|
|
|
|
llvm::outs(),
|
|
|
|
StackMapV1Parser<support::little>(StackMapContentsArray));
|
|
|
|
else
|
|
|
|
prettyPrintStackMap(llvm::outs(),
|
|
|
|
StackMapV1Parser<support::big>(StackMapContentsArray));
|
|
|
|
}
|
2016-05-14 08:02:53 +08:00
|
|
|
|
|
|
|
void llvm::dumpCodeViewMergedTypes(
|
|
|
|
ScopedPrinter &Writer, llvm::codeview::MemoryTypeTableBuilder &CVTypes) {
|
|
|
|
// Flatten it first, then run our dumper on it.
|
|
|
|
ListScope S(Writer, "MergedTypeStream");
|
|
|
|
SmallString<0> Buf;
|
[codeview] Improve readability of type record assembly
Adds the method MCStreamer::EmitBinaryData, which is usually an alias
for EmitBytes. In the MCAsmStreamer case, it is overridden to emit hex
dump output like this:
.byte 0x0e, 0x00, 0x08, 0x10
.byte 0x03, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x10, 0x00, 0x00
Also, when verbose asm comments are enabled, this patch prints the dump
output for each comment before its record, like this:
# ArgList (0x1000) {
# TypeLeafKind: LF_ARGLIST (0x1201)
# NumArgs: 0
# Arguments [
# ]
# }
.byte 0x06, 0x00, 0x01, 0x12
.byte 0x00, 0x00, 0x00, 0x00
This should make debugging easier and testing more convenient.
Reviewers: aaboud
Subscribers: majnemer, zturner, amccarth, aaboud, llvm-commits
Differential Revision: http://reviews.llvm.org/D20711
llvm-svn: 271313
2016-06-01 02:45:36 +08:00
|
|
|
CVTypes.ForEachRecord([&](TypeIndex TI, StringRef Record) {
|
|
|
|
Buf.append(Record.begin(), Record.end());
|
2016-05-14 08:02:53 +08:00
|
|
|
});
|
[codeview] Improve readability of type record assembly
Adds the method MCStreamer::EmitBinaryData, which is usually an alias
for EmitBytes. In the MCAsmStreamer case, it is overridden to emit hex
dump output like this:
.byte 0x0e, 0x00, 0x08, 0x10
.byte 0x03, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x10, 0x00, 0x00
Also, when verbose asm comments are enabled, this patch prints the dump
output for each comment before its record, like this:
# ArgList (0x1000) {
# TypeLeafKind: LF_ARGLIST (0x1201)
# NumArgs: 0
# Arguments [
# ]
# }
.byte 0x06, 0x00, 0x01, 0x12
.byte 0x00, 0x00, 0x00, 0x00
This should make debugging easier and testing more convenient.
Reviewers: aaboud
Subscribers: majnemer, zturner, amccarth, aaboud, llvm-commits
Differential Revision: http://reviews.llvm.org/D20711
llvm-svn: 271313
2016-06-01 02:45:36 +08:00
|
|
|
CVTypeDumper CVTD(&Writer, opts::CodeViewSubsectionBytes);
|
2016-06-01 02:15:23 +08:00
|
|
|
if (!CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()})) {
|
2016-05-14 08:02:53 +08:00
|
|
|
Writer.flush();
|
|
|
|
error(object_error::parse_failed);
|
|
|
|
}
|
|
|
|
}
|