[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