NO

Author Topic: some fun with pdb  (Read 216 times)

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1720
some fun with pdb
« on: June 25, 2018, 04:56:27 pm »
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:
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.
« Last Edit: July 07, 2018, 11:02:49 am by TimoVJL »
May the source be with you

Offline Vortex

  • Member
  • *
  • Posts: 508
    • http://www.vortex.masmcode.com
Re: some fun with pdb
« Reply #1 on: July 04, 2018, 10:11:01 pm »
Hi Timo,

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

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1720
Re: some fun with pdb
« Reply #2 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
« Last Edit: July 06, 2018, 02:41:57 pm by TimoVJL »
May the source be with you

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1720
Re: some fun with pdb
« Reply #3 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.
May the source be with you