forked from OSchip/llvm-project
Teach the llvm-readobj COFF dumper to dump debug line tables from object files
Reviewed at http://llvm-reviews.chandlerc.com/D2425 llvm-svn: 197674
This commit is contained in:
parent
d4c5c674f0
commit
48703be503
|
@ -611,6 +611,13 @@ namespace COFF {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CodeViewLineTableIdentifiers {
|
||||||
|
DEBUG_SECTION_MAGIC = 0x4,
|
||||||
|
DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
|
||||||
|
DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
|
||||||
|
DEBUG_INDEX_SUBSECTION = 0xF4
|
||||||
|
};
|
||||||
|
|
||||||
} // End namespace COFF.
|
} // End namespace COFF.
|
||||||
} // End namespace llvm.
|
} // End namespace llvm.
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,282 @@
|
||||||
|
RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifunction-linetables.obj.coff-2012-i368 \
|
||||||
|
RUN: | FileCheck %s -check-prefix MFUN32
|
||||||
|
RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifunction-linetables.obj.coff-2012-x86_64 \
|
||||||
|
RUN: | FileCheck %s -check-prefix MFUN64
|
||||||
|
RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifile-linetables.obj.coff-2012-i368 \
|
||||||
|
RUN: | FileCheck %s -check-prefix MFILE32
|
||||||
|
RUN: llvm-readobj -s -codeview-linetables %p/Inputs/multifile-linetables.obj.coff-2012-x86_64 \
|
||||||
|
RUN: | FileCheck %s -check-prefix MFILE64
|
||||||
|
|
||||||
|
MFUN32: CodeViewLineTables [
|
||||||
|
MFUN32-NEXT: Magic: 0x4
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF1
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x52
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF5
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x24
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF1
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF2
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x30
|
||||||
|
MFUN32: FunctionName: _x
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF5
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x24
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF1
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF2
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x30
|
||||||
|
MFUN32: FunctionName: _y
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF5
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x24
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF1
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF2
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x40
|
||||||
|
MFUN32: FunctionName: _f
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF4
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x18
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF3
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x46
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: Subsection [
|
||||||
|
MFUN32-NEXT: Type: 0xF1
|
||||||
|
MFUN32-NEXT: PayloadSize: 0x8
|
||||||
|
MFUN32: ]
|
||||||
|
MFUN32-NEXT: FunctionLineTable [
|
||||||
|
MFUN32-NEXT: FunctionName: _x
|
||||||
|
MFUN32-NEXT: CodeSize: 0xA
|
||||||
|
MFUN32-NEXT: FilenameSegment [
|
||||||
|
MFUN32-NEXT: Filename: d:\source.c
|
||||||
|
MFUN32-NEXT: +0x0: 3
|
||||||
|
MFUN32-NEXT: +0x3: 4
|
||||||
|
MFUN32-NEXT: +0x8: 5
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: FunctionLineTable [
|
||||||
|
MFUN32-NEXT: FunctionName: _y
|
||||||
|
MFUN32-NEXT: CodeSize: 0xA
|
||||||
|
MFUN32-NEXT: FilenameSegment [
|
||||||
|
MFUN32-NEXT: Filename: d:\source.c
|
||||||
|
MFUN32-NEXT: +0x0: 7
|
||||||
|
MFUN32-NEXT: +0x3: 8
|
||||||
|
MFUN32-NEXT: +0x8: 9
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: FunctionLineTable [
|
||||||
|
MFUN32-NEXT: FunctionName: _f
|
||||||
|
MFUN32-NEXT: CodeSize: 0x14
|
||||||
|
MFUN32-NEXT: FilenameSegment [
|
||||||
|
MFUN32-NEXT: Filename: d:\source.c
|
||||||
|
MFUN32-NEXT: +0x0: 11
|
||||||
|
MFUN32-NEXT: +0x3: 12
|
||||||
|
MFUN32-NEXT: +0x8: 13
|
||||||
|
MFUN32-NEXT: +0xD: 14
|
||||||
|
MFUN32-NEXT: +0x12: 15
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
MFUN32-NEXT: ]
|
||||||
|
|
||||||
|
MFUN64: CodeViewLineTables [
|
||||||
|
MFUN64-NEXT: Magic: 0x4
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF1
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x52
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF1
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF2
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x30
|
||||||
|
MFUN64: FunctionName: x
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF1
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF2
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x30
|
||||||
|
MFUN64: FunctionName: y
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF1
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF2
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x40
|
||||||
|
MFUN64: FunctionName: f
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF4
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x18
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF3
|
||||||
|
MFUN64-NEXT: PayloadSize: 0xD
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: Subsection [
|
||||||
|
MFUN64-NEXT: Type: 0xF1
|
||||||
|
MFUN64-NEXT: PayloadSize: 0x8
|
||||||
|
MFUN64: ]
|
||||||
|
MFUN64-NEXT: FunctionLineTable [
|
||||||
|
MFUN64-NEXT: FunctionName: x
|
||||||
|
MFUN64-NEXT: CodeSize: 0xE
|
||||||
|
MFUN64-NEXT: FilenameSegment [
|
||||||
|
MFUN64-NEXT: Filename: d:\source.c
|
||||||
|
MFUN64-NEXT: +0x0: 3
|
||||||
|
MFUN64-NEXT: +0x4: 4
|
||||||
|
MFUN64-NEXT: +0x9: 5
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: FunctionLineTable [
|
||||||
|
MFUN64-NEXT: FunctionName: y
|
||||||
|
MFUN64-NEXT: CodeSize: 0xE
|
||||||
|
MFUN64-NEXT: FilenameSegment [
|
||||||
|
MFUN64-NEXT: Filename: d:\source.c
|
||||||
|
MFUN64-NEXT: +0x0: 7
|
||||||
|
MFUN64-NEXT: +0x4: 8
|
||||||
|
MFUN64-NEXT: +0x9: 9
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: FunctionLineTable [
|
||||||
|
MFUN64-NEXT: FunctionName: f
|
||||||
|
MFUN64-NEXT: CodeSize: 0x18
|
||||||
|
MFUN64-NEXT: FilenameSegment [
|
||||||
|
MFUN64-NEXT: Filename: d:\source.c
|
||||||
|
MFUN64-NEXT: +0x0: 11
|
||||||
|
MFUN64-NEXT: +0x4: 12
|
||||||
|
MFUN64-NEXT: +0x9: 13
|
||||||
|
MFUN64-NEXT: +0xE: 14
|
||||||
|
MFUN64-NEXT: +0x13: 15
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
MFUN64-NEXT: ]
|
||||||
|
|
||||||
|
MFILE32: CodeViewLineTables [
|
||||||
|
MFILE32-NEXT: Magic: 0x4
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF1
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x51
|
||||||
|
MFILE32: ]
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF5
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x24
|
||||||
|
MFILE32: ]
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF1
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFILE32: ]
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF2
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x64
|
||||||
|
MFILE32: FunctionName: _f
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF4
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x28
|
||||||
|
MFILE32: ]
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF3
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x57
|
||||||
|
MFILE32: ]
|
||||||
|
MFILE32-NEXT: Subsection [
|
||||||
|
MFILE32-NEXT: Type: 0xF1
|
||||||
|
MFILE32-NEXT: PayloadSize: 0x8
|
||||||
|
MFILE32: ]
|
||||||
|
MFILE32-NEXT: FunctionLineTable [
|
||||||
|
MFILE32-NEXT: FunctionName: _f
|
||||||
|
MFILE32-NEXT: CodeSize: 0x14
|
||||||
|
MFILE32-NEXT: FilenameSegment [
|
||||||
|
MFILE32-NEXT: Filename: d:\input.c
|
||||||
|
MFILE32-NEXT: +0x0: 3
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
MFILE32-NEXT: FilenameSegment [
|
||||||
|
MFILE32-NEXT: Filename: d:\one.c
|
||||||
|
MFILE32-NEXT: +0x3: 1
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
MFILE32-NEXT: FilenameSegment [
|
||||||
|
MFILE32-NEXT: Filename: d:\two.c
|
||||||
|
MFILE32-NEXT: +0x8: 2
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
MFILE32-NEXT: FilenameSegment [
|
||||||
|
MFILE32-NEXT: Filename: d:\one.c
|
||||||
|
MFILE32-NEXT: +0xD: 7
|
||||||
|
MFILE32-NEXT: +0x12: 8
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
MFILE32-NEXT: ]
|
||||||
|
|
||||||
|
MFILE64: CodeViewLineTables [
|
||||||
|
MFILE64-NEXT: Magic: 0x4
|
||||||
|
MFILE64-NEXT: Subsection [
|
||||||
|
MFILE64-NEXT: Type: 0xF1
|
||||||
|
MFILE64-NEXT: PayloadSize: 0x51
|
||||||
|
MFILE64: ]
|
||||||
|
MFILE64-NEXT: Subsection [
|
||||||
|
MFILE64-NEXT: Type: 0xF1
|
||||||
|
MFILE64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFILE64: ]
|
||||||
|
MFILE64-NEXT: Subsection [
|
||||||
|
MFILE64-NEXT: Type: 0xF2
|
||||||
|
MFILE64-NEXT: PayloadSize: 0x64
|
||||||
|
MFILE64: FunctionName: f
|
||||||
|
MFILE64-NEXT: ]
|
||||||
|
MFILE64-NEXT: Subsection [
|
||||||
|
MFILE64-NEXT: Type: 0xF4
|
||||||
|
MFILE64-NEXT: PayloadSize: 0x28
|
||||||
|
MFILE64: ]
|
||||||
|
MFILE64-NEXT: Subsection [
|
||||||
|
MFILE64-NEXT: Type: 0xF3
|
||||||
|
MFILE64-NEXT: PayloadSize: 0x1E
|
||||||
|
MFILE64: ]
|
||||||
|
MFILE64-NEXT: Subsection [
|
||||||
|
MFILE64-NEXT: Type: 0xF1
|
||||||
|
MFILE64-NEXT: PayloadSize: 0x8
|
||||||
|
MFILE64: ]
|
||||||
|
MFILE64-NEXT: FunctionLineTable [
|
||||||
|
MFILE64-NEXT: FunctionName: f
|
||||||
|
MFILE64-NEXT: CodeSize: 0x18
|
||||||
|
MFILE64-NEXT: FilenameSegment [
|
||||||
|
MFILE64-NEXT: Filename: d:\input.c
|
||||||
|
MFILE64-NEXT: +0x0: 3
|
||||||
|
MFILE64-NEXT: ]
|
||||||
|
MFILE64-NEXT: FilenameSegment [
|
||||||
|
MFILE64-NEXT: Filename: d:\one.c
|
||||||
|
MFILE64-NEXT: +0x4: 1
|
||||||
|
MFILE64-NEXT: ]
|
||||||
|
MFILE64-NEXT: FilenameSegment [
|
||||||
|
MFILE64-NEXT: Filename: d:\two.c
|
||||||
|
MFILE64-NEXT: +0x9: 2
|
||||||
|
MFILE64-NEXT: ]
|
||||||
|
MFILE64-NEXT: FilenameSegment [
|
||||||
|
MFILE64-NEXT: Filename: d:\one.c
|
||||||
|
MFILE64-NEXT: +0xE: 7
|
||||||
|
MFILE64-NEXT: +0x13: 8
|
||||||
|
MFILE64-NEXT: ]
|
||||||
|
MFILE64-NEXT: ]
|
||||||
|
MFILE64-NEXT: ]
|
|
@ -24,6 +24,8 @@
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
|
#include "llvm/Support/COFF.h"
|
||||||
|
#include "llvm/Support/DataExtractor.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/Win64EH.h"
|
#include "llvm/Support/Win64EH.h"
|
||||||
|
@ -76,6 +78,8 @@ private:
|
||||||
|
|
||||||
void printUnwindCode(const Win64EH::UnwindInfo& UI, ArrayRef<UnwindCode> UCs);
|
void printUnwindCode(const Win64EH::UnwindInfo& UI, ArrayRef<UnwindCode> UCs);
|
||||||
|
|
||||||
|
void printCodeViewLineTables(section_iterator SecI);
|
||||||
|
|
||||||
void cacheRelocations();
|
void cacheRelocations();
|
||||||
|
|
||||||
error_code getSectionContents(
|
error_code getSectionContents(
|
||||||
|
@ -648,6 +652,164 @@ void COFFDumper::printFileHeaders() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void COFFDumper::printCodeViewLineTables(section_iterator SecI) {
|
||||||
|
StringRef Data;
|
||||||
|
if (error(SecI->getContents(Data))) return;
|
||||||
|
|
||||||
|
SmallVector<StringRef, 10> FunctionNames;
|
||||||
|
StringMap<StringRef> FunctionLineTables;
|
||||||
|
StringRef FileIndexToStringOffsetTable;
|
||||||
|
StringRef StringTable;
|
||||||
|
|
||||||
|
ListScope D(W, "CodeViewLineTables");
|
||||||
|
{
|
||||||
|
DataExtractor DE(Data, true, 4);
|
||||||
|
uint32_t Offset = 0,
|
||||||
|
Magic = DE.getU32(&Offset);
|
||||||
|
W.printHex("Magic", Magic);
|
||||||
|
if (Magic != COFF::DEBUG_SECTION_MAGIC) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Finished = false;
|
||||||
|
while (DE.isValidOffset(Offset) && !Finished) {
|
||||||
|
// The section consists of a number of subsection in the following format:
|
||||||
|
// |Type|PayloadSize|Payload...|
|
||||||
|
uint32_t SubSectionType = DE.getU32(&Offset),
|
||||||
|
PayloadSize = DE.getU32(&Offset);
|
||||||
|
ListScope S(W, "Subsection");
|
||||||
|
W.printHex("Type", SubSectionType);
|
||||||
|
W.printHex("PayloadSize", PayloadSize);
|
||||||
|
if (PayloadSize > Data.size() - Offset) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the raw contents to simplify debugging if anything goes wrong
|
||||||
|
// afterwards.
|
||||||
|
StringRef Contents = Data.substr(Offset, PayloadSize);
|
||||||
|
W.printBinaryBlock("Contents", Contents);
|
||||||
|
|
||||||
|
switch (SubSectionType) {
|
||||||
|
case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
|
||||||
|
// 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 (PayloadSize < 12) {
|
||||||
|
// There should be at least three words to store two function
|
||||||
|
// relocations and size of the code.
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef FunctionName;
|
||||||
|
if (error(resolveSymbolName(RelocMap[Obj->getCOFFSection(SecI)], Offset,
|
||||||
|
FunctionName)))
|
||||||
|
return;
|
||||||
|
W.printString("FunctionName", FunctionName);
|
||||||
|
if (FunctionLineTables.count(FunctionName) != 0) {
|
||||||
|
// Saw debug info for this function already?
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionLineTables[FunctionName] = Contents;
|
||||||
|
FunctionNames.push_back(FunctionName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case COFF::DEBUG_STRING_TABLE_SUBSECTION:
|
||||||
|
if (PayloadSize == 0 || StringTable.data() != 0 ||
|
||||||
|
Contents.back() != '\0') {
|
||||||
|
// Empty or duplicate or non-null-terminated subsection.
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StringTable = Contents;
|
||||||
|
break;
|
||||||
|
case COFF::DEBUG_INDEX_SUBSECTION:
|
||||||
|
// Holds the translation table from file indices
|
||||||
|
// to offsets in the string table.
|
||||||
|
|
||||||
|
if (PayloadSize == 0 || FileIndexToStringOffsetTable.data() != 0) {
|
||||||
|
// Empty or duplicate subsection.
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FileIndexToStringOffsetTable = Contents;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Offset += PayloadSize;
|
||||||
|
|
||||||
|
// Align the reading pointer by 4.
|
||||||
|
Offset += (-Offset) % 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
W.printString("FunctionName", Name);
|
||||||
|
|
||||||
|
DataExtractor DE(FunctionLineTables[Name], true, 4);
|
||||||
|
uint32_t Offset = 8; // Skip relocations.
|
||||||
|
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),
|
||||||
|
SegmentLength = DE.getU32(&Offset),
|
||||||
|
FullSegmentSize = DE.getU32(&Offset);
|
||||||
|
if (FullSegmentSize != 12 + 8 * SegmentLength) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t FilenameOffset;
|
||||||
|
{
|
||||||
|
DataExtractor SDE(FileIndexToStringOffsetTable, true, 4);
|
||||||
|
uint32_t OffsetInSDE = OffsetInIndex;
|
||||||
|
if (!SDE.isValidOffset(OffsetInSDE)) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FilenameOffset = SDE.getU32(&OffsetInSDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() ||
|
||||||
|
StringTable.data()[FilenameOffset - 1] != '\0') {
|
||||||
|
// Each string in an F3 subsection should be preceded by a null
|
||||||
|
// character.
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef Filename(StringTable.data() + FilenameOffset);
|
||||||
|
ListScope S(W, "FilenameSegment");
|
||||||
|
W.printString("Filename", Filename);
|
||||||
|
for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
|
||||||
|
++J) {
|
||||||
|
// Then go the (PC, LineNumber) pairs. The line number is stored in the
|
||||||
|
// least significant 31 bits of the respective word in the table.
|
||||||
|
uint32_t PC = DE.getU32(&Offset),
|
||||||
|
LineNumber = DE.getU32(&Offset) & 0x7fffffff;
|
||||||
|
if (PC >= FunctionSize) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char Buffer[32];
|
||||||
|
format("+0x%X", PC).snprint(Buffer, 32);
|
||||||
|
W.printNumber(Buffer, LineNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void COFFDumper::printSections() {
|
void COFFDumper::printSections() {
|
||||||
error_code EC;
|
error_code EC;
|
||||||
|
|
||||||
|
@ -707,6 +869,9 @@ void COFFDumper::printSections() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Name == ".debug$S" && opts::CodeViewLineTables)
|
||||||
|
printCodeViewLineTables(SecI);
|
||||||
|
|
||||||
if (opts::SectionData) {
|
if (opts::SectionData) {
|
||||||
StringRef Data;
|
StringRef Data;
|
||||||
if (error(SecI->getContents(Data))) break;
|
if (error(SecI->getContents(Data))) break;
|
||||||
|
|
|
@ -128,6 +128,10 @@ namespace opts {
|
||||||
// -expand-relocs
|
// -expand-relocs
|
||||||
cl::opt<bool> ExpandRelocs("expand-relocs",
|
cl::opt<bool> ExpandRelocs("expand-relocs",
|
||||||
cl::desc("Expand each shown relocation to multiple lines"));
|
cl::desc("Expand each shown relocation to multiple lines"));
|
||||||
|
|
||||||
|
// -codeview-linetables
|
||||||
|
cl::opt<bool> CodeViewLineTables("codeview-linetables",
|
||||||
|
cl::desc("Display CodeView line table information"));
|
||||||
} // namespace opts
|
} // namespace opts
|
||||||
|
|
||||||
static int ReturnValue = EXIT_SUCCESS;
|
static int ReturnValue = EXIT_SUCCESS;
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace opts {
|
||||||
extern llvm::cl::opt<bool> DynamicSymbols;
|
extern llvm::cl::opt<bool> DynamicSymbols;
|
||||||
extern llvm::cl::opt<bool> UnwindInfo;
|
extern llvm::cl::opt<bool> UnwindInfo;
|
||||||
extern llvm::cl::opt<bool> ExpandRelocs;
|
extern llvm::cl::opt<bool> ExpandRelocs;
|
||||||
|
extern llvm::cl::opt<bool> CodeViewLineTables;
|
||||||
} // namespace opts
|
} // namespace opts
|
||||||
|
|
||||||
#define LLVM_READOBJ_ENUM_ENT(ns, enum) \
|
#define LLVM_READOBJ_ENUM_ENT(ns, enum) \
|
||||||
|
|
Loading…
Reference in New Issue