Pdb
Description
Parsed PDB file. Holds the raw bytes (always parser-owned) plus decoded indices into them. All three PdbOpen* constructors leave the parser as sole owner of data – see the L / R semantics on the FromMemory / FromMemoryCopy constructors (mirrors VecInsertL / VecInsertR).
Fields
| Name | Description |
|---|---|
data |
Raw PDB bytes as a Buf (owned). Carries its own length and allocator – read via BufLength / BufData / BufAllocator. |
block_size |
MSF page size (read from the superblock; usually 4096 but can be 512/1024/2048). |
num_streams |
Stream count from the directory. |
info |
Decoded PDB Info stream (#1). |
functions |
Sorted-by-rva list of public function names from the Publics stream. Populated by PdbOpen[FromMemory]. |
Usage example (Cross-references)
Usage examples (Cross-references)
- In
PdbCache.h:26:
#define MISRA_SYS_PDB_CACHE_H
#include <Misra/Parsers/Pdb.h>
#include <Misra/Parsers/Pe.h>
#include <Misra/Std/Allocator.h>- In
PdbCache.h:36:
Str module_path; // owned; cleaned via StrDeinit
Pe pe;
Pdb pdb;
bool pe_open;
bool pdb_open;- In
Pdb.h:28:
#define MISRA_PARSERS_PDB_H
#include <Misra/Parsers/Pdb/Private.h>
#include <Misra/Std/Allocator.h>
#include <Misra/Std/Container/Buf.h>- In
Pdb.h:109:
// together in `PdbDeinit`.
Str name_pool;
} Pdb;
///
- In
Pdb.h:167:
/// TAGS: Parser, PDB, Memory, Ownership
///
bool PdbOpenFromMemory(Pdb *out, Buf *in);
///
- In
Pdb.h:194:
/// TAGS: Parser, PDB, Deinit, Lifecycle
///
void PdbDeinit(Pdb *self);
///
- In
Pdb.h:207:
/// TAGS: Parser, PDB, Function, Resolve
///
const PdbFunction *PdbResolveRva(const Pdb *self, u32 rva);
#endif // MISRA_PARSERS_PDB_H
- In
Pdb.c:9:
#include <Misra/Std/Container/Buf.h>
#include <Misra/Parsers/Pdb.h>
#include <Misra/Std.h>
#include <Misra/Std/File.h>- In
Pdb.c:93:
// Return a pointer to the first byte of block `block_id` inside the
// PDB file. NULL on out-of-range.
static const u8 *block_ptr(const Pdb *self, u32 block_id) {
u64 off = (u64)block_id * self->block_size;
if (off + self->block_size > BufLength(&self->data))- In
Pdb.c:102:
// Read `n` bytes from stream `idx` starting at byte offset `offset`
// into `dest`. Walks the stream's block chain.
static bool stream_read(const Pdb *self, u32 idx, u64 offset, u8 *dest, u64 n) {
if (idx >= self->num_streams)
return false;- In
Pdb.c:142:
// ---------------------------------------------------------------------------
static bool parse_superblock(Pdb *self, u32 *out_num_dir_bytes, u32 *out_block_map_addr) {
if (BufLength(&self->data) < SUPERBLOCK_SIZE) {
LOG_ERROR("PDB: file too small for MSF superblock");- In
Pdb.c:182:
// Reconstruct the stream directory into a contiguous buffer.
static bool reconstruct_directory(Pdb *self, u32 num_dir_bytes, u32 block_map_addr) {
// The block_map_addr page holds an array of u32 block indices,
// one per `block_size` chunk of the directory. The number of
- In
Pdb.c:232:
// Parse the reconstructed directory bytes into per-stream metadata.
static bool parse_directory(Pdb *self) {
if (self->stream_dir_size < 4) {
LOG_ERROR("PDB: directory truncated (no stream count)");- In
Pdb.c:318:
// ---------------------------------------------------------------------------
static bool parse_pdb_info(Pdb *self) {
if (self->num_streams <= 1)
return true; // no info stream
- In
Pdb.c:360:
} DbiSubstreamInfo;
static DbiSubstreamInfo parse_dbi_header(const Pdb *self) {
DbiSubstreamInfo r = {0};
if (DBI_STREAM_INDEX >= self->num_streams)- In
Pdb.c:452:
// return a small allocator-backed array of (RVA, VSize) pairs. Caller
// frees via AllocatorFree.
static SectionRva *load_section_table(const Pdb *self, u16 section_hdr_stream, u32 *out_count) {
*out_count = 0;
if (section_hdr_stream >= self->num_streams)- In
Pdb.c:532:
static bool walk_publics(
const Pdb *self,
u16 symrec_stream,
const SectionRva *sections,- In
Pdb.c:628:
// Top-level: pull DBI -> SectionHdr table + SymRecord stream -> publics.
static bool parse_pdb_functions(Pdb *self) {
DbiSubstreamInfo dbi = parse_dbi_header(self);
if (!dbi.ok)- In
Pdb.c:697:
// then MemSets the caller's view. On exit `*in` is zeroed (success
// or failure); allocator and bytes are carried by `taken`.
bool PdbOpenFromMemory(Pdb *out, Buf *in) {
if (!out || !in || !BufData(in) || !BufAllocator(in)) {
LOG_FATAL("PdbOpenFromMemory: NULL argument (contract violation)");- In
Pdb.c:730:
// R-value form: allocate Buf, copy, hand `©` to the L-form.
bool pdb_open_from_memory_copy(Pdb *out, const u8 *data, size data_size, Allocator *alloc) {
if (!out || !data || !alloc) {
LOG_FATAL("PdbOpenFromMemoryCopy: NULL argument (contract violation)");- In
Pdb.c:744:
}
bool pdb_open(Pdb *out, Zstr path, Allocator *alloc) {
if (!out || !path || !alloc) {
LOG_FATAL("PdbOpen: NULL argument (contract violation)");- In
Pdb.c:757:
}
void PdbDeinit(Pdb *self) {
if (!self)
return;- In
Pdb.c:777:
}
const PdbFunction *PdbResolveRva(const Pdb *self, u32 rva) {
if (!self || VecLen(&self->functions) == 0)
return NULL;- In
Pdb.c:12:
#include <Misra.h>
#include <Misra/Parsers/Pdb.h>
#include <Misra/Std/Zstr.h>
#include <Misra/Std/Allocator/Default.h>- In
Pdb.c:101:
build_msf_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, blob, sizeof(blob), base);
if (!ok) {- In
Pdb.c:127:
MemSet(garbage, 0xCC, sizeof(garbage));
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, garbage, sizeof(garbage), base);- In
Pdb.c:289:
build_full_pdb_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, fblob, sizeof(fblob), base);
if (!ok) {- In
Pdb.c:435:
build_multi_pdb_blob(&symrec_size);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, mblob, sizeof(mblob), base);
if (!ok) {- In
Pdb.c:500:
wr_u32(&buf[52], 0);
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, buf, sizeof(buf), base);- In
Pdb.c:516:
MemCopy(buf, kMagic, 16); // partial magic, far short of 56-byte superblock
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, buf, sizeof(buf), base);- In
Pdb.c:677:
// rva of the first function when count >= 1.
static int open_and_count(Allocator *base, u32 *out_rva0) {
Pdb pdb;
if (!PdbOpenFromMemoryCopy(&pdb, gblob, sizeof(gblob), base))
return -1;- In
Pdb.c:978:
u32 blob_len = build_blob_m2(B_BS, sizes, 3, &dir_bytes, &num_pages);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:998:
u32 sizes[2] = {0, 28};
u32 blob_len = build_blob_m2(bs, sizes, 2, NULL, NULL);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1037:
wr_u32(&buf[52], 0);
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, buf, sizeof(buf), base);
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:1056:
u32 blob_len = build_blob_m2(B_BS, sizes, 2, NULL, NULL);
g_blob[b] ^= 0xFF; // corrupt one magic byte
Pdb pdb;
bool opened = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (opened) {- In
Pdb.c:1080:
wr_u32(&buf[32], B_BS);
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, buf, sizeof(buf), base);
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:1101:
wr_u32(&g_blob[B_BLOCK_MAP * B_BS], num_pages);
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:1119:
u32 blob_len = build_blob_m2(B_BS, sizes, 2, NULL, NULL);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1140:
u32 blob_len = build_blob_m2(B_BS, sizes, 2, NULL, NULL);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1224:
build_two_block_dir();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_tblob, sizeof(g_tblob), base);
if (ok) {- In
Pdb.c:1253:
u32 blob_len = build_blob_multiblock(sizes, 5);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1290:
u32 blob_len = build_blob_multiblock(sizes, 3);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1317:
u32 blob_len = build_blob_multiblock(sizes, 1);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1343:
wr_u32(&dir[0], 1000); // claims 1000 streams; dir page can't hold them
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:1363:
wr_u32(&dir[4 + 1 * 4], 100 * 512); // 100 blocks claimed, none listed
Pdb pdb;
bool ok = !PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:1397:
wr_u32(&g_blob[Z_DIR * Z_BS], 0); // num_streams = 0
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, Z_PAGES * Z_BS, base);
if (ok) {- In
Pdb.c:1422:
u32 blob_len = build_blob_m2(B_BS, sizes, 3, NULL, NULL);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1451:
u32 blob_len = build_blob_multiblock(sizes, 2);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob, blob_len, base);
if (ok) {- In
Pdb.c:1503:
wr_u32(&dir0[4], PDB_NIL); // stream 0 is NIL -> no blocks
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_hblob, sizeof(g_hblob), base);
if (ok) {- In
Pdb.c:1674:
build_filter_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_filter, sizeof(g_blob_filter), base);
if (!ok) {- In
Pdb.c:1735:
build_sect_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_sect, sizeof(g_blob_sect), base);
if (!ok) {- In
Pdb.c:1792:
build_oob_seg_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_oob, sizeof(g_blob_oob), base);
if (!ok) {- In
Pdb.c:1848:
build_size_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_size, sizeof(g_blob_size), base);
if (!ok) {- In
Pdb.c:1915:
build_sort_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_sort, sizeof(g_blob_sort), base);
if (!ok) {- In
Pdb.c:1976:
build_mal_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_mal, sizeof(g_blob_mal), base);
if (!ok) {- In
Pdb.c:2034:
build_ovf_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_ovf, sizeof(g_blob_ovf), base);
if (!ok) {- In
Pdb.c:2228:
build_crossblock_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, xblob, sizeof(xblob), base);
if (!ok) {- In
Pdb.c:2270:
wr_u32(&info[8], 0x090A0B0C); // age
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, xblob, sizeof(xblob), base);
if (!ok) {- In
Pdb.c:2344:
build_info_blob(999);
Pdb pdb;
bool open_ok = PdbOpenFromMemoryCopy(&pdb, sblob, sizeof(sblob), base);
// Real code: rejected.
- In
Pdb.c:2364:
build_info_blob(S_INFO_PAGE);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, sblob, sizeof(sblob), base);
if (!ok) {- In
Pdb.c:2403:
BufResize(&in, (size)sizeof(sblob));
Pdb pdb;
bool open_ok = PdbOpenFromMemory(&pdb, &in);
// Expect failure (bogus info block id).
- In
Pdb.c:2429:
build_crossblock_blob(); // populates name_pool with two function names
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, xblob, sizeof(xblob), base);
if (!ok) {- In
Pdb.c:2468:
}
Pdb pdb;
bool ok = PdbOpen(&pdb, X_TMP_VALID, base);
if (ok) {- In
Pdb.c:2496:
}
Pdb pdb;
bool ok = !PdbOpen(&pdb, X_TMP_JUNK, base);- In
Pdb.c:2512:
build_crossblock_blob();
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, xblob, sizeof(xblob), base);
if (!ok) {- In
Pdb.c:2686:
build_pdb(g_blob_m5, secs, 6, pubs, 1, 0, 0);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_m5, P5_BLOB_SIZE, base);
if (ok) {- In
Pdb.c:2721:
build_pdb(g_blob_m5, secs, 3, pubs, 1, /*sec_block_id_override=*/100, 0);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_m5, P5_BLOB_SIZE, base);
if (ok) {- In
Pdb.c:2751:
build_pdb(g_blob_m5, secs, 2, pubs, 2, 0, 0);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_m5, P5_BLOB_SIZE, base);
if (ok) {- In
Pdb.c:2783:
build_pdb(g_blob_m5, secs, 1, pubs, 3, 0, 0);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_m5, P5_BLOB_SIZE, base);
if (ok) {- In
Pdb.c:2814:
build_pdb(g_blob_m5, secs, 1, pubs, 1, 0, 0);
Pdb pdb;
bool ok = PdbOpenFromMemoryCopy(&pdb, g_blob_m5, P5_BLOB_SIZE, base);
if (ok) {- In
Pdb.c:2849:
build_pdb(g_blob_m5, secs, 1, pubs, 1, 0, /*symrec_override=*/99);
Pdb pdb;
bool rejected = !PdbOpenFromMemoryCopy(&pdb, g_blob_m5, P5_BLOB_SIZE, base);
if (!rejected)- In
Pdb.c:3001:
static int open_count(Allocator *base, Blob *b) {
Pdb pdb;
if (!PdbOpenFromMemoryCopy(&pdb, b->bytes, b->len, base))
return -1;- In
Pdb.c:3032:
put_pub32(stream_page(&b, 4), 0x100, 1, "deepblk");
Pdb pdb;
if (!PdbOpenFromMemoryCopy(&pdb, b.bytes, b.len, base)) {
DefaultAllocatorDeinit(&alloc);- In
Pdb.c:3075:
put_pub32(stream_page(&b, 4), 0x100, 1, "deepfn");
Pdb pdb;
bool opened = PdbOpenFromMemoryCopy(&pdb, b.bytes, b.len, base);
bool ok = opened && VecLen(&pdb.functions) == 1 && pdb.num_streams == N;- In
Pdb.c:3116:
put_pub32(stream_page(&b, 4), 0x100, 1, "fn");
Pdb pdb;
bool opened = PdbOpenFromMemoryCopy(&pdb, b.bytes, b.len, base);
bool ok = opened && VecLen(&pdb.functions) == 1;- In
Pdb.c:3225:
int main(void) {
WriteFmt("[INFO] Starting Pdb tests\n\n");
TestFunction tests[] = {- In
Pdb.c:3290:
};
return run_test_suite(tests, sizeof(tests) / sizeof(tests[0]), NULL, 0, "Pdb");
}
Last updated on