1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[codeview] Translate file table offsets to filenames and print them

llvm-svn: 257846
This commit is contained in:
Reid Kleckner 2016-01-15 00:11:21 +00:00
parent cdc98ebda4
commit 6237bdd778
2 changed files with 68 additions and 53 deletions

View File

@ -38,7 +38,7 @@ RUN: llvm-readobj -s -codeview -section-symbols %p/Inputs/codeview-inlining.obj.
; CHECK-NEXT: SubSectionSize: 0x3C
; CHECK-NEXT: InlineeSourceLine {
; CHECK-NEXT: Inlinee: bar (0x1002)
; CHECK-NEXT: FileID: 0x30
; CHECK-NEXT: FileID: d:\src\llvm\build\t.cpp (0x30)
; CHECK-NEXT: SourceLineNum: 2
; CHECK-NEXT: ExtraFileCount: 0
; CHECK-NEXT: ExtraFiles [
@ -46,7 +46,7 @@ RUN: llvm-readobj -s -codeview -section-symbols %p/Inputs/codeview-inlining.obj.
; CHECK-NEXT: }
; CHECK-NEXT: InlineeSourceLine {
; CHECK-NEXT: Inlinee: baz (0x1003)
; CHECK-NEXT: FileID: 0x30
; CHECK-NEXT: FileID: d:\src\llvm\build\t.cpp (0x30)
; CHECK-NEXT: SourceLineNum: 5
; CHECK-NEXT: ExtraFileCount: 0
; CHECK-NEXT: ExtraFiles [
@ -55,11 +55,11 @@ RUN: llvm-readobj -s -codeview -section-symbols %p/Inputs/codeview-inlining.obj.
; The 'foo' inline site has extra files due to includes.
; CHECK-NEXT: InlineeSourceLine {
; CHECK-NEXT: Inlinee: foo (0x1004)
; CHECK-NEXT: FileID: 0x0
; CHECK-NEXT: FileID: d:\src\llvm\build\a.h (0x0)
; CHECK-NEXT: SourceLineNum: 1
; CHECK-NEXT: ExtraFileCount: 2
; CHECK-NEXT: ExtraFiles [
; CHECK-NEXT: FileID: 0x18
; CHECK-NEXT: FileID: 0x30
; CHECK-NEXT: FileID: d:\src\llvm\build\b.h (0x18)
; CHECK-NEXT: FileID: d:\src\llvm\build\t.cpp (0x30)
; CHECK-NEXT: ]
; CHECK-NEXT: }

View File

@ -86,6 +86,8 @@ private:
void printCodeViewTypeSection(StringRef SectionName, const SectionRef &Section);
void printCodeViewFieldList(StringRef FieldData);
StringRef getTypeName(TypeIndex Ty);
StringRef getFileNameForFileOffset(uint32_t FileOffset);
void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
void printTypeIndex(StringRef FieldName, TypeIndex TI);
void printCodeViewSymbolsSubsection(StringRef Subsection,
@ -103,6 +105,9 @@ private:
void printBinaryBlockWithRelocs(StringRef Label, const SectionRef &Sec,
StringRef SectionContents, StringRef Block);
/// Given a .debug$S section, find the string table and file checksum table.
void initializeFileAndStringTables(StringRef Data);
void cacheRelocations();
std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
@ -122,7 +127,7 @@ private:
const llvm::object::COFFObjectFile *Obj;
bool RelocCached = false;
RelocMapTy RelocMap;
StringRef CVFileIndexToStringOffsetTable;
StringRef CVFileChecksumTable;
StringRef CVStringTable;
/// All user defined type records in .debug$T live in here. Type indices
@ -942,6 +947,30 @@ static std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {
return std::error_code();
}
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;
error(consumeUInt32(Data, SubType));
error(consumeUInt32(Data, SubSectionSize));
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;
}
Data = Data.drop_front(alignTo(SubSectionSize, 4));
}
}
void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
const SectionRef &Section) {
StringRef SectionContents;
@ -962,6 +991,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
if (Magic != COFF::DEBUG_SECTION_MAGIC)
return error(object_error::parse_failed);
initializeFileAndStringTables(Data);
while (!Data.empty()) {
// The section consists of a number of subsection in the following format:
// |SubSectionType|SubSectionSize|Contents...|
@ -1025,27 +1056,6 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
FunctionNames.push_back(LinkageName);
break;
}
case ModuleSubstreamKind::StringTable:
if (SubSectionSize == 0 || CVStringTable.data() != nullptr ||
Contents.back() != '\0') {
// Empty or duplicate or non-null-terminated subsection.
error(object_error::parse_failed);
return;
}
CVStringTable = Contents;
break;
case ModuleSubstreamKind::FileChecksums:
// Holds the translation table from file indices
// to offsets in the string table.
if (SubSectionSize == 0 ||
CVFileIndexToStringOffsetTable.data() != nullptr) {
// Empty or duplicate subsection.
error(object_error::parse_failed);
return;
}
CVFileIndexToStringOffsetTable = Contents;
break;
case ModuleSubstreamKind::FrameData: {
const size_t RelocationSize = 4;
if (SubSectionSize != sizeof(FrameData) + RelocationSize) {
@ -1106,28 +1116,8 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
return;
}
uint32_t FilenameOffset;
{
DataExtractor SDE(CVFileIndexToStringOffsetTable, 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 >= CVStringTable.size() ||
CVStringTable.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(CVStringTable.data() + FilenameOffset);
ListScope S(W, "FilenameSegment");
W.printString("Filename", Filename);
printFileNameForOffset("Filename", OffsetInIndex);
for (unsigned LineIdx = 0;
LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
// Then go the (PC, LineNumber) pairs. The line number is stored in the
@ -1453,10 +1443,10 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
break;
case ChangeCodeOffsetAndLineOffset: {
uint32_t Annotation = GetCompressedAnnotation();
uint32_t SourceDelta = Annotation >> 4;
int32_t LineOffset = DecodeSignedOperand(Annotation >> 4);
uint32_t CodeOffset = Annotation & 0xf;
W.startLine() << "ChangeCodeOffsetAndLineOffset: {SourceDelta: "
<< SourceDelta << ", CodeOffset: " << W.hex(CodeOffset)
W.startLine() << "ChangeCodeOffsetAndLineOffset: {LineOffset: "
<< LineOffset << ", CodeOffset: " << W.hex(CodeOffset)
<< "}\n";
break;
}
@ -1722,7 +1712,7 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
error(consumeObject(Data, ISL));
DictScope S(W, "InlineeSourceLine");
printTypeIndex("Inlinee", ISL->Inlinee);
W.printHex("FileID", ISL->FileID);
printFileNameForOffset("FileID", ISL->FileID);
W.printNumber("SourceLineNum", ISL->SourceLineNum);
if (HasExtraFiles) {
@ -1733,7 +1723,7 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
for (unsigned I = 0; I < ExtraFileCount; ++I) {
uint32_t FileID;
error(consumeUInt32(Data, FileID));
W.printHex("FileID", FileID);
printFileNameForOffset("FileID", FileID);
}
}
}
@ -1792,6 +1782,31 @@ void COFFDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
W.printHex(FieldName, TI.getIndex());
}
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;
error(consumeUInt32(Data, StringOffset));
// 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);
}
static StringRef getLeafTypeName(TypeLeafKind LT) {
switch (LT) {
case LF_STRING_ID: return "StringId";