News:

Download Pelles C here: http://www.smorgasbordet.com/pellesc/

Main Menu

some fun with pdb

Started by TimoVJL, June 25, 2018, 04:56:27 PM

Previous topic - Next topic

TimoVJL

How about reading pdb?
llvm offers some info about it, The PDB File Format

I hope that we can discuss about it in here and we find out what it can offer to PellesC users.
An open discussion about it.

EDIT:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
//#include "msf.h"

// https://llvm.org/docs/PDB/MsfFile.html

const char Magic[] = "Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\0\0";

typedef struct SuperBlock {
  char FileMagic[32]; //sizeof(Magic)];
  uint32_t BlockSize;
  uint32_t FreeBlockMapBlock;
  uint32_t NumBlocks;
  uint32_t NumDirectoryBytes;
  uint32_t Unknown;
  uint32_t BlockMapAddr;
}SUPERBLOCK,*PSUPERBLOCK;

typedef struct StreamDirectory {
  uint32_t NumStreams;
  uint32_t StreamSizes; //[NumStreams];
  uint32_t StreamBlocks[]; //[NumStreams][];
}STREAMDIRECTORY,*PSTREAMDIRECTORY;

int ProcessFile(PBYTE pMem);

int main(int argc, char **argv)
{
HANDLE hFile, hMapping;
VOID *pMem;

if (argc < 2) {
puts("Usage: TestMsf.exe <file>");
return 1;
}

hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping)
{
pMem = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (pMem)
{
ProcessFile(pMem);
UnmapViewOfFile(pMem);
} else
puts("File open error");
CloseHandle(hMapping);
} else
puts("FileMapping error");
CloseHandle(hFile);
}
else
puts("File open error");
return 0;
}

/*
Old Directory Fixed Stream Index 0 Previous MSF Stream Directory
PDB Stream Fixed Stream Index 1 Basic File Information
TPI Stream Fixed Stream Index 2 CodeView Type Records
DBI Stream Fixed Stream Index 3 Module/Compiland Information
IPI Stream Fixed Stream Index 4 CodeView Type Records
*/
int ProcessFile(PBYTE pMem)
{
SUPERBLOCK *pMsfHdr = (SUPERBLOCK*)pMem;
printf("FileMagic: %s\n", pMsfHdr->FileMagic);
printf("BlockSize: %u\n", pMsfHdr->BlockSize);
printf("FreeBlockMapBlock: %u -> %Xh\n", pMsfHdr->FreeBlockMapBlock,
pMsfHdr->FreeBlockMapBlock*pMsfHdr->BlockSize);
printf("NumBlocks: %u\n", pMsfHdr->NumBlocks);
printf("NumDirectoryBytes: %u\n", pMsfHdr->NumDirectoryBytes);
printf("Unknown: %u\n", pMsfHdr->Unknown);
printf("BlockMapAddr: %u -> %Xh\n", pMsfHdr->BlockMapAddr,
pMsfHdr->BlockMapAddr*pMsfHdr->BlockSize);
printf("\nfilesize: %u\n", pMsfHdr->BlockSize*pMsfHdr->NumBlocks);
DWORD *pIndexes = (DWORD*)(pMem+pMsfHdr->BlockMapAddr*pMsfHdr->BlockSize);
DWORD *pIndex = pIndexes; // the first Index Block
printf("\nStreamDir indexes:");
while (*pIndex)
printf("%04Xh", *pIndex++);
pIndex = pIndexes; // the first Index Block
printf("\nStreamDir Block %u -> %Xh\n", *pIndex, *pIndex*pMsfHdr->BlockSize);
PSTREAMDIRECTORY pStreamDir = (PSTREAMDIRECTORY)(pMem+*pIndex*pMsfHdr->BlockSize);
printf("NumStreams %u\n", pStreamDir->NumStreams);
DWORD nStreams = pStreamDir->NumStreams;
DWORD nStreamBlocks = pMsfHdr->NumDirectoryBytes/4-1-pStreamDir->NumStreams;
printf("Number of stream blocks %u\n", nStreamBlocks);
//DWORD *pDW = (DWORD*)&pStreamDir->StreamSizes;
DWORD *pStreamSizes = &pStreamDir->StreamSizes;
printf("StreamSizes[%u] = ", nStreams);
for (DWORD nC=0; nC<nStreams; nC++)
printf("%d ", pStreamSizes[nC]);
printf("\nStreamBlocks[%u] =", nStreamBlocks);
DWORD *pStreamBlocks = &pStreamDir->StreamSizes;
pStreamBlocks += nStreams;
for (DWORD nC=0; nC<nStreamBlocks; nC++)
printf(" %2d", pStreamBlocks[nC]);
printf("\n                 ");
for (DWORD nC=0; nC<nStreams; nC++) {
//int nBlocks = pStreamSizes[nC]/nBlockSize+(pStreamSizes[nC]%nBlockSize?1:0);
int nBlocks;
if (pStreamSizes[nC]>0 && pStreamSizes[nC]<0xFFFFFFFF) // -1 free block
nBlocks = (pStreamSizes[nC]-1)/nBlockSize+1;
else nBlocks = 0;
if (nBlocks) {
printf("%2d %u {", nStream, nBlocks);
int nBlk1 = nBlkCnt;
for (int i=0; i<nBlocks; i++) {
if (i) printf(",");
printf("%d", pStreamBlocks[nBlkCnt++]);
}
printf("} %u bytes -> %Xh\n", pStreamSizes[nC], pStreamBlocks[nBlk1]*nBlockSize);
} else printf("%2d %u\n", nStream, nBlocks);
nStream++;
}
return 0;
}


EDIT 2018-07-05: TestPdb_a2 avoid to show wrong stream blocks.
EDIT 2018-07-06: TestPdb_a2 fixed streams.
May the source be with you

Vortex

Hi Timo,

Nice work, thanks. It shows all the sections of .pdb files.
Code it... That's all...

TimoVJL

#2
Examples don't read blocks correctly, if they are not sequential :(
The hex-viewer works only with sequential data.

EDIT: a fix with a hex-viewer2
May the source be with you

TimoVJL

I hope that at least someone is interest of exploring PDB and gives a some info about it.
If you know good links for PDB internals, let us know about it.
May the source be with you

frankie

#4
Try if this work.
Actually it only read and extract files.
There is no codeview support, it only process the Multi Stream File format.
I'll publish source when my MSF lib is somewhat more solid.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

TimoVJL

Sure i test it :)
Good to know that you explore pdb too.
May the source be with you

frankie

Just a mind exercise.  ;)
It is more close to my attitude, system code, drivers ...
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide