feat: IPI & TPI stream merger.
This commit is contained in:
@@ -11,10 +11,7 @@ using namespace llvm::pdb;
|
||||
|
||||
namespace makepdb::binary {
|
||||
|
||||
PDB::PDB(COFF&& coff, SymbolData&& symbol_data)
|
||||
: m_owning_coff(std::move(coff)),
|
||||
m_owning_symbol_data(std::move(symbol_data)),
|
||||
m_builder(m_allocator) {
|
||||
PDB::PDB() : m_builder(m_allocator) {
|
||||
constexpr uint32_t block_size = 4096;
|
||||
if (m_builder.initialize(block_size)) {
|
||||
throw std::runtime_error("Failed to initialize pdb file builder.");
|
||||
@@ -25,8 +22,6 @@ PDB::PDB(COFF&& coff, SymbolData&& symbol_data)
|
||||
throw std::runtime_error("Failed to add initial stream.");
|
||||
}
|
||||
}
|
||||
|
||||
m_image_base = m_owning_coff.get_owning_coff().getImageBase();
|
||||
}
|
||||
|
||||
void PDB::write(std::string_view path) {
|
||||
@@ -46,18 +41,17 @@ void PDB::build() {
|
||||
}
|
||||
|
||||
void PDB::build_Info() {
|
||||
auto pdb_info = m_owning_coff.get_debug_info();
|
||||
auto& info_builder = m_builder.getInfoBuilder();
|
||||
auto pdb_info = m_owning_coff->get_debug_info();
|
||||
auto& Info = m_builder.getInfoBuilder();
|
||||
|
||||
info_builder.setVersion(PdbRaw_ImplVer::PdbImplVC70);
|
||||
info_builder.setAge(pdb_info.Age);
|
||||
info_builder.setGuid(*reinterpret_cast<codeview::GUID*>(pdb_info.Signature)
|
||||
);
|
||||
info_builder.addFeature(PdbRaw_FeatureSig::VC140);
|
||||
Info.setVersion(PdbRaw_ImplVer::PdbImplVC70);
|
||||
Info.setAge(pdb_info.Age);
|
||||
Info.setGuid(*reinterpret_cast<codeview::GUID*>(pdb_info.Signature));
|
||||
Info.addFeature(PdbRaw_FeatureSig::VC140);
|
||||
}
|
||||
|
||||
void PDB::build_DBI() {
|
||||
auto pdb_info = m_owning_coff.get_debug_info();
|
||||
auto pdb_info = m_owning_coff->get_debug_info();
|
||||
auto& DBI = m_builder.getDbiBuilder();
|
||||
|
||||
DBI.setVersionHeader(PdbRaw_DbiVer::PdbDbiV70);
|
||||
@@ -67,12 +61,12 @@ void PDB::build_DBI() {
|
||||
DBI.setBuildNumber(14, 11); // LLVM is compatible with LINK 14.11
|
||||
|
||||
// Add sections.
|
||||
auto section_table = m_owning_coff.get_section_table();
|
||||
auto number_of_sections = m_owning_coff.get_number_of_sections();
|
||||
auto section_table = m_owning_coff->get_section_table();
|
||||
auto number_of_sections = m_owning_coff->get_number_of_sections();
|
||||
|
||||
auto section_data_ref = ArrayRef<uint8_t>(
|
||||
(uint8_t*)section_table,
|
||||
m_owning_coff.get_number_of_sections() * sizeof(object::coff_section)
|
||||
m_owning_coff->get_number_of_sections() * sizeof(object::coff_section)
|
||||
);
|
||||
|
||||
auto section_table_ref = ArrayRef<object::coff_section>(
|
||||
@@ -89,20 +83,36 @@ void PDB::build_DBI() {
|
||||
}
|
||||
|
||||
void PDB::build_TPI() {
|
||||
m_builder.getTpiBuilder().setVersionHeader(PdbRaw_TpiVer::PdbTpiV80);
|
||||
m_builder.getIpiBuilder().setVersionHeader(PdbRaw_TpiVer::PdbTpiV80);
|
||||
auto& TPI = m_builder.getTpiBuilder();
|
||||
auto& IPI = m_builder.getIpiBuilder();
|
||||
|
||||
TPI.setVersionHeader(PdbRaw_TpiVer::PdbTpiV80);
|
||||
IPI.setVersionHeader(PdbRaw_TpiVer::PdbTpiV80);
|
||||
|
||||
if (m_owning_raw_type_data) {
|
||||
m_owning_raw_type_data->for_each<RawTypeData::TPI>(
|
||||
[&TPI](codeview::TypeIndex index, const codeview::CVType& type) {
|
||||
TPI.addTypeRecord(type.RecordData, std::nullopt);
|
||||
}
|
||||
);
|
||||
m_owning_raw_type_data->for_each<RawTypeData::IPI>(
|
||||
[&IPI](codeview::TypeIndex index, const codeview::CVType& type) {
|
||||
IPI.addTypeRecord(type.RecordData, std::nullopt);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void PDB::build_GSI() {
|
||||
std::vector<BulkPublic> publics;
|
||||
m_owning_symbol_data.for_each([&publics,
|
||||
this](const SymbolDataEntity& entity) {
|
||||
m_owning_symbol_data->for_each([&publics,
|
||||
this](const SymbolDataEntity& entity) {
|
||||
BulkPublic symbol;
|
||||
|
||||
auto section_index =
|
||||
m_owning_coff.get_section_index(entity.rva - m_image_base);
|
||||
m_owning_coff->get_section_index(entity.rva - m_image_base);
|
||||
auto section_or_err =
|
||||
m_owning_coff.get_owning_coff().getSection(section_index + 1);
|
||||
m_owning_coff->get_owning_coff().getSection(section_index + 1);
|
||||
if (!section_or_err) {
|
||||
throw std::runtime_error("Invalid section.");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "binary/COFF.h"
|
||||
|
||||
#include "raw_type_data.h"
|
||||
#include "symbol_data.h"
|
||||
|
||||
#include <llvm/DebugInfo/PDB/Native/PDBFileBuilder.h>
|
||||
@@ -10,7 +12,23 @@ namespace makepdb::binary {
|
||||
|
||||
class PDB {
|
||||
public:
|
||||
explicit PDB(COFF&& coff, SymbolData&& symbol_data);
|
||||
using OwningCOFF = std::unique_ptr<COFF>;
|
||||
using OwningSymbolData = std::unique_ptr<SymbolData>;
|
||||
using OwningRawTypeData = std::unique_ptr<RawTypeData>;
|
||||
|
||||
explicit PDB();
|
||||
|
||||
void set_coff_object(OwningCOFF coff_object) {
|
||||
m_owning_coff = std::move(coff_object);
|
||||
m_image_base = m_owning_coff->get_owning_coff().getImageBase();
|
||||
}
|
||||
|
||||
void set_symbol_data(OwningSymbolData symbol_data) {
|
||||
m_owning_symbol_data = std::move(symbol_data);
|
||||
}
|
||||
void set_raw_type_data(OwningRawTypeData raw_type_data) {
|
||||
m_owning_raw_type_data = std::move(raw_type_data);
|
||||
}
|
||||
|
||||
void write(std::string_view path);
|
||||
|
||||
@@ -22,8 +40,9 @@ private:
|
||||
inline void build_TPI();
|
||||
inline void build_GSI();
|
||||
|
||||
COFF m_owning_coff;
|
||||
SymbolData m_owning_symbol_data;
|
||||
OwningCOFF m_owning_coff;
|
||||
OwningSymbolData m_owning_symbol_data;
|
||||
OwningRawTypeData m_owning_raw_type_data;
|
||||
|
||||
uint64_t m_image_base;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "binary/COFF.h"
|
||||
#include "binary/PDB.h"
|
||||
|
||||
#include "raw_type_data.h"
|
||||
#include "symbol_data.h"
|
||||
|
||||
using namespace makepdb;
|
||||
@@ -14,8 +15,9 @@ using namespace makepdb;
|
||||
struct {
|
||||
std::string server_program_path;
|
||||
std::string symbol_data_path;
|
||||
std::string typeinfo_pdb_path;
|
||||
std::string output_path;
|
||||
|
||||
std::optional<std::string> typeinfo_pdb_path;
|
||||
} args;
|
||||
|
||||
program.add_argument("--program")
|
||||
@@ -28,6 +30,10 @@ using namespace makepdb;
|
||||
.store_into(args.symbol_data_path)
|
||||
.required();
|
||||
|
||||
program.add_argument("--typeinfo")
|
||||
.help("Path to compiler PDB which contains TPI & IPI (will merged into "
|
||||
"result PDB).");
|
||||
|
||||
program.add_argument("--output", "-o")
|
||||
.help("Path to output PDB.")
|
||||
.store_into(args.output_path)
|
||||
@@ -35,6 +41,10 @@ using namespace makepdb;
|
||||
|
||||
program.parse_args(argc, argv);
|
||||
|
||||
if (program.is_used("--typeinfo")) {
|
||||
args.typeinfo_pdb_path = program.get<std::string>("--typeinfo");
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -42,10 +52,20 @@ int main(int argc, char* argv[]) try {
|
||||
|
||||
auto args = load_args(argc, argv);
|
||||
|
||||
binary::COFF server_program(args.server_program_path);
|
||||
SymbolData symbol_data(args.symbol_data_path);
|
||||
auto server_program =
|
||||
std::make_unique<binary::COFF>(args.server_program_path);
|
||||
|
||||
binary::PDB pdb(std::move(server_program), std::move(symbol_data));
|
||||
auto symbol_data = std::make_unique<SymbolData>(args.symbol_data_path);
|
||||
|
||||
std::unique_ptr<RawTypeData> raw_type_data;
|
||||
if (args.typeinfo_pdb_path) {
|
||||
raw_type_data = std::make_unique<RawTypeData>(*args.typeinfo_pdb_path);
|
||||
}
|
||||
|
||||
binary::PDB pdb;
|
||||
pdb.set_coff_object(std::move(server_program));
|
||||
pdb.set_symbol_data(std::move(symbol_data));
|
||||
pdb.set_raw_type_data(std::move(raw_type_data));
|
||||
|
||||
pdb.write(args.output_path);
|
||||
|
||||
|
||||
54
MakePDB/src/raw_type_data.cpp
Normal file
54
MakePDB/src/raw_type_data.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "raw_type_data.h"
|
||||
|
||||
#include <llvm/DebugInfo/PDB/IPDBSession.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/NativeSession.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/PDBFile.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/TpiStream.h>
|
||||
#include <llvm/DebugInfo/PDB/PDB.h>
|
||||
#include <llvm/DebugInfo/PDB/PDBTypes.h>
|
||||
|
||||
using namespace llvm::pdb;
|
||||
|
||||
namespace makepdb {
|
||||
|
||||
RawTypeData::RawTypeData(std::string_view path)
|
||||
: m_storaged_TPI(m_allocator),
|
||||
m_storaged_IPI(m_allocator) {
|
||||
std::unique_ptr<IPDBSession> pdb_session;
|
||||
if (llvm::pdb::loadDataForPDB(PDB_ReaderType::Native, path, pdb_session)) {
|
||||
throw std::runtime_error("Failed to load PDB.");
|
||||
}
|
||||
|
||||
auto native_session = static_cast<NativeSession*>(pdb_session.get());
|
||||
auto& pdb_file = native_session->getPDBFile();
|
||||
|
||||
SmallVector<codeview::TypeIndex, 128> type_map;
|
||||
SmallVector<codeview::TypeIndex, 128> id_map;
|
||||
|
||||
if (auto tpi_stream = pdb_file.getPDBTpiStream()) {
|
||||
if (codeview::mergeTypeRecords(
|
||||
m_storaged_TPI,
|
||||
type_map,
|
||||
(*tpi_stream).typeArray()
|
||||
)) {
|
||||
throw std::runtime_error("Failed to merge type record.");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("TPI is not valid.");
|
||||
}
|
||||
|
||||
if (auto ipi_stream = pdb_file.getPDBIpiStream()) {
|
||||
if (codeview::mergeIdRecords(
|
||||
m_storaged_IPI,
|
||||
type_map,
|
||||
id_map,
|
||||
(*ipi_stream).typeArray()
|
||||
)) {
|
||||
throw std::runtime_error("Failed to merge id record.");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("IPI is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace makepdb
|
||||
34
MakePDB/src/raw_type_data.h
Normal file
34
MakePDB/src/raw_type_data.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h>
|
||||
#include <llvm/DebugInfo/CodeView/TypeStreamMerger.h>
|
||||
|
||||
namespace makepdb {
|
||||
|
||||
class RawTypeData {
|
||||
public:
|
||||
using ForEachTpiCallback =
|
||||
std::function<void(codeview::TypeIndex, codeview::CVType)>;
|
||||
|
||||
enum TypedStream { TPI, IPI };
|
||||
|
||||
explicit RawTypeData(std::string_view path);
|
||||
|
||||
template <TypedStream Stream>
|
||||
void for_each(const ForEachTpiCallback& callback) /*const*/ {
|
||||
if constexpr (Stream == TPI) {
|
||||
return m_storaged_TPI.ForEachRecord(callback);
|
||||
}
|
||||
if constexpr (Stream == IPI) {
|
||||
return m_storaged_IPI.ForEachRecord(callback);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BumpPtrAllocator m_allocator;
|
||||
|
||||
codeview::MergingTypeTableBuilder m_storaged_TPI;
|
||||
codeview::MergingTypeTableBuilder m_storaged_IPI;
|
||||
};
|
||||
|
||||
} // namespace makepdb
|
||||
Reference in New Issue
Block a user