[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

llvm-svn: 342080
This commit is contained in:
Zachary Turner 2018-09-12 21:02:01 +00:00
parent 7bc655bc82
commit 5139ea485d
5 changed files with 98 additions and 24 deletions

View File

@ -33,6 +33,7 @@ class MSFBuilder;
}
namespace object {
struct coff_section;
struct FpoData;
}
namespace pdb {
class DbiStream;
@ -69,7 +70,8 @@ public:
void setGlobalsStreamIndex(uint32_t Index);
void setPublicsStreamIndex(uint32_t Index);
void setSymbolRecordStreamIndex(uint32_t Index);
void addFrameData(const codeview::FrameData &FD);
void addNewFpoData(const codeview::FrameData &FD);
void addOldFpoData(const object::FpoData &Fpo);
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
@ -123,7 +125,8 @@ private:
std::vector<std::unique_ptr<DbiModuleDescriptorBuilder>> ModiList;
Optional<codeview::DebugFrameDataSubsection> FrameData;
Optional<codeview::DebugFrameDataSubsection> NewFpoData;
std::vector<object::FpoData> OldFpoData;
StringMap<uint32_t> SourceFileNames;

View File

@ -594,6 +594,8 @@ enum class coff_guard_flags : uint32_t {
FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes
};
enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 };
struct coff_load_config_code_integrity {
support::ulittle16_t Flags;
support::ulittle16_t Catalog;
@ -1228,7 +1230,7 @@ struct FpoData {
bool useBP() const { return (Attributes >> 10) & 1; }
// cbFrame: frame pointer
int getFP() const { return Attributes >> 14; }
frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); }
};
} // end namespace object

View File

@ -75,11 +75,15 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
PublicsStreamIndex = Index;
}
void DbiStreamBuilder::addFrameData(const codeview::FrameData &FD) {
if (!FrameData.hasValue())
FrameData.emplace(false);
void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) {
if (!NewFpoData.hasValue())
NewFpoData.emplace(false);
FrameData->addFrameData(FD);
NewFpoData->addFrameData(FD);
}
void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) {
OldFpoData.push_back(FD);
}
Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
@ -286,13 +290,23 @@ Error DbiStreamBuilder::finalize() {
}
Error DbiStreamBuilder::finalizeMsfLayout() {
if (FrameData.hasValue()) {
if (NewFpoData.hasValue()) {
DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
FrameData->calculateSerializedSize();
NewFpoData->calculateSerializedSize();
DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
[this](BinaryStreamWriter &Writer) {
return FrameData->commit(Writer);
return NewFpoData->commit(Writer);
};
}
if (!OldFpoData.empty()) {
DbgStreams[(int)DbgHeaderType::FPO].emplace();
DbgStreams[(int)DbgHeaderType::FPO]->Size =
sizeof(object::FpoData) * OldFpoData.size();
DbgStreams[(int)DbgHeaderType::FPO]->WriteFn =
[this](BinaryStreamWriter &Writer) {
return Writer.writeArray(makeArrayRef(OldFpoData));
};
}

View File

@ -991,22 +991,56 @@ Error DumpOutputStyle::dumpXme() {
return Error::success();
}
Error DumpOutputStyle::dumpFpo() {
std::string formatFrameType(object::frame_type FT) {
switch (FT) {
case object::frame_type::Fpo:
return "FPO";
case object::frame_type::NonFpo:
return "Non-FPO";
case object::frame_type::Trap:
return "Trap";
case object::frame_type::Tss:
return "TSS";
}
return "<unknown>";
}
Error DumpOutputStyle::dumpOldFpo(PDBFile &File) {
printHeader(P, "Old FPO Data");
ExitOnError Err("Error dumping old fpo data:");
auto &Dbi = Err(File.getPDBDbiStream());
uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::FPO);
if (Index == kInvalidStreamIndex) {
printStreamNotPresent("FPO");
return Error::success();
}
std::unique_ptr<MappedBlockStream> OldFpo = File.createIndexedStream(Index);
BinaryStreamReader Reader(*OldFpo);
FixedStreamArray<object::FpoData> Records;
Err(Reader.readArray(Records,
Reader.bytesRemaining() / sizeof(object::FpoData)));
P.printLine(" RVA | Code | Locals | Params | Prolog | Saved Regs | Use "
"BP | Has SEH | Frame Type");
for (const object::FpoData &FD : Records) {
P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,6} | {5,10} | {6,6} | "
"{7,7} | {8,9}",
uint32_t(FD.Offset), uint32_t(FD.Size), uint32_t(FD.NumLocals),
uint32_t(FD.NumParams), FD.getPrologSize(),
FD.getNumSavedRegs(), FD.useBP(), FD.hasSEH(),
formatFrameType(FD.getFP()));
}
return Error::success();
}
Error DumpOutputStyle::dumpNewFpo(PDBFile &File) {
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:");
ExitOnError Err("Error dumping new fpo data:");
auto &Dbi = Err(File.getPDBDbiStream());
uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO);
@ -1043,6 +1077,25 @@ Error DumpOutputStyle::dumpFpo() {
return Error::success();
}
Error DumpOutputStyle::dumpFpo() {
if (!File.isPdb()) {
printStreamNotValidForObj();
return Error::success();
}
PDBFile &File = getPdb();
if (!File.hasPDBDbiStream()) {
printStreamNotPresent("DBI");
return Error::success();
}
if (auto EC = dumpOldFpo(File))
return EC;
if (auto EC = dumpNewFpo(File))
return EC;
return Error::success();
}
Error DumpOutputStyle::dumpStringTableFromPdb() {
AutoIndent Indent(P);
auto IS = getPdb().getStringTable();

View File

@ -86,6 +86,8 @@ private:
Error dumpXmi();
Error dumpXme();
Error dumpFpo();
Error dumpOldFpo(PDBFile &File);
Error dumpNewFpo(PDBFile &File);
Error dumpTpiStream(uint32_t StreamIdx);
Error dumpTypesFromObjectFile();
Error dumpModules();