Pelles C forum

C language => Tips & tricks => Topic started by: TimoVJL on June 25, 2018, 04:56:27 PM

Title: some fun with pdb
Post by: TimoVJL on June 25, 2018, 04:56:27 PM
How about reading pdb?
llvm offers some info about it, The PDB File Format (https://llvm.org/docs/PDB/index.html)

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:
Code: [Select]
#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.
Title: Re: some fun with pdb
Post by: Vortex on July 04, 2018, 10:11:01 PM
Hi Timo,

Nice work, thanks. It shows all the sections of .pdb files.
Title: Re: some fun with pdb
Post by: TimoVJL on July 05, 2018, 09:04:24 AM
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
Title: Re: some fun with pdb
Post by: TimoVJL on July 07, 2018, 02:58:38 PM
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.
Title: Re: some fun with pdb
Post by: frankie on July 25, 2018, 03:47:54 PM
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.
Title: Re: some fun with pdb
Post by: TimoVJL on July 25, 2018, 04:19:40 PM
Sure i test it :)
Good to know that you explore pdb too.
Title: Re: some fun with pdb
Post by: frankie on July 25, 2018, 04:44:54 PM
Just a mind exercise.  ;)
It is more close to my attitude, system code, drivers ...