mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-01 10:57:21 +00:00
PR21189: Teach llvm-readobj to dump bits of COFF symbol subsections required to debug using VS2012+
Reviewed at http://reviews.llvm.org/D5755 Thanks to Andrey Guskov for his help investigating this! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220526 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
48ba51a8cd
commit
13535f412a
@ -662,9 +662,14 @@ namespace COFF {
|
|||||||
|
|
||||||
enum CodeViewLineTableIdentifiers {
|
enum CodeViewLineTableIdentifiers {
|
||||||
DEBUG_SECTION_MAGIC = 0x4,
|
DEBUG_SECTION_MAGIC = 0x4,
|
||||||
|
DEBUG_SYMBOL_SUBSECTION = 0xF1,
|
||||||
DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
|
DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
|
||||||
DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
|
DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
|
||||||
DEBUG_INDEX_SUBSECTION = 0xF4
|
DEBUG_INDEX_SUBSECTION = 0xF4,
|
||||||
|
|
||||||
|
// Symbol subsections are split into records of different types.
|
||||||
|
DEBUG_SYMBOL_TYPE_PROC_START = 0x1147,
|
||||||
|
DEBUG_SYMBOL_TYPE_PROC_END = 0x114F
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool isReservedSectionNumber(int32_t SectionNumber) {
|
inline bool isReservedSectionNumber(int32_t SectionNumber) {
|
||||||
|
@ -40,6 +40,12 @@ MFUN32: ]
|
|||||||
MFUN32-NEXT: Subsection [
|
MFUN32-NEXT: Subsection [
|
||||||
MFUN32-NEXT: Type: 0xF1
|
MFUN32-NEXT: Type: 0xF1
|
||||||
MFUN32-NEXT: PayloadSize: 0x4B
|
MFUN32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN32: ProcStart {
|
||||||
|
MFUN32-NEXT: FunctionName: x
|
||||||
|
MFUN32-NEXT: Section: _x
|
||||||
|
MFUN32-NEXT: CodeSize: 0xA
|
||||||
|
MFUN32-NEXT: }
|
||||||
|
MFUN32-NEXT: ProcEnd
|
||||||
MFUN32: ]
|
MFUN32: ]
|
||||||
MFUN32-NEXT: Subsection [
|
MFUN32-NEXT: Subsection [
|
||||||
MFUN32-NEXT: Type: 0xF2
|
MFUN32-NEXT: Type: 0xF2
|
||||||
@ -53,6 +59,12 @@ MFUN32: ]
|
|||||||
MFUN32-NEXT: Subsection [
|
MFUN32-NEXT: Subsection [
|
||||||
MFUN32-NEXT: Type: 0xF1
|
MFUN32-NEXT: Type: 0xF1
|
||||||
MFUN32-NEXT: PayloadSize: 0x4B
|
MFUN32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN32: ProcStart {
|
||||||
|
MFUN32-NEXT: FunctionName: y
|
||||||
|
MFUN32-NEXT: Section: _y
|
||||||
|
MFUN32-NEXT: CodeSize: 0xA
|
||||||
|
MFUN32-NEXT: }
|
||||||
|
MFUN32-NEXT: ProcEnd
|
||||||
MFUN32: ]
|
MFUN32: ]
|
||||||
MFUN32-NEXT: Subsection [
|
MFUN32-NEXT: Subsection [
|
||||||
MFUN32-NEXT: Type: 0xF2
|
MFUN32-NEXT: Type: 0xF2
|
||||||
@ -66,6 +78,12 @@ MFUN32: ]
|
|||||||
MFUN32-NEXT: Subsection [
|
MFUN32-NEXT: Subsection [
|
||||||
MFUN32-NEXT: Type: 0xF1
|
MFUN32-NEXT: Type: 0xF1
|
||||||
MFUN32-NEXT: PayloadSize: 0x4B
|
MFUN32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN32: ProcStart {
|
||||||
|
MFUN32-NEXT: FunctionName: f
|
||||||
|
MFUN32-NEXT: Section: _f
|
||||||
|
MFUN32-NEXT: CodeSize: 0x14
|
||||||
|
MFUN32-NEXT: }
|
||||||
|
MFUN32-NEXT: ProcEnd
|
||||||
MFUN32: ]
|
MFUN32: ]
|
||||||
MFUN32-NEXT: Subsection [
|
MFUN32-NEXT: Subsection [
|
||||||
MFUN32-NEXT: Type: 0xF2
|
MFUN32-NEXT: Type: 0xF2
|
||||||
@ -127,6 +145,12 @@ MFUN64: ]
|
|||||||
MFUN64-NEXT: Subsection [
|
MFUN64-NEXT: Subsection [
|
||||||
MFUN64-NEXT: Type: 0xF1
|
MFUN64-NEXT: Type: 0xF1
|
||||||
MFUN64-NEXT: PayloadSize: 0x4B
|
MFUN64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN64: ProcStart {
|
||||||
|
MFUN64-NEXT: FunctionName: x
|
||||||
|
MFUN64-NEXT: Section: x
|
||||||
|
MFUN64-NEXT: CodeSize: 0xE
|
||||||
|
MFUN64-NEXT: }
|
||||||
|
MFUN64-NEXT: ProcEnd
|
||||||
MFUN64: ]
|
MFUN64: ]
|
||||||
MFUN64-NEXT: Subsection [
|
MFUN64-NEXT: Subsection [
|
||||||
MFUN64-NEXT: Type: 0xF2
|
MFUN64-NEXT: Type: 0xF2
|
||||||
@ -136,6 +160,12 @@ MFUN64-NEXT: ]
|
|||||||
MFUN64-NEXT: Subsection [
|
MFUN64-NEXT: Subsection [
|
||||||
MFUN64-NEXT: Type: 0xF1
|
MFUN64-NEXT: Type: 0xF1
|
||||||
MFUN64-NEXT: PayloadSize: 0x4B
|
MFUN64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN64: ProcStart {
|
||||||
|
MFUN64-NEXT: FunctionName: y
|
||||||
|
MFUN64-NEXT: Section: y
|
||||||
|
MFUN64-NEXT: CodeSize: 0xE
|
||||||
|
MFUN64-NEXT: }
|
||||||
|
MFUN64-NEXT: ProcEnd
|
||||||
MFUN64: ]
|
MFUN64: ]
|
||||||
MFUN64-NEXT: Subsection [
|
MFUN64-NEXT: Subsection [
|
||||||
MFUN64-NEXT: Type: 0xF2
|
MFUN64-NEXT: Type: 0xF2
|
||||||
@ -145,6 +175,12 @@ MFUN64-NEXT: ]
|
|||||||
MFUN64-NEXT: Subsection [
|
MFUN64-NEXT: Subsection [
|
||||||
MFUN64-NEXT: Type: 0xF1
|
MFUN64-NEXT: Type: 0xF1
|
||||||
MFUN64-NEXT: PayloadSize: 0x4B
|
MFUN64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFUN64: ProcStart {
|
||||||
|
MFUN64-NEXT: FunctionName: f
|
||||||
|
MFUN64-NEXT: Section: f
|
||||||
|
MFUN64-NEXT: CodeSize: 0x18
|
||||||
|
MFUN64-NEXT: }
|
||||||
|
MFUN64-NEXT: ProcEnd
|
||||||
MFUN64: ]
|
MFUN64: ]
|
||||||
MFUN64-NEXT: Subsection [
|
MFUN64-NEXT: Subsection [
|
||||||
MFUN64-NEXT: Type: 0xF2
|
MFUN64-NEXT: Type: 0xF2
|
||||||
@ -234,6 +270,12 @@ MFILE32: ]
|
|||||||
MFILE32-NEXT: Subsection [
|
MFILE32-NEXT: Subsection [
|
||||||
MFILE32-NEXT: Type: 0xF1
|
MFILE32-NEXT: Type: 0xF1
|
||||||
MFILE32-NEXT: PayloadSize: 0x4B
|
MFILE32-NEXT: PayloadSize: 0x4B
|
||||||
|
MFILE32: ProcStart {
|
||||||
|
MFILE32-NEXT: FunctionName: f
|
||||||
|
MFILE32-NEXT: Section: _f
|
||||||
|
MFILE32-NEXT: CodeSize: 0x14
|
||||||
|
MFILE32-NEXT: }
|
||||||
|
MFILE32-NEXT: ProcEnd
|
||||||
MFILE32: ]
|
MFILE32: ]
|
||||||
MFILE32-NEXT: Subsection [
|
MFILE32-NEXT: Subsection [
|
||||||
MFILE32-NEXT: Type: 0xF2
|
MFILE32-NEXT: Type: 0xF2
|
||||||
@ -284,6 +326,12 @@ MFILE64: ]
|
|||||||
MFILE64-NEXT: Subsection [
|
MFILE64-NEXT: Subsection [
|
||||||
MFILE64-NEXT: Type: 0xF1
|
MFILE64-NEXT: Type: 0xF1
|
||||||
MFILE64-NEXT: PayloadSize: 0x4B
|
MFILE64-NEXT: PayloadSize: 0x4B
|
||||||
|
MFILE64: ProcStart {
|
||||||
|
MFILE64-NEXT: FunctionName: f
|
||||||
|
MFILE64-NEXT: Section: f
|
||||||
|
MFILE64-NEXT: CodeSize: 0x18
|
||||||
|
MFILE64-NEXT: }
|
||||||
|
MFILE64-NEXT: ProcEnd
|
||||||
MFILE64: ]
|
MFILE64: ]
|
||||||
MFILE64-NEXT: Subsection [
|
MFILE64-NEXT: Subsection [
|
||||||
MFILE64-NEXT: Type: 0xF2
|
MFILE64-NEXT: Type: 0xF2
|
||||||
@ -344,6 +392,11 @@ RUN: | FileCheck %s -check-prefix MCOMDAT
|
|||||||
RUN: llvm-readobj -s -codeview-linetables %p/Inputs/comdat-function-linetables.obj.coff-2013-i386 \
|
RUN: llvm-readobj -s -codeview-linetables %p/Inputs/comdat-function-linetables.obj.coff-2013-i386 \
|
||||||
RUN: | FileCheck %s -check-prefix MCOMDAT
|
RUN: | FileCheck %s -check-prefix MCOMDAT
|
||||||
|
|
||||||
|
MCOMDAT: ProcStart {
|
||||||
|
MCOMDAT-NEXT: FunctionName: f
|
||||||
|
MCOMDAT-NEXT: Section: ?f@@YAHXZ
|
||||||
|
MCOMDAT-NEXT: CodeSize: 0x7
|
||||||
|
MCOMDAT-NEXT: }
|
||||||
MCOMDAT: FunctionLineTable [
|
MCOMDAT: FunctionLineTable [
|
||||||
MCOMDAT-NEXT: FunctionName: ?f@@YAHXZ
|
MCOMDAT-NEXT: FunctionName: ?f@@YAHXZ
|
||||||
MCOMDAT-NEXT: CodeSize: 0x7
|
MCOMDAT-NEXT: CodeSize: 0x7
|
||||||
@ -354,6 +407,11 @@ MCOMDAT-NEXT: +0x3: 3
|
|||||||
MCOMDAT-NEXT: +0x5: 4
|
MCOMDAT-NEXT: +0x5: 4
|
||||||
MCOMDAT-NEXT: ]
|
MCOMDAT-NEXT: ]
|
||||||
MCOMDAT-NEXT: ]
|
MCOMDAT-NEXT: ]
|
||||||
|
MCOMDAT: ProcStart {
|
||||||
|
MCOMDAT-NEXT: FunctionName: g
|
||||||
|
MCOMDAT-NEXT: Section: ?g@@YAHXZ
|
||||||
|
MCOMDAT-NEXT: CodeSize: 0x7
|
||||||
|
MCOMDAT-NEXT: }
|
||||||
MCOMDAT: FunctionLineTable [
|
MCOMDAT: FunctionLineTable [
|
||||||
MCOMDAT-NEXT: FunctionName: ?g@@YAHXZ
|
MCOMDAT-NEXT: FunctionName: ?g@@YAHXZ
|
||||||
MCOMDAT-NEXT: CodeSize: 0x7
|
MCOMDAT-NEXT: CodeSize: 0x7
|
||||||
|
@ -69,6 +69,10 @@ private:
|
|||||||
|
|
||||||
void printCodeViewLineTables(const SectionRef &Section);
|
void printCodeViewLineTables(const SectionRef &Section);
|
||||||
|
|
||||||
|
void printCodeViewSymbolsSubsection(StringRef Subsection,
|
||||||
|
const SectionRef &Section,
|
||||||
|
uint32_t Offset);
|
||||||
|
|
||||||
void cacheRelocations();
|
void cacheRelocations();
|
||||||
|
|
||||||
std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
|
std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
|
||||||
@ -444,6 +448,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
|
|||||||
|
|
||||||
ListScope D(W, "CodeViewLineTables");
|
ListScope D(W, "CodeViewLineTables");
|
||||||
{
|
{
|
||||||
|
// FIXME: Add more offset correctness checks.
|
||||||
DataExtractor DE(Data, true, 4);
|
DataExtractor DE(Data, true, 4);
|
||||||
uint32_t Offset = 0,
|
uint32_t Offset = 0,
|
||||||
Magic = DE.getU32(&Offset);
|
Magic = DE.getU32(&Offset);
|
||||||
@ -473,6 +478,9 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
|
|||||||
W.printBinaryBlock("Contents", Contents);
|
W.printBinaryBlock("Contents", Contents);
|
||||||
|
|
||||||
switch (SubSectionType) {
|
switch (SubSectionType) {
|
||||||
|
case COFF::DEBUG_SYMBOL_SUBSECTION:
|
||||||
|
printCodeViewSymbolsSubsection(Contents, Section, Offset);
|
||||||
|
break;
|
||||||
case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
|
case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
|
||||||
// Holds a PC to file:line table. Some data to parse this subsection is
|
// 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
|
// stored in the other subsections, so just check sanity and store the
|
||||||
@ -592,6 +600,80 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
|
||||||
|
const SectionRef &Section,
|
||||||
|
uint32_t OffsetInSection) {
|
||||||
|
if (Subsection.size() == 0) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DataExtractor DE(Subsection, true, 4);
|
||||||
|
uint32_t Offset = 0;
|
||||||
|
|
||||||
|
// Function-level subsections have "procedure start" and "procedure end"
|
||||||
|
// commands that should come in pairs and surround relevant info.
|
||||||
|
bool InFunctionScope = false;
|
||||||
|
while (DE.isValidOffset(Offset)) {
|
||||||
|
// Read subsection segments one by one.
|
||||||
|
uint16_t Size = DE.getU16(&Offset);
|
||||||
|
// The section size includes the size of the type identifier.
|
||||||
|
if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Size -= 2;
|
||||||
|
uint16_t Type = DE.getU16(&Offset);
|
||||||
|
switch (Type) {
|
||||||
|
case COFF::DEBUG_SYMBOL_TYPE_PROC_START: {
|
||||||
|
DictScope S(W, "ProcStart");
|
||||||
|
if (InFunctionScope || Size < 36) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InFunctionScope = true;
|
||||||
|
|
||||||
|
// We're currently interested in a limited subset of fields in this
|
||||||
|
// segment, just ignore the rest of the fields for now.
|
||||||
|
uint8_t Unused[12];
|
||||||
|
DE.getU8(&Offset, Unused, 12);
|
||||||
|
uint32_t CodeSize = DE.getU32(&Offset);
|
||||||
|
DE.getU8(&Offset, Unused, 12);
|
||||||
|
StringRef SectionName;
|
||||||
|
if (error(resolveSymbolName(Obj->getCOFFSection(Section),
|
||||||
|
OffsetInSection + Offset, SectionName)))
|
||||||
|
return;
|
||||||
|
Offset += 4;
|
||||||
|
DE.getU8(&Offset, Unused, 3);
|
||||||
|
StringRef FunctionName = DE.getCStr(&Offset);
|
||||||
|
if (!DE.isValidOffset(Offset)) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
W.printString("FunctionName", FunctionName);
|
||||||
|
W.printString("Section", SectionName);
|
||||||
|
W.printHex("CodeSize", CodeSize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case COFF::DEBUG_SYMBOL_TYPE_PROC_END: {
|
||||||
|
W.startLine() << "ProcEnd\n";
|
||||||
|
if (!InFunctionScope || Size > 0) {
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InFunctionScope = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Offset += Size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InFunctionScope)
|
||||||
|
error(object_error::parse_failed);
|
||||||
|
}
|
||||||
|
|
||||||
void COFFDumper::printSections() {
|
void COFFDumper::printSections() {
|
||||||
ListScope SectionsD(W, "Sections");
|
ListScope SectionsD(W, "Sections");
|
||||||
int SectionNumber = 0;
|
int SectionNumber = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user