[PDB] Write FPO Data to the PDB.
llvm-svn: 342003
diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
index 1e329c7..f74120a 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
@@ -26,11 +26,12 @@
}
Error initialize(BinaryStreamReader Reader);
+ Error initialize(BinaryStreamRef Stream);
FixedStreamArray<FrameData>::Iterator begin() const { return Frames.begin(); }
FixedStreamArray<FrameData>::Iterator end() const { return Frames.end(); }
- const void *getRelocPtr() const { return RelocPtr; }
+ const uint32_t *getRelocPtr() const { return RelocPtr; }
private:
const uint32_t *RelocPtr = nullptr;
@@ -39,8 +40,9 @@
class DebugFrameDataSubsection final : public DebugSubsection {
public:
- DebugFrameDataSubsection()
- : DebugSubsection(DebugSubsectionKind::FrameData) {}
+ DebugFrameDataSubsection(bool IncludeRelocPtr)
+ : DebugSubsection(DebugSubsectionKind::FrameData),
+ IncludeRelocPtr(IncludeRelocPtr) {}
static bool classof(const DebugSubsection *S) {
return S->kind() == DebugSubsectionKind::FrameData;
}
@@ -52,6 +54,7 @@
void setFrames(ArrayRef<FrameData> Frames);
private:
+ bool IncludeRelocPtr = false;
std::vector<FrameData> Frames;
};
}
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index 51befcd..826e0c1 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -15,6 +15,7 @@
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Support/Error.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
@@ -24,6 +25,9 @@
#include "llvm/Support/Endian.h"
namespace llvm {
+namespace codeview {
+struct FrameData;
+}
namespace msf {
class MSFBuilder;
}
@@ -65,6 +69,7 @@
void setGlobalsStreamIndex(uint32_t Index);
void setPublicsStreamIndex(uint32_t Index);
void setSymbolRecordStreamIndex(uint32_t Index);
+ void addFrameData(const codeview::FrameData &FD);
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
@@ -84,7 +89,8 @@
private:
struct DebugStream {
- ArrayRef<uint8_t> Data;
+ std::function<Error(BinaryStreamWriter &)> WriteFn;
+ uint32_t Size = 0;
uint16_t StreamNumber = kInvalidStreamIndex;
};
@@ -117,6 +123,8 @@
std::vector<std::unique_ptr<DbiModuleDescriptorBuilder>> ModiList;
+ Optional<codeview::DebugFrameDataSubsection> FrameData;
+
StringMap<uint32_t> SourceFileNames;
PDBStringTableBuilder ECNamesBuilder;
diff --git a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
index fd558aa..5881bf1 100644
--- a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
+++ b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
@@ -14,8 +14,11 @@
using namespace llvm::codeview;
Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) {
- if (auto EC = Reader.readObject(RelocPtr))
- return EC;
+ if (Reader.bytesRemaining() % sizeof(FrameData) != 0) {
+ if (auto EC = Reader.readObject(RelocPtr))
+ return EC;
+ }
+
if (Reader.bytesRemaining() % sizeof(FrameData) != 0)
return make_error<CodeViewError>(cv_error_code::corrupt_record,
"Invalid frame data record format!");
@@ -26,15 +29,30 @@
return Error::success();
}
+Error DebugFrameDataSubsectionRef::initialize(BinaryStreamRef Section) {
+ BinaryStreamReader Reader(Section);
+ return initialize(Reader);
+}
+
uint32_t DebugFrameDataSubsection::calculateSerializedSize() const {
- return 4 + sizeof(FrameData) * Frames.size();
+ uint32_t Size = sizeof(FrameData) * Frames.size();
+ if (IncludeRelocPtr)
+ Size += sizeof(uint32_t);
+ return Size;
}
Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const {
- if (auto EC = Writer.writeInteger<uint32_t>(0))
- return EC;
+ if (IncludeRelocPtr) {
+ if (auto EC = Writer.writeInteger<uint32_t>(0))
+ return EC;
+ }
- if (auto EC = Writer.writeArray(makeArrayRef(Frames)))
+ std::vector<FrameData> SortedFrames(Frames.begin(), Frames.end());
+ std::sort(SortedFrames.begin(), SortedFrames.end(),
+ [](const FrameData &LHS, const FrameData &RHS) {
+ return LHS.RvaStart < RHS.RvaStart;
+ });
+ if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames)))
return EC;
return Error::success();
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index f6043bf..9b045f9 100644
--- a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
@@ -74,10 +75,23 @@
PublicsStreamIndex = Index;
}
+void DbiStreamBuilder::addFrameData(const codeview::FrameData &FD) {
+ if (!FrameData.hasValue())
+ FrameData.emplace(false);
+
+ FrameData->addFrameData(FD);
+}
+
Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
ArrayRef<uint8_t> Data) {
+ assert(Type != DbgHeaderType::NewFPO &&
+ "NewFPO data should be written via addFrameData()!");
+
DbgStreams[(int)Type].emplace();
- DbgStreams[(int)Type]->Data = Data;
+ DbgStreams[(int)Type]->Size = Data.size();
+ DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
+ return Writer.writeArray(Data);
+ };
return Error::success();
}
@@ -272,10 +286,20 @@
}
Error DbiStreamBuilder::finalizeMsfLayout() {
+ if (FrameData.hasValue()) {
+ DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
+ DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
+ FrameData->calculateSerializedSize();
+ DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
+ [this](BinaryStreamWriter &Writer) {
+ return FrameData->commit(Writer);
+ };
+ }
+
for (auto &S : DbgStreams) {
if (!S.hasValue())
continue;
- auto ExpectedIndex = Msf.addStream(S->Data.size());
+ auto ExpectedIndex = Msf.addStream(S->Size);
if (!ExpectedIndex)
return ExpectedIndex.takeError();
S->StreamNumber = *ExpectedIndex;
@@ -406,7 +430,8 @@
auto WritableStream = WritableMappedBlockStream::createIndexedStream(
Layout, MsfBuffer, Stream->StreamNumber, Allocator);
BinaryStreamWriter DbgStreamWriter(*WritableStream);
- if (auto EC = DbgStreamWriter.writeArray(Stream->Data))
+
+ if (auto EC = Stream->WriteFn(DbgStreamWriter))
return EC;
}
diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
index 6debd8a..4deeae8 100644
--- a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
+++ b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
@@ -511,7 +511,7 @@
const codeview::StringsAndChecksums &SC) const {
assert(SC.hasStrings());
- auto Result = std::make_shared<DebugFrameDataSubsection>();
+ auto Result = std::make_shared<DebugFrameDataSubsection>(true);
for (const auto &YF : Frames) {
codeview::FrameData F;
F.CodeSize = YF.CodeSize;
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index c628b14..60f79f0 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -22,6 +22,7 @@
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
@@ -142,6 +143,11 @@
return EC;
}
+ if (opts::dump::DumpFpo) {
+ if (auto EC = dumpFpo())
+ return EC;
+ }
+
if (File.isObj()) {
if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() ||
opts::dump::DumpTypeExtras)
@@ -985,6 +991,58 @@
return Error::success();
}
+Error DumpOutputStyle::dumpFpo() {
+ printHeader(P, "New FPO Data");
+
+ if (!File.isPdb()) {
+ printStreamNotValidForObj();
+ return Error::success();
+ }
+
+ PDBFile &File = getPdb();
+ if (!File.hasPDBDbiStream()) {
+ printStreamNotPresent("DBI");
+ return Error::success();
+ }
+
+ ExitOnError Err("Error dumping fpo data:");
+
+ auto &Dbi = Err(File.getPDBDbiStream());
+
+ uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO);
+ if (Index == kInvalidStreamIndex) {
+ printStreamNotPresent("New FPO");
+ return Error::success();
+ }
+
+ std::unique_ptr<MappedBlockStream> NewFpo = File.createIndexedStream(Index);
+
+ DebugFrameDataSubsectionRef FDS;
+ if (auto EC = FDS.initialize(*NewFpo))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid new fpo stream");
+
+ P.printLine(" RVA | Code | Locals | Params | Stack | Prolog | Saved Regs "
+ "| Has SEH | Has C++EH | Start | Program");
+ for (const FrameData &FD : FDS) {
+ bool IsFuncStart = FD.Flags & FrameData::IsFunctionStart;
+ bool HasEH = FD.Flags & FrameData::HasEH;
+ bool HasSEH = FD.Flags & FrameData::HasSEH;
+
+ auto &StringTable = Err(File.getStringTable());
+
+ auto Program = Err(StringTable.getStringForID(FD.FrameFunc));
+ P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,5} | {5,6} | {6,10} | "
+ "{7,7} | {8,9} | {9,5} | {10}",
+ uint32_t(FD.RvaStart), uint32_t(FD.CodeSize),
+ uint32_t(FD.LocalSize), uint32_t(FD.ParamsSize),
+ uint32_t(FD.MaxStackSize), uint16_t(FD.PrologSize),
+ uint16_t(FD.SavedRegsSize), HasSEH, HasEH, IsFuncStart,
+ Program);
+ }
+ return Error::success();
+}
+
Error DumpOutputStyle::dumpStringTableFromPdb() {
AutoIndent Indent(P);
auto IS = getPdb().getStringTable();
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
index 5232a07..946a305 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -85,6 +85,7 @@
Error dumpInlineeLines();
Error dumpXmi();
Error dumpXme();
+ Error dumpFpo();
Error dumpTpiStream(uint32_t StreamIdx);
Error dumpTypesFromObjectFile();
Error dumpModules();
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 0a4fb49..7c34cc6 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -501,6 +501,9 @@
cl::desc("dump CodeView symbol record raw bytes"),
cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+
// MODULE & FILE OPTIONS
cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
cl::cat(FileOptions), cl::sub(DumpSubcommand));
@@ -1372,6 +1375,7 @@
if (opts::DumpSubcommand) {
if (opts::dump::RawAll) {
opts::dump::DumpGlobals = true;
+ opts::dump::DumpFpo = true;
opts::dump::DumpInlineeLines = true;
opts::dump::DumpIds = true;
opts::dump::DumpIdExtras = true;
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
index 7496ada..1524f83 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -171,6 +171,7 @@
extern llvm::cl::opt<bool> DumpSectionMap;
extern llvm::cl::opt<bool> DumpModules;
extern llvm::cl::opt<bool> DumpModuleFiles;
+extern llvm::cl::opt<bool> DumpFpo;
extern llvm::cl::opt<bool> RawAll;
}