diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/CodeView.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h | 8 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h | 44 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/EnumTables.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp | 31 | ||||
-rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-headers.test | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp | 5 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h | 7 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/COFFDumper.cpp | 7 |
9 files changed, 96 insertions, 11 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 4ce9f68cffd..fd2a66551ae 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -231,6 +231,8 @@ enum class FrameProcedureOptions : uint32_t { Inlined = 0x00000800, StrictSecurityChecks = 0x00001000, SafeBuffers = 0x00002000, + EncodedLocalBasePointerMask = 0x0000C000, + EncodedParamBasePointerMask = 0x00030000, ProfileGuidedOptimization = 0x00040000, ValidProfileCounts = 0x00080000, OptimizedForSpeed = 0x00100000, diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index 293daa851bd..215da2e2b52 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -27,10 +27,10 @@ class CVSymbolDumper { public: CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types, CodeViewContainer Container, - std::unique_ptr<SymbolDumpDelegate> ObjDelegate, + std::unique_ptr<SymbolDumpDelegate> ObjDelegate, CPUType CPU, bool PrintRecordBytes) : W(W), Types(Types), Container(Container), - ObjDelegate(std::move(ObjDelegate)), + ObjDelegate(std::move(ObjDelegate)), CompilationCPUType(CPU), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, @@ -43,12 +43,14 @@ public: /// parse error, and true otherwise. Error dump(const CVSymbolArray &Symbols); + CPUType getCompilationCPUType() const { return CompilationCPUType; } + private: ScopedPrinter &W; TypeCollection &Types; CodeViewContainer Container; std::unique_ptr<SymbolDumpDelegate> ObjDelegate; - + CPUType CompilationCPUType; bool PrintRecordBytes; }; } // end namespace codeview diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 93306824012..039d390ed10 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -761,7 +761,51 @@ public: uint16_t SectionIdOfExceptionHandler; FrameProcedureOptions Flags; + /// Extract the register this frame uses to refer to local variables. + RegisterId getLocalFramePtrReg(CPUType CPU) const { + return decodeFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U, CPU); + } + + /// Extract the register this frame uses to refer to parameters. + RegisterId getParamFramePtrReg(CPUType CPU) const { + return decodeFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U, CPU); + } + uint32_t RecordOffset; + +private: + static RegisterId decodeFramePtrReg(uint32_t EncodedReg, CPUType CPU) { + assert(EncodedReg < 4); + switch (CPU) { + // FIXME: Add ARM and AArch64 variants here. + default: + break; + case CPUType::Intel8080: + case CPUType::Intel8086: + case CPUType::Intel80286: + case CPUType::Intel80386: + case CPUType::Intel80486: + case CPUType::Pentium: + case CPUType::PentiumPro: + case CPUType::Pentium3: + switch (EncodedReg) { + case 0: return RegisterId::NONE; + case 1: return RegisterId::VFRAME; + case 2: return RegisterId::EBP; + case 3: return RegisterId::EBX; + } + llvm_unreachable("bad encoding"); + case CPUType::X64: + switch (EncodedReg) { + case 0: return RegisterId::NONE; + case 1: return RegisterId::RSP; + case 2: return RegisterId::RBP; + case 3: return RegisterId::R13; + } + llvm_unreachable("bad encoding"); + } + return RegisterId::NONE; + } }; // S_CALLSITEINFO diff --git a/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/llvm/lib/DebugInfo/CodeView/EnumTables.cpp index d8301cab165..ef4e42f79eb 100644 --- a/llvm/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/llvm/lib/DebugInfo/CodeView/EnumTables.cpp @@ -200,6 +200,8 @@ static const EnumEntry<uint32_t> FrameProcSymFlagNames[] = { CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined), CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks), CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedLocalBasePointerMask), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedParamBasePointerMask), CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization), CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts), CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed), diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index f8bf961f22a..4cb267e857e 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -32,8 +32,8 @@ namespace { class CVSymbolDumperImpl : public SymbolVisitorCallbacks { public: CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate, - ScopedPrinter &W, bool PrintRecordBytes) - : Types(Types), ObjDelegate(ObjDelegate), W(W), + ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes) + : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} /// CVSymbolVisitor overrides. @@ -46,6 +46,8 @@ public: Error visitSymbolEnd(CVSymbol &Record) override; Error visitUnknownSymbol(CVSymbol &Record) override; + CPUType getCompilationCPUType() const { return CompilationCPUType; } + private: void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, uint32_t RelocationOffset); @@ -56,6 +58,9 @@ private: SymbolDumpDelegate *ObjDelegate; ScopedPrinter &W; + /// Save the machine or CPU type when dumping a compile symbols. + CPUType CompilationCPUType = CPUType::X64; + bool PrintRecordBytes; bool InFunctionScope; }; @@ -235,6 +240,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames()); W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames()); W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames()); + CompilationCPUType = Compile2.Machine; std::string FrontendVersion; { raw_string_ostream Out(FrontendVersion); @@ -258,6 +264,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames()); W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames()); W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames()); + CompilationCPUType = Compile3.Machine; std::string FrontendVersion; { raw_string_ostream Out(FrontendVersion); @@ -415,6 +422,12 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, FrameProc.SectionIdOfExceptionHandler); W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags), getFrameProcSymFlagNames()); + W.printEnum("LocalFramePtrReg", + uint16_t(FrameProc.getLocalFramePtrReg(CompilationCPUType)), + getRegisterNames()); + W.printEnum("ParamFramePtrReg", + uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)), + getRegisterNames()); return Error::success(); } @@ -625,21 +638,27 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get(), Container); - CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, + PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); CVSymbolVisitor Visitor(Pipeline); - return Visitor.visitSymbolRecord(Record); + auto Err = Visitor.visitSymbolRecord(Record); + CompilationCPUType = Dumper.getCompilationCPUType(); + return Err; } Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get(), Container); - CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, + PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); CVSymbolVisitor Visitor(Pipeline); - return Visitor.visitSymbolStream(Symbols); + auto Err = Visitor.visitSymbolStream(Symbols); + CompilationCPUType = Dumper.getCompilationCPUType(); + return Err; } diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index b05e62078b7..99c37218e92 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -487,6 +487,7 @@ ALL-NEXT: type = `0x1001 (int ())`, debug start = 3, debug end = 8, fla ALL-NEXT: 164 | S_FRAMEPROC [size = 32] ALL-NEXT: size = 0, padding size = 0, offset to padding = 0 ALL-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 +ALL-NEXT: local fp reg = EBP, param fp reg = EBP ALL-NEXT: flags = has async eh | opt speed ALL-NEXT: 196 | S_END [size = 4] ALL-NEXT: 200 | S_BUILDINFO [size = 8] BuildId = `0x100E` diff --git a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp index f8b2ecc6060..5dc4f85c9bc 100644 --- a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -490,6 +490,7 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, AutoIndent Indent(P, 7); SourceLanguage Lang = static_cast<SourceLanguage>( Compile2.Flags & CompileSym2Flags::SourceLanguageMask); + CompilationCPU = Compile2.Machine; P.formatLine("machine = {0}, ver = {1}, language = {2}", formatMachineType(Compile2.Machine), Compile2.Version, formatSourceLanguage(Lang)); @@ -510,6 +511,7 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, AutoIndent Indent(P, 7); SourceLanguage Lang = static_cast<SourceLanguage>( Compile3.Flags & CompileSym3Flags::SourceLanguageMask); + CompilationCPU = Compile3.Machine; P.formatLine("machine = {0}, Ver = {1}, language = {2}", formatMachineType(Compile3.Machine), Compile3.Version, formatSourceLanguage(Lang)); @@ -629,6 +631,9 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameProcSym &FP) { FP.BytesOfCalleeSavedRegisters, formatSegmentOffset(FP.SectionIdOfExceptionHandler, FP.OffsetOfExceptionHandler)); + P.formatLine("local fp reg = {0}, param fp reg = {1}", + formatRegisterId(FP.getLocalFPReg(CompilationCPU)), + formatRegisterId(FP.getParamFPReg(CompilationCPU))); P.formatLine("flags = {0}", formatFrameProcedureOptions(P.getIndentLevel() + 9, FP.Flags)); return Error::success(); diff --git a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h index 1c26a85a4ea..033e193cee6 100644 --- a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h +++ b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.h @@ -53,6 +53,11 @@ private: std::string idIndex(codeview::TypeIndex TI) const; LinePrinter &P; + + /// Dumping certain records requires knowing what machine this is. The + /// S_COMPILE3 record will tell us, but if we don't see one, default to X64. + codeview::CPUType CompilationCPU = codeview::CPUType::X64; + bool RecordBytes; const SymbolGroup *SymGroup = nullptr; codeview::LazyRandomTypeCollection &Ids; @@ -61,4 +66,4 @@ private: } // namespace pdb } // namespace llvm -#endif
\ No newline at end of file +#endif diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index e9944908982..8da5fc4234e 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -179,6 +179,10 @@ private: DebugStringTableSubsectionRef CVStringTable; + /// Track the compilation CPU type. S_COMPILE3 symbol records typically come + /// first, but if we don't see one, just assume an X64 CPU type. It is common. + CPUType CompilationCPUType = CPUType::X64; + ScopedPrinter &Writer; BinaryByteStream TypeContents; LazyRandomTypeCollection Types; @@ -1150,7 +1154,7 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj, SectionContents); CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD), - opts::CodeViewSubsectionBytes); + CompilationCPUType, opts::CodeViewSubsectionBytes); CVSymbolArray Symbols; BinaryStreamReader Reader(BinaryData, llvm::support::little); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) { @@ -1163,6 +1167,7 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, W.flush(); error(std::move(EC)); } + CompilationCPUType = CVSD.getCompilationCPUType(); W.flush(); } |