Files
2025-09-29 00:52:08 +02:00

117 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python
from construct import *
_ALIGN = 4
def get_parsed_size(tp,con):
return len(tp.build(con))
def SymbolRange(name):
return Struct(name,
SLInt16("section"),
Padding(2),
SLInt32("offset"),
SLInt32("size"),
ULInt32("flags"),
SLInt16("module"),
Padding(2),
ULInt32("dataCRC"),
ULInt32("relocCRC"),
)
DBIHeader = Struct("DBIHeader",
Const(Bytes("magic", 4), "\xFF\xFF\xFF\xFF"), # 0
ULInt32("version"), # 4
ULInt32("age"), # 8
SLInt16("gssymStream"), # 12
ULInt16("vers"), # 14
SLInt16("pssymStream"), # 16
ULInt16("pdbver"), # 18
SLInt16("symrecStream"), # stream containing global symbols # 20
ULInt16("pdbver2"), # 22
ULInt32("module_size"), # total size of DBIExHeaders # 24
ULInt32("secconSize"), # 28
ULInt32("secmapSize"), # 32
ULInt32("filinfSize"), # 36
ULInt32("tsmapSize"), # 40
ULInt32("mfcIndex"), # 44
ULInt32("dbghdrSize"), # 48
ULInt32("ecinfoSize"), # 52
ULInt16("flags"), # 56
Enum(ULInt16("Machine"), # 58
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
IMAGE_FILE_MACHINE_I386 = 0x014c,
IMAGE_FILE_MACHINE_IA64 = 0x0200,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
),
ULInt32("resvd"), # 60
)
DBIExHeader = Struct("DBIExHeader",
ULInt32("opened"),
SymbolRange("range"),
ULInt16("flags"),
SLInt16("stream"),
ULInt32("symSize"),
ULInt32("oldLineSize"),
ULInt32("lineSize"),
SLInt16("nSrcFiles"),
Padding(2),
ULInt32("offsets"),
ULInt32("niSource"),
ULInt32("niCompiler"),
CString("modName"),
CString("objName"),
)
DbiDbgHeader = Struct("DbiDbgHeader",
SLInt16("snFPO"),
SLInt16("snException"),
SLInt16("snFixup"),
SLInt16("snOmapToSrc"),
SLInt16("snOmapFromSrc"),
SLInt16("snSectionHdr"),
SLInt16("snTokenRidMap"),
SLInt16("snXdata"),
SLInt16("snPdata"),
SLInt16("snNewFPO"),
SLInt16("snSectionHdrOrig"),
)
def parse_stream(stream):
pos = 0
dbihdr = DBIHeader.parse_stream(stream)
pos += get_parsed_size(DBIHeader, dbihdr)
stream.seek(pos)
dbiexhdr_data = stream.read(dbihdr.module_size)
# sizeof() is broken on CStrings for construct, so
# this ugly ugly hack is necessary
dbiexhdrs = []
while dbiexhdr_data:
dbiexhdrs.append(DBIExHeader.parse(dbiexhdr_data))
sz = get_parsed_size(DBIExHeader,dbiexhdrs[-1])
if sz % _ALIGN != 0: sz = sz + (_ALIGN - (sz % _ALIGN))
dbiexhdr_data = dbiexhdr_data[sz:]
# "Section Contribution"
stream.seek(dbihdr.secconSize, 1)
# "Section Map"
stream.seek(dbihdr.secmapSize, 1)
# "File Info"
stream.seek(dbihdr.filinfSize, 1)
# "TSM"
stream.seek(dbihdr.tsmapSize, 1)
# "EC"
stream.seek(dbihdr.ecinfoSize, 1)
# The data we really want
dbghdr = DbiDbgHeader.parse_stream(stream)
return Container(DBIHeader=dbihdr,
DBIExHeaders=ListContainer(dbiexhdrs),
DBIDbgHeader=dbghdr)
def parse(data):
return parse_stream(StringIO(data))