[llvm] r298717 - [PDB] Split item and type records when merging type streams
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 24 10:26:39 PDT 2017
Author: rnk
Date: Fri Mar 24 12:26:38 2017
New Revision: 298717
URL: http://llvm.org/viewvc/llvm-project?rev=298717&view=rev
Log:
[PDB] Split item and type records when merging type streams
Summary: MSVC does this when producing a PDB.
Reviewers: ruiu
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D31316
Modified:
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
llvm/trunk/test/tools/llvm-readobj/codeview-merging.test
llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
llvm/trunk/tools/llvm-readobj/ObjDumper.h
llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h?rev=298717&r1=298716&r2=298717&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h Fri Mar 24 12:26:38 2017
@@ -21,8 +21,9 @@ namespace codeview {
class TypeServerHandler;
/// Merges one type stream into another. Returns true on success.
-Error mergeTypeStreams(TypeTableBuilder &DestStream, TypeServerHandler *Handler,
- const CVTypeArray &Types);
+Error mergeTypeStreams(TypeTableBuilder &DestIdStream,
+ TypeTableBuilder &DestTypeStream,
+ TypeServerHandler *Handler, const CVTypeArray &Types);
} // end namespace codeview
} // end namespace llvm
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp?rev=298717&r1=298716&r2=298717&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp Fri Mar 24 12:26:38 2017
@@ -52,11 +52,17 @@ namespace {
/// - If the type record already exists in the destination stream, discard it
/// and update the type index map to forward the source type index to the
/// existing destination type index.
+///
+/// As an additional complication, type stream merging actually produces two
+/// streams: an item (or IPI) stream and a type stream, as this is what is
+/// actually stored in the final PDB. We choose which records go where by
+/// looking at the record kind.
class TypeStreamMerger : public TypeVisitorCallbacks {
public:
- TypeStreamMerger(TypeTableBuilder &DestStream, TypeServerHandler *Handler)
- : DestStream(DestStream), FieldListBuilder(DestStream), Handler(Handler) {
- }
+ TypeStreamMerger(TypeTableBuilder &DestIdStream,
+ TypeTableBuilder &DestTypeStream, TypeServerHandler *Handler)
+ : DestIdStream(DestIdStream), DestTypeStream(DestTypeStream),
+ FieldListBuilder(DestTypeStream), Handler(Handler) {}
/// TypeVisitorCallbacks overrides.
#define TYPE_RECORD(EnumName, EnumVal, Name) \
@@ -85,7 +91,18 @@ private:
std::move(*LastError),
llvm::make_error<CodeViewError>(cv_error_code::corrupt_record));
}
- IndexMap.push_back(DestStream.writeKnownType(R));
+ IndexMap.push_back(DestTypeStream.writeKnownType(R));
+ return Error::success();
+ }
+
+ template <typename RecordType>
+ Error writeIdRecord(RecordType &R, bool RemapSuccess) {
+ if (!RemapSuccess) {
+ LastError = joinErrors(
+ std::move(*LastError),
+ llvm::make_error<CodeViewError>(cv_error_code::corrupt_record));
+ }
+ IndexMap.push_back(DestIdStream.writeKnownType(R));
return Error::success();
}
@@ -104,7 +121,8 @@ private:
BumpPtrAllocator Allocator;
- TypeTableBuilder &DestStream;
+ TypeTableBuilder &DestIdStream;
+ TypeTableBuilder &DestTypeStream;
FieldListRecordBuilder FieldListBuilder;
TypeServerHandler *Handler;
@@ -158,6 +176,62 @@ bool TypeStreamMerger::remapIndex(TypeIn
return false;
}
+//----------------------------------------------------------------------------//
+// Item records
+//----------------------------------------------------------------------------//
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, FuncIdRecord &R) {
+ bool Success = true;
+ Success &= remapIndex(R.ParentScope);
+ Success &= remapIndex(R.FunctionType);
+ return writeIdRecord(R, Success);
+}
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, MemberFuncIdRecord &R) {
+ bool Success = true;
+ Success &= remapIndex(R.ClassType);
+ Success &= remapIndex(R.FunctionType);
+ return writeIdRecord(R, Success);
+}
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, StringIdRecord &R) {
+ return writeIdRecord(R, remapIndex(R.Id));
+}
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, StringListRecord &R) {
+ bool Success = true;
+ for (TypeIndex &Str : R.StringIndices)
+ Success &= remapIndex(Str);
+ return writeIdRecord(R, Success);
+}
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, BuildInfoRecord &R) {
+ bool Success = true;
+ for (TypeIndex &Arg : R.ArgIndices)
+ Success &= remapIndex(Arg);
+ return writeIdRecord(R, Success);
+}
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, UdtSourceLineRecord &R) {
+ bool Success = true;
+ Success &= remapIndex(R.UDT);
+ Success &= remapIndex(R.SourceFile);
+ // FIXME: Translate UdtSourceLineRecord into UdtModSourceLineRecords in the
+ // IPI stream.
+ return writeIdRecord(R, Success);
+}
+
+Error TypeStreamMerger::visitKnownRecord(CVType &, UdtModSourceLineRecord &R) {
+ bool Success = true;
+ Success &= remapIndex(R.UDT);
+ Success &= remapIndex(R.SourceFile);
+ return writeIdRecord(R, Success);
+}
+
+//----------------------------------------------------------------------------//
+// Type records
+//----------------------------------------------------------------------------//
+
Error TypeStreamMerger::visitKnownRecord(CVType &, ModifierRecord &R) {
return writeRecord(R, remapIndex(R.ModifiedType));
}
@@ -178,13 +252,6 @@ Error TypeStreamMerger::visitKnownRecord
return writeRecord(R, Success);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, MemberFuncIdRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ClassType);
- Success &= remapIndex(R.FunctionType);
- return writeRecord(R, Success);
-}
-
Error TypeStreamMerger::visitKnownRecord(CVType &, ArgListRecord &R) {
bool Success = true;
for (TypeIndex &Arg : R.ArgIndices)
@@ -192,13 +259,6 @@ Error TypeStreamMerger::visitKnownRecord
return writeRecord(R, Success);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, StringListRecord &R) {
- bool Success = true;
- for (TypeIndex &Str : R.StringIndices)
- Success &= remapIndex(Str);
- return writeRecord(R, Success);
-}
-
Error TypeStreamMerger::visitKnownRecord(CVType &, PointerRecord &R) {
bool Success = true;
Success &= remapIndex(R.ReferentType);
@@ -245,38 +305,6 @@ Error TypeStreamMerger::visitKnownRecord
return writeRecord(R, true);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, StringIdRecord &R) {
- return writeRecord(R, remapIndex(R.Id));
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, FuncIdRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ParentScope);
- Success &= remapIndex(R.FunctionType);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, UdtSourceLineRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.UDT);
- Success &= remapIndex(R.SourceFile);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, UdtModSourceLineRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.UDT);
- Success &= remapIndex(R.SourceFile);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, BuildInfoRecord &R) {
- bool Success = true;
- for (TypeIndex &Arg : R.ArgIndices)
- Success &= remapIndex(Arg);
- return writeRecord(R, Success);
-}
-
Error TypeStreamMerger::visitKnownRecord(CVType &, VFTableRecord &R) {
bool Success = true;
Success &= remapIndex(R.CompleteClass);
@@ -300,6 +328,10 @@ Error TypeStreamMerger::visitKnownRecord
return Error::success();
}
+//----------------------------------------------------------------------------//
+// Member records
+//----------------------------------------------------------------------------//
+
Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
NestedTypeRecord &R) {
return writeMember(R, remapIndex(R.Type));
@@ -381,8 +413,10 @@ Error TypeStreamMerger::mergeStream(cons
return Ret;
}
-Error llvm::codeview::mergeTypeStreams(TypeTableBuilder &DestStream,
+Error llvm::codeview::mergeTypeStreams(TypeTableBuilder &DestIdStream,
+ TypeTableBuilder &DestTypeStream,
TypeServerHandler *Handler,
const CVTypeArray &Types) {
- return TypeStreamMerger(DestStream, Handler).mergeStream(Types);
+ return TypeStreamMerger(DestIdStream, DestTypeStream, Handler)
+ .mergeStream(Types);
}
Modified: llvm/trunk/test/tools/llvm-readobj/codeview-merging.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/codeview-merging.test?rev=298717&r1=298716&r2=298717&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/codeview-merging.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/codeview-merging.test Fri Mar 24 12:26:38 2017
@@ -21,6 +21,15 @@ RUN: llvm-readobj -codeview %S/Inputs/co
RUN: llvm-readobj -codeview %S/Inputs/codeview-merging-2.obj | FileCheck %s --check-prefix=OBJ2
RUN: llvm-readobj -codeview-merged-types %S/Inputs/codeview-merging-1.obj %S/Inputs/codeview-merging-2.obj | FileCheck %s
+OBJ1: Procedure ({{.*}}) {
+OBJ1-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008)
+OBJ1-NEXT: ReturnType: int (0x74)
+OBJ1-NEXT: CallingConvention: NearC (0x0)
+OBJ1-NEXT: FunctionOptions [ (0x0)
+OBJ1-NEXT: ]
+OBJ1-NEXT: NumParameters: 1
+OBJ1-NEXT: ArgListType: (A*) (0x1002)
+OBJ1-NEXT: }
OBJ1: FuncId (0x100D) {
OBJ1-NEXT: TypeLeafKind: LF_FUNC_ID (0x1601)
OBJ1-NEXT: ParentScope: 0x0
@@ -50,16 +59,55 @@ OBJ2-NEXT: Name: g
OBJ2-NEXT: }
OBJ2-NOT: FuncId
-CHECK: FuncId (0x100D) {
+CHECK: MergedTypeStream [
+CHECK: Procedure ({{.*}}) {
+CHECK-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008)
+CHECK-NEXT: ReturnType: int (0x74)
+CHECK-NEXT: CallingConvention: NearC (0x0)
+CHECK-NEXT: FunctionOptions [ (0x0)
+CHECK-NEXT: ]
+CHECK-NEXT: NumParameters: 1
+CHECK-NEXT: ArgListType: (A*) (0x1002)
+CHECK-NEXT: }
+CHECK: Struct (0x1007) {
+CHECK-NEXT: TypeLeafKind: LF_STRUCTURE (0x1505)
+CHECK-NEXT: MemberCount: 1
+CHECK-NEXT: Properties [ (0x200)
+CHECK-NEXT: HasUniqueName (0x200)
+CHECK-NEXT: ]
+CHECK-NEXT: FieldList: <field list> (0x1006)
+CHECK-NEXT: DerivedFrom: 0x0
+CHECK-NEXT: VShape: 0x0
+CHECK-NEXT: SizeOf: 8
+CHECK-NEXT: Name: B
+CHECK-NEXT: LinkageName: .?AUB@@
+CHECK-NEXT: }
+CHECK: ]
+
+CHECK: MergedIDStream [
+CHECK-NEXT: StringId (0x1000) {
+CHECK-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
+CHECK-NEXT: Id: 0x0
+CHECK-NEXT: StringData: d:\src\llvm\build\t.cpp
+CHECK-NEXT: }
+# Test that we contextually dump item ids and type ids from different databases.
+CHECK-NEXT: UdtSourceLine (0x1001) {
+CHECK-NEXT: TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+CHECK-NEXT: UDT: B (0x1007)
+CHECK-NEXT: SourceFile: d:\src\llvm\build\t.cpp (0x1000)
+CHECK-NEXT: LineNumber: 3
+CHECK-NEXT: }
+CHECK: FuncId (0x1002) {
CHECK-NEXT: TypeLeafKind: LF_FUNC_ID (0x1601)
CHECK-NEXT: ParentScope: 0x0
-CHECK-NEXT: FunctionType: int (B*) (0x100C)
+CHECK-NEXT: FunctionType: int (B*)
CHECK-NEXT: Name: g
CHECK-NEXT: }
-CHECK-NEXT: FuncId (0x100E) {
+CHECK-NEXT: FuncId (0x1003) {
CHECK-NEXT: TypeLeafKind: LF_FUNC_ID (0x1601)
CHECK-NEXT: ParentScope: 0x0
-CHECK-NEXT: FunctionType: int (A*) (0x1003)
+CHECK-NEXT: FunctionType: int (A*)
CHECK-NEXT: Name: f
CHECK-NEXT: }
CHECK-NOT: FuncId
+CHECK: ]
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=298717&r1=298716&r2=298717&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Fri Mar 24 12:26:38 2017
@@ -79,7 +79,8 @@ public:
void printCOFFBaseReloc() override;
void printCOFFDebugDirectory() override;
void printCodeViewDebugInfo() override;
- void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVTypes) override;
+ void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs,
+ llvm::codeview::TypeTableBuilder &CVTypes) override;
void printStackMap() const override;
private:
void printSymbol(const SymbolRef &Sym);
@@ -1064,7 +1065,8 @@ void COFFDumper::printFileNameForOffset(
W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset);
}
-void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVTypes) {
+void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVIDs,
+ TypeTableBuilder &CVTypes) {
for (const SectionRef &S : Obj->sections()) {
StringRef SectionName;
error(S.getName(SectionName));
@@ -1086,7 +1088,7 @@ void COFFDumper::mergeCodeViewTypes(Type
error(object_error::parse_failed);
}
- if (auto EC = mergeTypeStreams(CVTypes, nullptr, Types)) {
+ if (auto EC = mergeTypeStreams(CVIDs, CVTypes, nullptr, Types)) {
consumeError(std::move(EC));
return error(object_error::parse_failed);
}
@@ -1551,20 +1553,43 @@ void COFFDumper::printStackMap() const {
}
void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
+ llvm::codeview::TypeTableBuilder &IDTable,
llvm::codeview::TypeTableBuilder &CVTypes) {
// Flatten it first, then run our dumper on it.
- ListScope S(Writer, "MergedTypeStream");
- SmallString<0> Buf;
+ SmallString<0> TypeBuf;
CVTypes.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) {
- Buf.append(Record.begin(), Record.end());
+ TypeBuf.append(Record.begin(), Record.end());
});
TypeDatabase TypeDB;
- CVTypeDumper CVTD(TypeDB);
- TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
- if (auto EC =
- CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()}, TDV)) {
- Writer.flush();
- error(llvm::errorToErrorCode(std::move(EC)));
+ {
+ ListScope S(Writer, "MergedTypeStream");
+ CVTypeDumper CVTD(TypeDB);
+ TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
+ if (auto EC = CVTD.dump(
+ {TypeBuf.str().bytes_begin(), TypeBuf.str().bytes_end()}, TDV)) {
+ Writer.flush();
+ error(llvm::errorToErrorCode(std::move(EC)));
+ }
+ }
+
+ // Flatten the id stream and print it next. The ID stream refers to names from
+ // the type stream.
+ SmallString<0> IDBuf;
+ IDTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) {
+ IDBuf.append(Record.begin(), Record.end());
+ });
+
+ {
+ ListScope S(Writer, "MergedIDStream");
+ TypeDatabase IDDB;
+ CVTypeDumper CVTD(IDDB);
+ TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
+ TDV.setItemDB(IDDB);
+ if (auto EC = CVTD.dump(
+ {IDBuf.str().bytes_begin(), IDBuf.str().bytes_end()}, TDV)) {
+ Writer.flush();
+ error(llvm::errorToErrorCode(std::move(EC)));
+ }
}
}
Modified: llvm/trunk/tools/llvm-readobj/ObjDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ObjDumper.h?rev=298717&r1=298716&r2=298717&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ObjDumper.h (original)
+++ llvm/trunk/tools/llvm-readobj/ObjDumper.h Fri Mar 24 12:26:38 2017
@@ -68,7 +68,8 @@ public:
virtual void printCOFFBaseReloc() { }
virtual void printCOFFDebugDirectory() { }
virtual void printCodeViewDebugInfo() { }
- virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVTypes) {}
+ virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs,
+ llvm::codeview::TypeTableBuilder &CVTypes) {}
// Only implemented for MachO.
virtual void printMachODataInCode() { }
@@ -103,7 +104,8 @@ std::error_code createWasmDumper(const o
void dumpCOFFImportFile(const object::COFFImportFile *File);
void dumpCodeViewMergedTypes(ScopedPrinter &Writer,
- llvm::codeview::TypeTableBuilder &CVTypes);
+ llvm::codeview::TypeTableBuilder &IDTable,
+ llvm::codeview::TypeTableBuilder &TypeTable);
} // namespace llvm
Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=298717&r1=298716&r2=298717&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Fri Mar 24 12:26:38 2017
@@ -338,10 +338,12 @@ static bool isMipsArch(unsigned Arch) {
}
namespace {
struct ReadObjTypeTableBuilder {
- ReadObjTypeTableBuilder() : Allocator(), Builder(Allocator) {}
+ ReadObjTypeTableBuilder()
+ : Allocator(), IDTable(Allocator), TypeTable(Allocator) {}
llvm::BumpPtrAllocator Allocator;
- llvm::codeview::TypeTableBuilder Builder;
+ llvm::codeview::TypeTableBuilder IDTable;
+ llvm::codeview::TypeTableBuilder TypeTable;
};
}
static ReadObjTypeTableBuilder CVTypes;
@@ -446,7 +448,7 @@ static void dumpObject(const ObjectFile
if (opts::CodeView)
Dumper->printCodeViewDebugInfo();
if (opts::CodeViewMergedTypes)
- Dumper->mergeCodeViewTypes(CVTypes.Builder);
+ Dumper->mergeCodeViewTypes(CVTypes.IDTable, CVTypes.TypeTable);
}
if (Obj->isMachO()) {
if (opts::MachODataInCode)
@@ -551,7 +553,7 @@ int main(int argc, const char *argv[]) {
if (opts::CodeViewMergedTypes) {
ScopedPrinter W(outs());
- dumpCodeViewMergedTypes(W, CVTypes.Builder);
+ dumpCodeViewMergedTypes(W, CVTypes.IDTable, CVTypes.TypeTable);
}
return 0;
More information about the llvm-commits
mailing list