llvm.org GIT mirror llvm / e87e5c3
[PDB] Fix linking of function symbols and local variables. The compiler outputs PROC32_ID symbols into the object files for functions, and these symbols have an embedded type index which, when copied to the PDB, refer to the IPI stream. However, the symbols themselves are also converted into regular symbols (e.g. S_GPROC32_ID -> S_GPROC32), and type indices in the regular symbol records refer to the TPI stream. So this patch applies two fixes to function records. 1. It converts ID symbols to the proper non-ID record type. 2. After remapping the type index from the object file's index space to the PDB file/IPI stream's index space, it then remaps that index to the TPI stream's index space by. Besides functions, during the remapping process we were also discarding symbol record types which we did not recognize. In particular, we were discarding S_BPREL32 records, which is what MSVC uses to describe local variables on the stack. So this patch fixes that as well by copying them to the PDB. Differential Revision: https://reviews.llvm.org/D36426 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310394 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
7 changed file(s) with 101 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
4949 if (auto EC = I.Mapping.visitTypeEnd(CVT))
5050 return EC;
5151 return Error::success();
52 }
53
54 template
55 static Expected deserializeAs(ArrayRef Data) {
56 CVType CVT;
57 CVT.RecordData = Data;
58 MappingInfo I(CVT.content());
59 const RecordPrefix *Prefix =
60 reinterpret_cast(Data.data());
61 TypeRecordKind K =
62 static_cast(uint16_t(Prefix->RecordKind));
63 T Record(K);
64 if (auto EC = deserializeAs(CVT, Record))
65 return std::move(EC);
66 return Record;
5267 }
5368
5469 Error visitTypeBegin(CVType &Record) override {
2929 SmallVectorImpl &Refs);
3030 void discoverTypeIndices(const CVType &Type,
3131 SmallVectorImpl &Indices);
32 void discoverTypeIndices(ArrayRef RecordData,
33 SmallVectorImpl &Indices);
3234
3335 /// Discover type indices in symbol records. Returns false if this is an unknown
3436 /// record.
35 bool discoverTypeIndices(const CVSymbol &Symbol,
36 SmallVectorImpl &Refs);
37 bool discoverTypeIndicesInSymbol(const CVSymbol &Symbol,
38 SmallVectorImpl &Refs);
39 bool discoverTypeIndicesInSymbol(ArrayRef RecordData,
40 SmallVectorImpl &Refs);
41 bool discoverTypeIndicesInSymbol(ArrayRef RecordData,
42 SmallVectorImpl &Indices);
3743 }
3844 }
3945
394394 case SymbolKind::S_CONSTANT:
395395 Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
396396 break;
397 case SymbolKind::S_BPREL32:
397398 case SymbolKind::S_REGREL32:
398399 Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
399400 break;
449450 ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
450451 }
451452
452 void llvm::codeview::discoverTypeIndices(const CVType &Type,
453 SmallVectorImpl &Indices) {
454
453 static void resolveTypeIndexReferences(ArrayRef RecordData,
454 ArrayRef Refs,
455 SmallVectorImpl &Indices) {
455456 Indices.clear();
456457
457 SmallVector Refs;
458 discoverTypeIndices(Type, Refs);
459458 if (Refs.empty())
460459 return;
461460
462 BinaryStreamReader Reader(Type.content(), support::little);
461 RecordData = RecordData.drop_front(sizeof(RecordPrefix));
462
463 BinaryStreamReader Reader(RecordData, support::little);
463464 for (const auto &Ref : Refs) {
464465 Reader.setOffset(Ref.Offset);
465466 FixedStreamArray Run;
468469 }
469470 }
470471
472 void llvm::codeview::discoverTypeIndices(const CVType &Type,
473 SmallVectorImpl &Indices) {
474 return discoverTypeIndices(Type.RecordData, Indices);
475 }
476
477 void llvm::codeview::discoverTypeIndices(ArrayRef RecordData,
478 SmallVectorImpl &Indices) {
479 SmallVector Refs;
480 discoverTypeIndices(RecordData, Refs);
481 resolveTypeIndexReferences(RecordData, Refs, Indices);
482 }
483
471484 void llvm::codeview::discoverTypeIndices(ArrayRef RecordData,
472485 SmallVectorImpl &Refs) {
473486 const RecordPrefix *P =
476489 ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
477490 }
478491
479 bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym,
480 SmallVectorImpl &Refs) {
492 bool llvm::codeview::discoverTypeIndicesInSymbol(
493 const CVSymbol &Sym, SmallVectorImpl &Refs) {
481494 SymbolKind K = Sym.kind();
482495 return ::discoverTypeIndices(Sym.content(), K, Refs);
483496 }
497
498 bool llvm::codeview::discoverTypeIndicesInSymbol(
499 ArrayRef RecordData, SmallVectorImpl &Refs) {
500 const RecordPrefix *P =
501 reinterpret_cast(RecordData.data());
502 SymbolKind K = static_cast(uint16_t(P->RecordKind));
503 return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
504 Refs);
505 }
506
507 bool llvm::codeview::discoverTypeIndicesInSymbol(
508 ArrayRef RecordData, SmallVectorImpl &Indices) {
509 SmallVector Refs;
510 if (!discoverTypeIndicesInSymbol(RecordData, Refs))
511 return false;
512 resolveTypeIndexReferences(RecordData, Refs, Indices);
513 return true;
514 }
836836
837837 ExitOnError Err("Unexpected error processing symbols: ");
838838
839 auto &Ids = Err(initializeTypes(StreamIPI));
839840 auto &Types = Err(initializeTypes(StreamTPI));
840841
841842 iterateModules(
851852
852853 SymbolVisitorCallbackPipeline Pipeline;
853854 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
854 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
855 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids,
856 Types);
855857
856858 Pipeline.addCallbackToPipeline(Deserializer);
857859 Pipeline.addCallbackToPipeline(Dumper);
935937 auto ExpectedTypes = initializeTypes(StreamTPI);
936938 if (!ExpectedTypes)
937939 return ExpectedTypes.takeError();
940 auto ExpectedIds = initializeTypes(StreamIPI);
941 if (!ExpectedIds)
942 return ExpectedIds.takeError();
938943 SymbolVisitorCallbackPipeline Pipeline;
939944 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
940 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedTypes);
945 MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedIds,
946 *ExpectedTypes);
941947
942948 Pipeline.addCallbackToPipeline(Deserializer);
943949 Pipeline.addCallbackToPipeline(Dumper);
388388 return Error::success();
389389 }
390390
391 std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
391 std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI,
392 bool IsType) const {
392393 if (TI.isSimple())
393394 return formatv("{0}", TI).str();
394 StringRef Name = Types.getTypeName(TI);
395 auto &Container = IsType ? Types : Ids;
396 StringRef Name = Container.getTypeName(TI);
395397 if (Name.size() > 32) {
396398 Name = Name.take_front(32);
397399 return formatv("{0} ({1}...)", TI, Name);
398400 } else
399401 return formatv("{0} ({1})", TI, Name);
402 }
403
404 std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const {
405 return typeOrIdIndex(TI, false);
406 }
407
408 std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
409 return typeOrIdIndex(TI, true);
400410 }
401411
402412 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
726736 Proc.Parent, Proc.End,
727737 formatSegmentOffset(Proc.Segment, Proc.CodeOffset),
728738 Proc.CodeSize);
729 // FIXME: It seems FunctionType is sometimes an id and sometimes a type.
739 bool IsType = true;
740 switch (Proc.getKind()) {
741 case SymbolRecordKind::GlobalProcIdSym:
742 case SymbolRecordKind::ProcIdSym:
743 case SymbolRecordKind::DPCProcIdSym:
744 IsType = false;
745 break;
746 default:
747 break;
748 }
730749 P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}",
731 typeIndex(Proc.FunctionType), Proc.DbgStart, Proc.DbgEnd,
750 typeOrIdIndex(Proc.FunctionType, IsType), Proc.DbgStart,
751 Proc.DbgEnd,
732752 formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags));
733753 return Error::success();
734754 }
2222 class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks {
2323 public:
2424 MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
25 codeview::LazyRandomTypeCollection &Ids,
2526 codeview::LazyRandomTypeCollection &Types)
26 : P(P), Types(Types) {}
27 : P(P), Ids(Ids), Types(Types) {}
2728
2829 Error visitSymbolBegin(codeview::CVSymbol &Record) override;
2930 Error visitSymbolBegin(codeview::CVSymbol &Record, uint32_t Offset) override;
3637 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
3738
3839 private:
40 std::string typeOrIdIndex(codeview::TypeIndex TI, bool IsType) const;
41
3942 std::string typeIndex(codeview::TypeIndex TI) const;
43 std::string idIndex(codeview::TypeIndex TI) const;
4044
4145 LinePrinter &P;
46 codeview::LazyRandomTypeCollection &Ids;
4247 codeview::LazyRandomTypeCollection &Types;
4348 };
4449 } // namespace pdb
130130 void discoverTypeIndicesInSymbols() {
131131 Refs.resize(Symbols.size());
132132 for (uint32_t I = 0; I < Symbols.size(); ++I)
133 discoverTypeIndices(Symbols[I], Refs[I]);
133 discoverTypeIndicesInSymbol(Symbols[I], Refs[I]);
134134 }
135135
136136 // Helper function to write out a field list record with the given list