llvm.org GIT mirror llvm / 69d3b58
[PDB] Emit old fpo data to the PDB file. r342003 added support for emitting FPO data from the DEBUG_S_FRAMEDATA subsection of the .debug$S section to the PDB file. However, that is not the end of the story. FPO can end up in two different destinations in a PDB, each corresponding to a different FPO data source. The case handled by r342003 involves copying data from the DEBUG_S_FRAMEDATA subsection of the .debug$S section to the "New FPO" stream in the PDB, which is then referred to by the DBI stream. The case handled by this patch involves copying records from the .debug$F section of an object file to the "FPO" stream (or perhaps more aptly, the "Old FPO" stream) in the PDB file, which is also referred to by the DBI stream. The formats are largely similar, and the difference is mostly only visible in masm generated object files, such as some of the low-level CRT object files like memcpy. MASM doesn't appear to support writing the DEBUG_S_FRAMEDATA subsection, and instead just writes these records to the .debug$F section. Although clang-cl does not emit a .debug$F section ever, lld still needs to support it so we have good debugging for CRT functions. Differential Revision: https://reviews.llvm.org/D51958 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@342080 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 8 days ago
5 changed file(s) with 99 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
3232 }
3333 namespace object {
3434 struct coff_section;
35 struct FpoData;
3536 }
3637 namespace pdb {
3738 class DbiStream;
6869 void setGlobalsStreamIndex(uint32_t Index);
6970 void setPublicsStreamIndex(uint32_t Index);
7071 void setSymbolRecordStreamIndex(uint32_t Index);
71 void addFrameData(const codeview::FrameData &FD);
72 void addNewFpoData(const codeview::FrameData &FD);
73 void addOldFpoData(const object::FpoData &Fpo);
7274
7375 Expected addModuleInfo(StringRef ModuleName);
7476 Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
122124
123125 std::vector> ModiList;
124126
125 Optional FrameData;
127 Optional NewFpoData;
128 std::vector OldFpoData;
126129
127130 StringMap SourceFileNames;
128131
593593 FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes
594594 };
595595
596 enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 };
597
596598 struct coff_load_config_code_integrity {
597599 support::ulittle16_t Flags;
598600 support::ulittle16_t Catalog;
12271229 bool useBP() const { return (Attributes >> 10) & 1; }
12281230
12291231 // cbFrame: frame pointer
1230 int getFP() const { return Attributes >> 14; }
1232 frame_type getFP() const { return static_cast(Attributes >> 14); }
12311233 };
12321234
12331235 } // end namespace object
7474 PublicsStreamIndex = Index;
7575 }
7676
77 void DbiStreamBuilder::addFrameData(const codeview::FrameData &FD) {
78 if (!FrameData.hasValue())
79 FrameData.emplace(false);
80
81 FrameData->addFrameData(FD);
77 void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) {
78 if (!NewFpoData.hasValue())
79 NewFpoData.emplace(false);
80
81 NewFpoData->addFrameData(FD);
82 }
83
84 void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) {
85 OldFpoData.push_back(FD);
8286 }
8387
8488 Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
285289 }
286290
287291 Error DbiStreamBuilder::finalizeMsfLayout() {
288 if (FrameData.hasValue()) {
292 if (NewFpoData.hasValue()) {
289293 DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
290294 DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
291 FrameData->calculateSerializedSize();
295 NewFpoData->calculateSerializedSize();
292296 DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
293297 [this](BinaryStreamWriter &Writer) {
294 return FrameData->commit(Writer);
298 return NewFpoData->commit(Writer);
299 };
300 }
301
302 if (!OldFpoData.empty()) {
303 DbgStreams[(int)DbgHeaderType::FPO].emplace();
304 DbgStreams[(int)DbgHeaderType::FPO]->Size =
305 sizeof(object::FpoData) * OldFpoData.size();
306 DbgStreams[(int)DbgHeaderType::FPO]->WriteFn =
307 [this](BinaryStreamWriter &Writer) {
308 return Writer.writeArray(makeArrayRef(OldFpoData));
295309 };
296310 }
297311
990990 return Error::success();
991991 }
992992
993 Error DumpOutputStyle::dumpFpo() {
993 std::string formatFrameType(object::frame_type FT) {
994 switch (FT) {
995 case object::frame_type::Fpo:
996 return "FPO";
997 case object::frame_type::NonFpo:
998 return "Non-FPO";
999 case object::frame_type::Trap:
1000 return "Trap";
1001 case object::frame_type::Tss:
1002 return "TSS";
1003 }
1004 return "";
1005 }
1006
1007 Error DumpOutputStyle::dumpOldFpo(PDBFile &File) {
1008 printHeader(P, "Old FPO Data");
1009
1010 ExitOnError Err("Error dumping old fpo data:");
1011 auto &Dbi = Err(File.getPDBDbiStream());
1012
1013 uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::FPO);
1014 if (Index == kInvalidStreamIndex) {
1015 printStreamNotPresent("FPO");
1016 return Error::success();
1017 }
1018
1019 std::unique_ptr OldFpo = File.createIndexedStream(Index);
1020 BinaryStreamReader Reader(*OldFpo);
1021 FixedStreamArray Records;
1022 Err(Reader.readArray(Records,
1023 Reader.bytesRemaining() / sizeof(object::FpoData)));
1024
1025 P.printLine(" RVA | Code | Locals | Params | Prolog | Saved Regs | Use "
1026 "BP | Has SEH | Frame Type");
1027
1028 for (const object::FpoData &FD : Records) {
1029 P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,6} | {5,10} | {6,6} | "
1030 "{7,7} | {8,9}",
1031 uint32_t(FD.Offset), uint32_t(FD.Size), uint32_t(FD.NumLocals),
1032 uint32_t(FD.NumParams), FD.getPrologSize(),
1033 FD.getNumSavedRegs(), FD.useBP(), FD.hasSEH(),
1034 formatFrameType(FD.getFP()));
1035 }
1036 return Error::success();
1037 }
1038
1039 Error DumpOutputStyle::dumpNewFpo(PDBFile &File) {
9941040 printHeader(P, "New FPO Data");
9951041
996 if (!File.isPdb()) {
997 printStreamNotValidForObj();
998 return Error::success();
999 }
1000
1001 PDBFile &File = getPdb();
1002 if (!File.hasPDBDbiStream()) {
1003 printStreamNotPresent("DBI");
1004 return Error::success();
1005 }
1006
1007 ExitOnError Err("Error dumping fpo data:");
1008
1042 ExitOnError Err("Error dumping new fpo data:");
10091043 auto &Dbi = Err(File.getPDBDbiStream());
10101044
10111045 uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO);
10391073 uint16_t(FD.SavedRegsSize), HasSEH, HasEH, IsFuncStart,
10401074 Program);
10411075 }
1076 return Error::success();
1077 }
1078
1079 Error DumpOutputStyle::dumpFpo() {
1080 if (!File.isPdb()) {
1081 printStreamNotValidForObj();
1082 return Error::success();
1083 }
1084
1085 PDBFile &File = getPdb();
1086 if (!File.hasPDBDbiStream()) {
1087 printStreamNotPresent("DBI");
1088 return Error::success();
1089 }
1090
1091 if (auto EC = dumpOldFpo(File))
1092 return EC;
1093 if (auto EC = dumpNewFpo(File))
1094 return EC;
10421095 return Error::success();
10431096 }
10441097
8585 Error dumpXmi();
8686 Error dumpXme();
8787 Error dumpFpo();
88 Error dumpOldFpo(PDBFile &File);
89 Error dumpNewFpo(PDBFile &File);
8890 Error dumpTpiStream(uint32_t StreamIdx);
8991 Error dumpTypesFromObjectFile();
9092 Error dumpModules();