117 lines
4.1 KiB
Python
Executable File
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))
|