mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
6931521bfe
This is the first step towards round-tripping symbol information, and thusly being able to write symbol information to a PDB. This patch writes the symbol information for each compiland to the Yaml when running in pdb2yaml mode. There's still some loose ends, such as what to do about relocations (necessary in order to print linkage names), how to print enums with friendly names, and how to give the dumper access to the StringTable, but this is a good first start. llvm-svn: 283641
232 lines
6.6 KiB
C++
232 lines
6.6 KiB
C++
//===- YAMLOutputStyle.cpp ------------------------------------ *- C++ --*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "YAMLOutputStyle.h"
|
|
|
|
#include "PdbYaml.h"
|
|
#include "llvm-pdbdump.h"
|
|
|
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
|
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
|
|
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
|
|
#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
|
|
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
|
|
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
|
|
#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::pdb;
|
|
|
|
YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
|
|
: File(File), Out(outs()), Obj(File.getAllocator()) {}
|
|
|
|
Error YAMLOutputStyle::dump() {
|
|
if (opts::pdb2yaml::StreamDirectory)
|
|
opts::pdb2yaml::StreamMetadata = true;
|
|
if (opts::pdb2yaml::DbiModuleSyms)
|
|
opts::pdb2yaml::DbiModuleInfo = true;
|
|
if (opts::pdb2yaml::DbiModuleSourceFileInfo)
|
|
opts::pdb2yaml::DbiModuleInfo = true;
|
|
if (opts::pdb2yaml::DbiModuleInfo)
|
|
opts::pdb2yaml::DbiStream = true;
|
|
|
|
if (auto EC = dumpFileHeaders())
|
|
return EC;
|
|
|
|
if (auto EC = dumpStreamMetadata())
|
|
return EC;
|
|
|
|
if (auto EC = dumpStreamDirectory())
|
|
return EC;
|
|
|
|
if (auto EC = dumpPDBStream())
|
|
return EC;
|
|
|
|
if (auto EC = dumpDbiStream())
|
|
return EC;
|
|
|
|
if (auto EC = dumpTpiStream())
|
|
return EC;
|
|
|
|
if (auto EC = dumpIpiStream())
|
|
return EC;
|
|
|
|
flush();
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpFileHeaders() {
|
|
if (opts::pdb2yaml::NoFileHeaders)
|
|
return Error::success();
|
|
|
|
yaml::MSFHeaders Headers;
|
|
Obj.Headers.emplace();
|
|
Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();
|
|
Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();
|
|
Obj.Headers->SuperBlock.BlockSize = File.getBlockSize();
|
|
auto Blocks = File.getDirectoryBlockArray();
|
|
Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end());
|
|
Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks();
|
|
Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes();
|
|
Obj.Headers->NumStreams =
|
|
opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0;
|
|
Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock();
|
|
Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1();
|
|
Obj.Headers->FileSize = File.getFileSize();
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpStreamMetadata() {
|
|
if (!opts::pdb2yaml::StreamMetadata)
|
|
return Error::success();
|
|
|
|
Obj.StreamSizes.emplace();
|
|
Obj.StreamSizes->assign(File.getStreamSizes().begin(),
|
|
File.getStreamSizes().end());
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpStreamDirectory() {
|
|
if (!opts::pdb2yaml::StreamDirectory)
|
|
return Error::success();
|
|
|
|
auto StreamMap = File.getStreamMap();
|
|
Obj.StreamMap.emplace();
|
|
for (auto &Stream : StreamMap) {
|
|
pdb::yaml::StreamBlockList BlockList;
|
|
BlockList.Blocks.assign(Stream.begin(), Stream.end());
|
|
Obj.StreamMap->push_back(BlockList);
|
|
}
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpPDBStream() {
|
|
if (!opts::pdb2yaml::PdbStream)
|
|
return Error::success();
|
|
|
|
auto IS = File.getPDBInfoStream();
|
|
if (!IS)
|
|
return IS.takeError();
|
|
|
|
auto &InfoS = IS.get();
|
|
Obj.PdbStream.emplace();
|
|
Obj.PdbStream->Age = InfoS.getAge();
|
|
Obj.PdbStream->Guid = InfoS.getGuid();
|
|
Obj.PdbStream->Signature = InfoS.getSignature();
|
|
Obj.PdbStream->Version = InfoS.getVersion();
|
|
for (auto &NS : InfoS.named_streams()) {
|
|
yaml::NamedStreamMapping Mapping;
|
|
Mapping.StreamName = NS.getKey();
|
|
Mapping.StreamNumber = NS.getValue();
|
|
Obj.PdbStream->NamedStreams.push_back(Mapping);
|
|
}
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpDbiStream() {
|
|
if (!opts::pdb2yaml::DbiStream)
|
|
return Error::success();
|
|
|
|
auto DbiS = File.getPDBDbiStream();
|
|
if (!DbiS)
|
|
return DbiS.takeError();
|
|
|
|
auto &DS = DbiS.get();
|
|
Obj.DbiStream.emplace();
|
|
Obj.DbiStream->Age = DS.getAge();
|
|
Obj.DbiStream->BuildNumber = DS.getBuildNumber();
|
|
Obj.DbiStream->Flags = DS.getFlags();
|
|
Obj.DbiStream->MachineType = DS.getMachineType();
|
|
Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
|
|
Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
|
|
Obj.DbiStream->VerHeader = DS.getDbiVersion();
|
|
if (opts::pdb2yaml::DbiModuleInfo) {
|
|
for (const auto &MI : DS.modules()) {
|
|
yaml::PdbDbiModuleInfo DMI;
|
|
DMI.Mod = MI.Info.getModuleName();
|
|
DMI.Obj = MI.Info.getObjFileName();
|
|
if (opts::pdb2yaml::DbiModuleSourceFileInfo)
|
|
DMI.SourceFiles = MI.SourceFiles;
|
|
|
|
if (opts::pdb2yaml::DbiModuleSyms &&
|
|
MI.Info.getModuleStreamIndex() != kInvalidStreamIndex) {
|
|
DMI.Modi.emplace();
|
|
auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
|
|
File.getMsfLayout(), File.getMsfBuffer(),
|
|
MI.Info.getModuleStreamIndex());
|
|
|
|
pdb::ModStream ModS(MI.Info, std::move(ModStreamData));
|
|
if (auto EC = ModS.reload())
|
|
return EC;
|
|
|
|
DMI.Modi->Signature = ModS.signature();
|
|
bool HadError = false;
|
|
for (auto &Sym : ModS.symbols(&HadError)) {
|
|
pdb::yaml::PdbSymbolRecord Record{Sym};
|
|
DMI.Modi->Symbols.push_back(Record);
|
|
}
|
|
}
|
|
Obj.DbiStream->ModInfos.push_back(DMI);
|
|
}
|
|
}
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpTpiStream() {
|
|
if (!opts::pdb2yaml::TpiStream)
|
|
return Error::success();
|
|
|
|
auto TpiS = File.getPDBTpiStream();
|
|
if (!TpiS)
|
|
return TpiS.takeError();
|
|
|
|
auto &TS = TpiS.get();
|
|
Obj.TpiStream.emplace();
|
|
Obj.TpiStream->Version = TS.getTpiVersion();
|
|
for (auto &Record : TS.types(nullptr)) {
|
|
yaml::PdbTpiRecord R;
|
|
// It's not necessary to set R.RecordData here. That only exists as a
|
|
// way to have the `PdbTpiRecord` structure own the memory that `R.Record`
|
|
// references. In the case of reading an existing PDB though, that memory
|
|
// is owned by the backing stream.
|
|
R.Record = Record;
|
|
Obj.TpiStream->Records.push_back(R);
|
|
}
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error YAMLOutputStyle::dumpIpiStream() {
|
|
if (!opts::pdb2yaml::IpiStream)
|
|
return Error::success();
|
|
|
|
auto IpiS = File.getPDBIpiStream();
|
|
if (!IpiS)
|
|
return IpiS.takeError();
|
|
|
|
auto &IS = IpiS.get();
|
|
Obj.IpiStream.emplace();
|
|
Obj.IpiStream->Version = IS.getTpiVersion();
|
|
for (auto &Record : IS.types(nullptr)) {
|
|
yaml::PdbTpiRecord R;
|
|
R.Record = Record;
|
|
Obj.IpiStream->Records.push_back(R);
|
|
}
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
void YAMLOutputStyle::flush() {
|
|
Out << Obj;
|
|
outs().flush();
|
|
}
|