mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-04 11:17:31 +00:00
[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:
parent
7bc655bc82
commit
5139ea485d
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user