mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
Replace DIA SDK COM-based PDB importer with RawPDB (MolecularMatters) which reads PDB files directly via memory-mapped I/O. Adds File menu "Import PDB..." dialog with type filtering, selection, and progress. - Vendor raw_pdb into third_party/ - Two-phase API: enumeratePdbTypes() + importPdbSelected() - Full recursive import of structs/unions/arrays/pointers/bitfields - PDB import dialog with name filter, select-all, type count - Benchmark: 1654 types from ntkrnlmp.pdb in 16ms - Reorganize import/export files into src/imports/
201 lines
5.4 KiB
C++
201 lines
5.4 KiB
C++
// Copyright 2011-2022, Molecular Matters GmbH <office@molecular-matters.com>
|
|
// See LICENSE.txt for licensing details (2-clause BSD License: https://opensource.org/licenses/BSD-2-Clause)
|
|
|
|
#include "Examples_PCH.h"
|
|
#include "ExampleMemoryMappedFile.h"
|
|
#include "PDB.h"
|
|
#include "PDB_RawFile.h"
|
|
#include "PDB_InfoStream.h"
|
|
#include "PDB_DBIStream.h"
|
|
#include "PDB_TPIStream.h"
|
|
#include "PDB_IPIStream.h"
|
|
#include "PDB_NamesStream.h"
|
|
|
|
namespace
|
|
{
|
|
PDB_NO_DISCARD static bool IsError(PDB::ErrorCode errorCode)
|
|
{
|
|
switch (errorCode)
|
|
{
|
|
case PDB::ErrorCode::Success:
|
|
return false;
|
|
|
|
case PDB::ErrorCode::InvalidSuperBlock:
|
|
printf("Invalid Superblock\n");
|
|
return true;
|
|
|
|
case PDB::ErrorCode::InvalidFreeBlockMap:
|
|
printf("Invalid free block map\n");
|
|
return true;
|
|
|
|
case PDB::ErrorCode::InvalidStream:
|
|
printf("Invalid stream\n");
|
|
return true;
|
|
|
|
case PDB::ErrorCode::InvalidSignature:
|
|
printf("Invalid stream signature\n");
|
|
return true;
|
|
|
|
case PDB::ErrorCode::InvalidStreamIndex:
|
|
printf("Invalid stream index\n");
|
|
return true;
|
|
|
|
case PDB::ErrorCode::InvalidDataSize:
|
|
printf("Invalid data size\n");
|
|
return true;
|
|
|
|
case PDB::ErrorCode::UnknownVersion:
|
|
printf("Unknown version\n");
|
|
return true;
|
|
}
|
|
|
|
// only ErrorCode::Success means there wasn't an error, so all other paths have to assume there was an error
|
|
return true;
|
|
}
|
|
|
|
PDB_NO_DISCARD static bool HasValidDBIStreams(const PDB::RawFile& rawPdbFile, const PDB::DBIStream& dbiStream)
|
|
{
|
|
// check whether the DBI stream offers all sub-streams we need
|
|
if (IsError(dbiStream.HasValidSymbolRecordStream(rawPdbFile)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (IsError(dbiStream.HasValidPublicSymbolStream(rawPdbFile)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (IsError(dbiStream.HasValidGlobalSymbolStream(rawPdbFile)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (IsError(dbiStream.HasValidSectionContributionStream(rawPdbFile)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (IsError(dbiStream.HasValidImageSectionStream(rawPdbFile)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
// declare all examples
|
|
extern void ExamplePDBSize(const PDB::RawFile&, const PDB::DBIStream&);
|
|
extern void ExampleTPISize(const PDB::TPIStream& tpiStream, const char* outPath);
|
|
extern void ExampleContributions(const PDB::RawFile&, const PDB::DBIStream&);
|
|
extern void ExampleSymbols(const PDB::RawFile&, const PDB::DBIStream&);
|
|
extern void ExampleFunctionSymbols(const PDB::RawFile&, const PDB::DBIStream&);
|
|
extern void ExampleFunctionVariables(const PDB::RawFile& rawPdbFile, const PDB::DBIStream& dbiStream, const PDB::TPIStream&);
|
|
extern void ExampleLines(const PDB::RawFile& rawPdbFile, const PDB::DBIStream& dbiStream, const PDB::InfoStream& infoStream);
|
|
extern void ExampleTypes(const PDB::TPIStream&);
|
|
extern void ExampleIPI(const PDB::RawFile& rawPdbFile, const PDB::InfoStream& infoStream, const PDB::TPIStream& tpiStream, const PDB::IPIStream& ipiStream);
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
if (argc != 2)
|
|
{
|
|
printf("Usage: Examples <PDB path>\nError: Incorrect usage\n");
|
|
|
|
return 1;
|
|
}
|
|
|
|
printf("Opening PDB file %s\n", argv[1]);
|
|
|
|
// try to open the PDB file and check whether all the data we need is available
|
|
MemoryMappedFile::Handle pdbFile = MemoryMappedFile::Open(argv[1]);
|
|
if (!pdbFile.baseAddress)
|
|
{
|
|
printf("Cannot memory-map file %s\n", argv[1]);
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (IsError(PDB::ValidateFile(pdbFile.baseAddress, pdbFile.len)))
|
|
{
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 2;
|
|
}
|
|
|
|
const PDB::RawFile rawPdbFile = PDB::CreateRawFile(pdbFile.baseAddress);
|
|
if (IsError(PDB::HasValidDBIStream(rawPdbFile)))
|
|
{
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 3;
|
|
}
|
|
|
|
const PDB::InfoStream infoStream(rawPdbFile);
|
|
if (infoStream.UsesDebugFastLink())
|
|
{
|
|
printf("PDB was linked using unsupported option /DEBUG:FASTLINK\n");
|
|
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 4;
|
|
}
|
|
|
|
const auto h = infoStream.GetHeader();
|
|
printf("Version %u, signature %u, age %u, GUID %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
|
static_cast<uint32_t>(h->version), h->signature, h->age,
|
|
h->guid.Data1, h->guid.Data2, h->guid.Data3,
|
|
h->guid.Data4[0], h->guid.Data4[1], h->guid.Data4[2], h->guid.Data4[3], h->guid.Data4[4], h->guid.Data4[5], h->guid.Data4[6], h->guid.Data4[7]);
|
|
|
|
const PDB::DBIStream dbiStream = PDB::CreateDBIStream(rawPdbFile);
|
|
if (!HasValidDBIStreams(rawPdbFile, dbiStream))
|
|
{
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 5;
|
|
}
|
|
|
|
if (IsError(PDB::HasValidTPIStream(rawPdbFile)))
|
|
{
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 5;
|
|
}
|
|
const PDB::TPIStream tpiStream = PDB::CreateTPIStream(rawPdbFile);
|
|
|
|
PDB::IPIStream ipiStream;
|
|
|
|
// It's perfectly possible that an old PDB does not have an IPI stream.
|
|
if(infoStream.HasIPIStream())
|
|
{
|
|
PDB::ErrorCode error = PDB::HasValidIPIStream(rawPdbFile);
|
|
|
|
if (error != PDB::ErrorCode::InvalidStream && IsError(error))
|
|
{
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 5;
|
|
}
|
|
|
|
ipiStream = PDB::CreateIPIStream(rawPdbFile);
|
|
}
|
|
|
|
|
|
// run all examples
|
|
ExamplePDBSize(rawPdbFile, dbiStream);
|
|
ExampleContributions(rawPdbFile, dbiStream);
|
|
ExampleSymbols(rawPdbFile, dbiStream);
|
|
ExampleFunctionSymbols(rawPdbFile, dbiStream);
|
|
ExampleFunctionVariables(rawPdbFile, dbiStream, tpiStream);
|
|
ExampleLines(rawPdbFile, dbiStream, infoStream);
|
|
ExampleTypes(tpiStream);
|
|
ExampleIPI(rawPdbFile, infoStream, tpiStream, ipiStream);
|
|
// uncomment to dump type sizes to a CSV
|
|
// ExampleTPISize(tpiStream, "output.csv");
|
|
|
|
MemoryMappedFile::Close(pdbFile);
|
|
|
|
return 0;
|
|
}
|