Path: blob/main/contrib/llvm-project/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp
35259 views
//===- YAMLOutputStyle.cpp ------------------------------------ *- C++ --*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "YAMLOutputStyle.h"910#include "PdbYaml.h"11#include "llvm-pdbutil.h"1213#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"14#include "llvm/DebugInfo/CodeView/DebugSubsection.h"15#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"16#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"17#include "llvm/DebugInfo/MSF/MappedBlockStream.h"18#include "llvm/DebugInfo/PDB/Native/DbiStream.h"19#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"20#include "llvm/DebugInfo/PDB/Native/InfoStream.h"21#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"22#include "llvm/DebugInfo/PDB/Native/PDBFile.h"23#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"24#include "llvm/DebugInfo/PDB/Native/RawConstants.h"25#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"26#include "llvm/DebugInfo/PDB/Native/TpiStream.h"2728using namespace llvm;29using namespace llvm::codeview;30using namespace llvm::pdb;3132static bool checkModuleSubsection(opts::ModuleSubsection MS) {33return any_of(opts::pdb2yaml::DumpModuleSubsections,34[=](opts::ModuleSubsection M) {35return M == MS || M == opts::ModuleSubsection::All;36});37}3839YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)40: File(File), Out(outs()), Obj(File.getAllocator()) {41Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal);42}4344Error YAMLOutputStyle::dump() {45if (opts::pdb2yaml::StreamDirectory)46opts::pdb2yaml::StreamMetadata = true;4748if (auto EC = dumpFileHeaders())49return EC;5051if (auto EC = dumpStreamMetadata())52return EC;5354if (auto EC = dumpStreamDirectory())55return EC;5657if (auto EC = dumpStringTable())58return EC;5960if (auto EC = dumpPDBStream())61return EC;6263if (auto EC = dumpDbiStream())64return EC;6566if (auto EC = dumpTpiStream())67return EC;6869if (auto EC = dumpIpiStream())70return EC;7172if (auto EC = dumpPublics())73return EC;7475flush();76return Error::success();77}787980Error YAMLOutputStyle::dumpFileHeaders() {81if (opts::pdb2yaml::NoFileHeaders)82return Error::success();8384yaml::MSFHeaders Headers;85Obj.Headers.emplace();86Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();87Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();88Obj.Headers->SuperBlock.BlockSize = File.getBlockSize();89auto Blocks = File.getDirectoryBlockArray();90Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end());91Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks();92Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes();93Obj.Headers->NumStreams =94opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0;95Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock();96Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1();97Obj.Headers->FileSize = File.getFileSize();9899return Error::success();100}101102Error YAMLOutputStyle::dumpStringTable() {103bool RequiresStringTable = opts::pdb2yaml::DumpModuleFiles ||104!opts::pdb2yaml::DumpModuleSubsections.empty();105bool RequestedStringTable = opts::pdb2yaml::StringTable;106if (!RequiresStringTable && !RequestedStringTable)107return Error::success();108109auto ExpectedST = File.getStringTable();110if (!ExpectedST)111return ExpectedST.takeError();112113Obj.StringTable.emplace();114const auto &ST = ExpectedST.get();115for (auto ID : ST.name_ids()) {116auto S = ST.getStringForID(ID);117if (!S)118return S.takeError();119if (S->empty())120continue;121Obj.StringTable->push_back(*S);122}123return Error::success();124}125126Error YAMLOutputStyle::dumpStreamMetadata() {127if (!opts::pdb2yaml::StreamMetadata)128return Error::success();129130Obj.StreamSizes.emplace();131Obj.StreamSizes->assign(File.getStreamSizes().begin(),132File.getStreamSizes().end());133return Error::success();134}135136Error YAMLOutputStyle::dumpStreamDirectory() {137if (!opts::pdb2yaml::StreamDirectory)138return Error::success();139140auto StreamMap = File.getStreamMap();141Obj.StreamMap.emplace();142for (auto &Stream : StreamMap) {143pdb::yaml::StreamBlockList BlockList;144BlockList.Blocks.assign(Stream.begin(), Stream.end());145Obj.StreamMap->push_back(BlockList);146}147148return Error::success();149}150151Error YAMLOutputStyle::dumpPDBStream() {152if (!opts::pdb2yaml::PdbStream)153return Error::success();154155auto IS = File.getPDBInfoStream();156if (!IS)157return IS.takeError();158159auto &InfoS = IS.get();160Obj.PdbStream.emplace();161Obj.PdbStream->Age = InfoS.getAge();162Obj.PdbStream->Guid = InfoS.getGuid();163Obj.PdbStream->Signature = InfoS.getSignature();164Obj.PdbStream->Version = InfoS.getVersion();165Obj.PdbStream->Features = InfoS.getFeatureSignatures();166167return Error::success();168}169170static opts::ModuleSubsection convertSubsectionKind(DebugSubsectionKind K) {171switch (K) {172case DebugSubsectionKind::CrossScopeExports:173return opts::ModuleSubsection::CrossScopeExports;174case DebugSubsectionKind::CrossScopeImports:175return opts::ModuleSubsection::CrossScopeImports;176case DebugSubsectionKind::FileChecksums:177return opts::ModuleSubsection::FileChecksums;178case DebugSubsectionKind::InlineeLines:179return opts::ModuleSubsection::InlineeLines;180case DebugSubsectionKind::Lines:181return opts::ModuleSubsection::Lines;182case DebugSubsectionKind::Symbols:183return opts::ModuleSubsection::Symbols;184case DebugSubsectionKind::StringTable:185return opts::ModuleSubsection::StringTable;186case DebugSubsectionKind::FrameData:187return opts::ModuleSubsection::FrameData;188default:189return opts::ModuleSubsection::Unknown;190}191llvm_unreachable("Unreachable!");192}193194Error YAMLOutputStyle::dumpDbiStream() {195if (!opts::pdb2yaml::DbiStream)196return Error::success();197198if (!File.hasPDBDbiStream())199return Error::success();200201auto DbiS = File.getPDBDbiStream();202if (!DbiS)203return DbiS.takeError();204205auto &DS = DbiS.get();206Obj.DbiStream.emplace();207Obj.DbiStream->Age = DS.getAge();208Obj.DbiStream->BuildNumber = DS.getBuildNumber();209Obj.DbiStream->Flags = DS.getFlags();210Obj.DbiStream->MachineType = DS.getMachineType();211Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();212Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();213Obj.DbiStream->VerHeader = DS.getDbiVersion();214if (opts::pdb2yaml::DumpModules) {215const auto &Modules = DS.modules();216for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {217DbiModuleDescriptor MI = Modules.getModuleDescriptor(I);218219Obj.DbiStream->ModInfos.emplace_back();220yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back();221222DMI.Mod = MI.getModuleName();223DMI.Obj = MI.getObjFileName();224if (opts::pdb2yaml::DumpModuleFiles) {225auto Files = Modules.source_files(I);226DMI.SourceFiles.assign(Files.begin(), Files.end());227}228229uint16_t ModiStream = MI.getModuleStreamIndex();230if (ModiStream == kInvalidStreamIndex)231continue;232233auto ModStreamData = File.createIndexedStream(ModiStream);234pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData));235if (auto EC = ModS.reload())236return EC;237238auto ExpectedST = File.getStringTable();239if (!ExpectedST)240return ExpectedST.takeError();241if (!opts::pdb2yaml::DumpModuleSubsections.empty() &&242ModS.hasDebugSubsections()) {243auto ExpectedChecksums = ModS.findChecksumsSubsection();244if (!ExpectedChecksums)245return ExpectedChecksums.takeError();246247StringsAndChecksumsRef SC(ExpectedST->getStringTable(),248*ExpectedChecksums);249250for (const auto &SS : ModS.subsections()) {251opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind());252if (!checkModuleSubsection(OptionKind))253continue;254255auto Converted =256CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(SC, SS);257if (!Converted)258return Converted.takeError();259DMI.Subsections.push_back(*Converted);260}261}262263if (opts::pdb2yaml::DumpModuleSyms) {264DMI.Modi.emplace();265266DMI.Modi->Signature = ModS.signature();267bool HadError = false;268for (auto &Sym : ModS.symbols(&HadError)) {269auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);270if (!ES)271return ES.takeError();272273DMI.Modi->Symbols.push_back(*ES);274}275}276}277}278return Error::success();279}280281Error YAMLOutputStyle::dumpTpiStream() {282if (!opts::pdb2yaml::TpiStream)283return Error::success();284285auto TpiS = File.getPDBTpiStream();286if (!TpiS)287return TpiS.takeError();288289auto &TS = TpiS.get();290Obj.TpiStream.emplace();291Obj.TpiStream->Version = TS.getTpiVersion();292for (auto &Record : TS.types(nullptr)) {293auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);294if (!ExpectedRecord)295return ExpectedRecord.takeError();296Obj.TpiStream->Records.push_back(*ExpectedRecord);297}298299return Error::success();300}301302Error YAMLOutputStyle::dumpIpiStream() {303if (!opts::pdb2yaml::IpiStream)304return Error::success();305306auto InfoS = File.getPDBInfoStream();307if (!InfoS)308return InfoS.takeError();309if (!InfoS->containsIdStream())310return Error::success();311312auto IpiS = File.getPDBIpiStream();313if (!IpiS)314return IpiS.takeError();315316auto &IS = IpiS.get();317Obj.IpiStream.emplace();318Obj.IpiStream->Version = IS.getTpiVersion();319for (auto &Record : IS.types(nullptr)) {320auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);321if (!ExpectedRecord)322return ExpectedRecord.takeError();323324Obj.IpiStream->Records.push_back(*ExpectedRecord);325}326327return Error::success();328}329330Error YAMLOutputStyle::dumpPublics() {331if (!opts::pdb2yaml::PublicsStream)332return Error::success();333334Obj.PublicsStream.emplace();335auto ExpectedPublics = File.getPDBPublicsStream();336if (!ExpectedPublics) {337llvm::consumeError(ExpectedPublics.takeError());338return Error::success();339}340341PublicsStream &Publics = *ExpectedPublics;342const GSIHashTable &PublicsTable = Publics.getPublicsTable();343344auto ExpectedSyms = File.getPDBSymbolStream();345if (!ExpectedSyms) {346llvm::consumeError(ExpectedSyms.takeError());347return Error::success();348}349350BinaryStreamRef SymStream =351ExpectedSyms->getSymbolArray().getUnderlyingStream();352for (uint32_t PubSymOff : PublicsTable) {353Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);354if (!Sym)355return Sym.takeError();356auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(*Sym);357if (!ES)358return ES.takeError();359360Obj.PublicsStream->PubSyms.push_back(*ES);361}362363return Error::success();364}365366void YAMLOutputStyle::flush() {367Out << Obj;368outs().flush();369}370371372