llvm.org GIT mirror llvm / b73f47d
[codeview] Decode and dump FP regs from S_FRAMEPROC records Summary: There are two registers encoded in the S_FRAMEPROC flags: one for locals and one for parameters. The encoding is described by the ExpandEncodedBasePointerReg function in cvinfo.h. Two bits are used to indicate one of four possible values: 0: no register - Used when there are no variables. 1: SP / standard - Variables are stored relative to the standard SP for the ISA. 2: FP - Variables are addressed relative to the ISA frame pointer, i.e. EBP on x86. If realignment is required, parameters use this. If a dynamic alloca is used, locals will be EBP relative. 3: Alternative - Variables are stored relative to some alternative third callee-saved register. This is required to address highly aligned locals when there are dynamic stack adjustments. In this case, both the incoming SP saved in the standard FP and the current SP are at some dynamic offset from the locals. LLVM uses ESI in this case, MSVC uses EBX. Most of the changes in this patch are to pass around the CPU so that we can decode these into real, named architectural registers. Subscribers: hiraditya Differential Revision: https://reviews.llvm.org/D51894 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341999 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 1 year, 5 days ago
9 changed file(s) with 98 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
230230 Inlined = 0x00000800,
231231 StrictSecurityChecks = 0x00001000,
232232 SafeBuffers = 0x00002000,
233 EncodedLocalBasePointerMask = 0x0000C000,
234 EncodedParamBasePointerMask = 0x00030000,
233235 ProfileGuidedOptimization = 0x00040000,
234236 ValidProfileCounts = 0x00080000,
235237 OptimizedForSpeed = 0x00100000,
2626 public:
2727 CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types,
2828 CodeViewContainer Container,
29 std::unique_ptr ObjDelegate,
29 std::unique_ptr ObjDelegate, CPUType CPU,
3030 bool PrintRecordBytes)
3131 : W(W), Types(Types), Container(Container),
32 ObjDelegate(std::move(ObjDelegate)),
32 ObjDelegate(std::move(ObjDelegate)), CompilationCPUType(CPU),
3333 PrintRecordBytes(PrintRecordBytes) {}
3434
3535 /// Dumps one type record. Returns false if there was a type parsing error,
4242 /// parse error, and true otherwise.
4343 Error dump(const CVSymbolArray &Symbols);
4444
45 CPUType getCompilationCPUType() const { return CompilationCPUType; }
46
4547 private:
4648 ScopedPrinter &W;
4749 TypeCollection &Types;
4850 CodeViewContainer Container;
4951 std::unique_ptr ObjDelegate;
50
52 CPUType CompilationCPUType;
5153 bool PrintRecordBytes;
5254 };
5355 } // end namespace codeview
760760 uint16_t SectionIdOfExceptionHandler;
761761 FrameProcedureOptions Flags;
762762
763 uint32_t RecordOffset;
763 /// Extract the register this frame uses to refer to local variables.
764 RegisterId getLocalFramePtrReg(CPUType CPU) const {
765 return decodeFramePtrReg((uint32_t(Flags) >> 14U) & 0x3U, CPU);
766 }
767
768 /// Extract the register this frame uses to refer to parameters.
769 RegisterId getParamFramePtrReg(CPUType CPU) const {
770 return decodeFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U, CPU);
771 }
772
773 uint32_t RecordOffset;
774
775 private:
776 static RegisterId decodeFramePtrReg(uint32_t EncodedReg, CPUType CPU) {
777 assert(EncodedReg < 4);
778 switch (CPU) {
779 // FIXME: Add ARM and AArch64 variants here.
780 default:
781 break;
782 case CPUType::Intel8080:
783 case CPUType::Intel8086:
784 case CPUType::Intel80286:
785 case CPUType::Intel80386:
786 case CPUType::Intel80486:
787 case CPUType::Pentium:
788 case CPUType::PentiumPro:
789 case CPUType::Pentium3:
790 switch (EncodedReg) {
791 case 0: return RegisterId::NONE;
792 case 1: return RegisterId::VFRAME;
793 case 2: return RegisterId::EBP;
794 case 3: return RegisterId::EBX;
795 }
796 llvm_unreachable("bad encoding");
797 case CPUType::X64:
798 switch (EncodedReg) {
799 case 0: return RegisterId::NONE;
800 case 1: return RegisterId::RSP;
801 case 2: return RegisterId::RBP;
802 case 3: return RegisterId::R13;
803 }
804 llvm_unreachable("bad encoding");
805 }
806 return RegisterId::NONE;
807 }
764808 };
765809
766810 // S_CALLSITEINFO
199199 CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined),
200200 CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks),
201201 CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers),
202 CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedLocalBasePointerMask),
203 CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedParamBasePointerMask),
202204 CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization),
203205 CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts),
204206 CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed),
3131 class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
3232 public:
3333 CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
34 ScopedPrinter &W, bool PrintRecordBytes)
35 : Types(Types), ObjDelegate(ObjDelegate), W(W),
34 ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes)
35 : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU),
3636 PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
3737
3838 /// CVSymbolVisitor overrides.
4545 Error visitSymbolEnd(CVSymbol &Record) override;
4646 Error visitUnknownSymbol(CVSymbol &Record) override;
4747
48 CPUType getCompilationCPUType() const { return CompilationCPUType; }
49
4850 private:
4951 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
5052 uint32_t RelocationOffset);
5456 TypeCollection &Types;
5557 SymbolDumpDelegate *ObjDelegate;
5658 ScopedPrinter &W;
59
60 /// Save the machine or CPU type when dumping a compile symbols.
61 CPUType CompilationCPUType = CPUType::X64;
5762
5863 bool PrintRecordBytes;
5964 bool InFunctionScope;
234239 W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames());
235240 W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames());
236241 W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
242 CompilationCPUType = Compile2.Machine;
237243 std::string FrontendVersion;
238244 {
239245 raw_string_ostream Out(FrontendVersion);
257263 W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames());
258264 W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames());
259265 W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
266 CompilationCPUType = Compile3.Machine;
260267 std::string FrontendVersion;
261268 {
262269 raw_string_ostream Out(FrontendVersion);
414421 FrameProc.SectionIdOfExceptionHandler);
415422 W.printFlags("Flags", static_cast(FrameProc.Flags),
416423 getFrameProcSymFlagNames());
424 W.printEnum("LocalFramePtrReg",
425 uint16_t(FrameProc.getLocalFramePtrReg(CompilationCPUType)),
426 getRegisterNames());
427 W.printEnum("ParamFramePtrReg",
428 uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)),
429 getRegisterNames());
417430 return Error::success();
418431 }
419432
624637 Error CVSymbolDumper::dump(CVRecord &Record) {
625638 SymbolVisitorCallbackPipeline Pipeline;
626639 SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
627 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
640 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType,
641 PrintRecordBytes);
628642
629643 Pipeline.addCallbackToPipeline(Deserializer);
630644 Pipeline.addCallbackToPipeline(Dumper);
631645 CVSymbolVisitor Visitor(Pipeline);
632 return Visitor.visitSymbolRecord(Record);
646 auto Err = Visitor.visitSymbolRecord(Record);
647 CompilationCPUType = Dumper.getCompilationCPUType();
648 return Err;
633649 }
634650
635651 Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
636652 SymbolVisitorCallbackPipeline Pipeline;
637653 SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
638 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
654 CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType,
655 PrintRecordBytes);
639656
640657 Pipeline.addCallbackToPipeline(Deserializer);
641658 Pipeline.addCallbackToPipeline(Dumper);
642659 CVSymbolVisitor Visitor(Pipeline);
643 return Visitor.visitSymbolStream(Symbols);
644 }
660 auto Err = Visitor.visitSymbolStream(Symbols);
661 CompilationCPUType = Dumper.getCompilationCPUType();
662 return Err;
663 }
486486 ALL-NEXT: 164 | S_FRAMEPROC [size = 32]
487487 ALL-NEXT: size = 0, padding size = 0, offset to padding = 0
488488 ALL-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000
489 ALL-NEXT: local fp reg = EBP, param fp reg = EBP
489490 ALL-NEXT: flags = has async eh | opt speed
490491 ALL-NEXT: 196 | S_END [size = 4]
491492 ALL-NEXT: 200 | S_BUILDINFO [size = 8] BuildId = `0x100E`
489489 AutoIndent Indent(P, 7);
490490 SourceLanguage Lang = static_cast(
491491 Compile2.Flags & CompileSym2Flags::SourceLanguageMask);
492 CompilationCPU = Compile2.Machine;
492493 P.formatLine("machine = {0}, ver = {1}, language = {2}",
493494 formatMachineType(Compile2.Machine), Compile2.Version,
494495 formatSourceLanguage(Lang));
509510 AutoIndent Indent(P, 7);
510511 SourceLanguage Lang = static_cast(
511512 Compile3.Flags & CompileSym3Flags::SourceLanguageMask);
513 CompilationCPU = Compile3.Machine;
512514 P.formatLine("machine = {0}, Ver = {1}, language = {2}",
513515 formatMachineType(Compile3.Machine), Compile3.Version,
514516 formatSourceLanguage(Lang));
628630 FP.BytesOfCalleeSavedRegisters,
629631 formatSegmentOffset(FP.SectionIdOfExceptionHandler,
630632 FP.OffsetOfExceptionHandler));
633 P.formatLine("local fp reg = {0}, param fp reg = {1}",
634 formatRegisterId(FP.getLocalFPReg(CompilationCPU)),
635 formatRegisterId(FP.getParamFPReg(CompilationCPU)));
631636 P.formatLine("flags = {0}",
632637 formatFrameProcedureOptions(P.getIndentLevel() + 9, FP.Flags));
633638 return Error::success();
5252 std::string idIndex(codeview::TypeIndex TI) const;
5353
5454 LinePrinter &P;
55
56 /// Dumping certain records requires knowing what machine this is. The
57 /// S_COMPILE3 record will tell us, but if we don't see one, default to X64.
58 codeview::CPUType CompilationCPU = codeview::CPUType::X64;
59
5560 bool RecordBytes;
5661 const SymbolGroup *SymGroup = nullptr;
5762 codeview::LazyRandomTypeCollection &Ids;
6065 } // namespace pdb
6166 } // namespace llvm
6267
63 #endif
68 #endif
178178
179179 DebugStringTableSubsectionRef CVStringTable;
180180
181 /// Track the compilation CPU type. S_COMPILE3 symbol records typically come
182 /// first, but if we don't see one, just assume an X64 CPU type. It is common.
183 CPUType CompilationCPUType = CPUType::X64;
184
181185 ScopedPrinter &Writer;
182186 BinaryByteStream TypeContents;
183187 LazyRandomTypeCollection Types;
11491153 auto CODD = llvm::make_unique(*this, Section, Obj,
11501154 SectionContents);
11511155 CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD),
1152 opts::CodeViewSubsectionBytes);
1156 CompilationCPUType, opts::CodeViewSubsectionBytes);
11531157 CVSymbolArray Symbols;
11541158 BinaryStreamReader Reader(BinaryData, llvm::support::little);
11551159 if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
11621166 W.flush();
11631167 error(std::move(EC));
11641168 }
1169 CompilationCPUType = CVSD.getCompilationCPUType();
11651170 W.flush();
11661171 }
11671172