Factor out some functionality to separate file.

This commit is contained in:
Krystian Bacławski
2013-05-25 17:48:44 +02:00
parent b8aee8e3a3
commit ff799ccd5f
2 changed files with 118 additions and 114 deletions
+11 -114
View File
@@ -1,115 +1,12 @@
#!/usr/bin/env python2.7 -B
from collections import namedtuple, defaultdict
import inspect
from collections import defaultdict
import struct
import sys
import textwrap
from objtools import util
class HunkMap(object):
# Any hunks that have the HUNKB_ADVISORY bit set will be ignored if they
# aren't understood. When ignored, they're treated like HUNK_DEBUG hunks.
# NOTE: this handling of HUNKB_ADVISORY started as of V39 dos.library! If
# lading such executables is attempted under <V39 dos, it will fail with a
# bad hunk type.
HUNKB_ADVISORY = 29
HUNKB_CHIP = 30
HUNKB_FAST = 31
HUNKF_ADVISORY = 1 << HUNKB_ADVISORY
HUNKF_CHIP = 1 << HUNKB_CHIP
HUNKF_FAST = 1 << HUNKB_FAST
HUNK_UNIT = 999
HUNK_NAME = 1000
HUNK_CODE = 1001
HUNK_DATA = 1002
HUNK_BSS = 1003
HUNK_RELOC32 = 1004
HUNK_RELOC16 = 1005
HUNK_RELOC8 = 1006
HUNK_EXT = 1007
HUNK_SYMBOL = 1008
HUNK_DEBUG = 1009
HUNK_END = 1010
HUNK_HEADER = 1011
HUNK_OVERLAY = 1013
HUNK_BREAK = 1014
HUNK_DREL32 = 1015
HUNK_DREL16 = 1016
HUNK_DREL8 = 1017
HUNK_LIB = 1018
HUNK_INDEX = 1019
HUNK_RELOC32SHORT = 1020
HUNK_RELRELOC32 = 1021
HUNK_ABSRELOC16 = 1022
HUNK_PPC_CODE = 1257
HUNK_RELRELOC26 = 1260
@classmethod
def GetName(cls, number):
number &= 0x1fffffff
for name, value in inspect.getmembers(cls):
if name.startswith('HUNK_'):
if value == number:
return name
raise ValueError('Unknown Hunk: %d' % number)
@classmethod
def GetFlags(cls, number):
flags = []
for name, value in inspect.getmembers(cls):
if name.startswith('HUNKF_'):
if value & number:
flags.append(name)
return flags
class HunkExtMap(object):
EXT_SYMB = 0 # symbol table
EXT_DEF = 1 # relocatable definition
EXT_ABS = 2 # Absolute definition
EXT_RES = 3 # no longer supported
EXT_REF32 = 129 # 32 bit absolute reference to symbol
EXT_COMMON = 130 # 32 bit absolute reference to COMMON block
EXT_REF16 = 131 # 16 bit PC-relative reference to symbol
EXT_REF8 = 132 # 8 bit PC-relative reference to symbol
EXT_DEXT32 = 133 # 32 bit data relative reference
EXT_DEXT16 = 134 # 16 bit data relative reference
EXT_DEXT8 = 135 # 8 bit data relative reference
EXT_RELREF32 = 136 # 32 bit PC-relative reference to symbol
EXT_RELCOMMON = 137 # 32 bit PC-relative reference to COMMON block
EXT_ABSREF16 = 138 # 16 bit absolute reference to symbol
EXT_ABSREF8 = 139 # 8 bit absolute reference to symbol
EXT_RELREF26 = 229
@classmethod
def GetName(cls, number):
for name, value in inspect.getmembers(cls):
if name.startswith('EXT_'):
if value == number:
return name
raise ValueError('Unknown HunkExt: %d' % number)
class Hunk(namedtuple('Hunk', 'name data flags')):
def __repr__(self):
if self.data:
if self.flags:
flags = ', flags=%s' % '|'.join(self.flags)
else:
flags = ''
return '%s(%r%s)' % (self.name, self.data, flags)
else:
return self.name
Header = namedtuple('Header', 'residents hunks first last specifiers')
from objtools.hunk import (GetHunkName, GetHunkExtName, GetHunkFlags, Hunk,
Header)
class HunkParser(object):
@@ -118,17 +15,17 @@ class HunkParser(object):
self.index = 0
def ReadLong(self):
data = struct.unpack('>I', self.data[self.index:self.index + 4])[0]
data = struct.unpack_from('>I', self.data, self.index)[0]
self.index += 4
return data
def ReadWord(self):
data = struct.unpack('>H', self.data[self.index:self.index + 2])[0]
data = struct.unpack_from('>H', self.data, self.index)[0]
self.index += 2
return data
def ReadInt(self):
data = struct.unpack('>i', self.data[self.index:self.index + 4])[0]
data = struct.unpack_from('>i', self.data, self.index)[0]
self.index += 4
return data
@@ -176,7 +73,7 @@ class HunkParser(object):
break
length = (longs & 0xffffff) * 4
extName = HunkExtMap.GetName(longs >> 24)
extName = GetHunkExtName(longs >> 24)
if extName in ['EXT_DEF', 'EXT_ABS', 'EXT_REL']:
data = self.ReadSymbol(length)
@@ -201,7 +98,7 @@ class HunkParser(object):
hunkRef = self.ReadLong()
offsets = [self.ReadLong() for i in range(longs)]
relocs.update({hunkRef: offsets})
relocs[hunkRef] = offsets
return relocs
@@ -217,7 +114,7 @@ class HunkParser(object):
hunkRef = self.ReadWord()
offsets = [self.ReadWord() for i in range(words)]
relocs.update({hunkRef: offsets})
relocs[hunkRef] = offsets
if (self.index - start) & 3:
self.index += 2
@@ -255,8 +152,8 @@ class HunkParser(object):
hunkId = self.ReadLong()
try:
flags = HunkMap.GetFlags(hunkId)
name = HunkMap.GetName(hunkId)
flags = GetHunkFlags(hunkId)
name = GetHunkName(hunkId)
except ValueError:
print 'Parse error at position %d.' % self.index
raise
+107
View File
@@ -0,0 +1,107 @@
from collections import namedtuple
HunkMap = {
'HUNK_UNIT': 999,
'HUNK_NAME': 1000,
'HUNK_CODE': 1001,
'HUNK_DATA': 1002,
'HUNK_BSS': 1003,
'HUNK_RELOC32': 1004,
'HUNK_RELOC16': 1005,
'HUNK_RELOC8': 1006,
'HUNK_EXT': 1007,
'HUNK_SYMBOL': 1008,
'HUNK_DEBUG': 1009,
'HUNK_END': 1010,
'HUNK_HEADER': 1011,
'HUNK_OVERLAY': 1013,
'HUNK_BREAK': 1014,
'HUNK_DREL32': 1015,
'HUNK_DREL16': 1016,
'HUNK_DREL8': 1017,
'HUNK_LIB': 1018,
'HUNK_INDEX': 1019,
'HUNK_RELOC32SHORT': 1020,
'HUNK_RELRELOC32': 1021,
'HUNK_ABSRELOC16': 1022,
'HUNK_PPC_CODE': 1257,
'HUNK_RELRELOC26': 1260
}
HunkExtMap = {
'EXT_SYMB': 0, # symbol table
'EXT_DEF': 1, # relocatable definition
'EXT_ABS': 2, # Absolute definition
'EXT_RES': 3, # no longer supported
'EXT_REF32': 129, # 32 bit absolute reference to symbol
'EXT_COMMON': 130, # 32 bit absolute reference to COMMON block
'EXT_REF16': 131, # 16 bit PC-relative reference to symbol
'EXT_REF8': 132, # 8 bit PC-relative reference to symbol
'EXT_DEXT32': 133, # 32 bit data relative reference
'EXT_DEXT16': 134, # 16 bit data relative reference
'EXT_DEXT8': 135, # 8 bit data relative reference
'EXT_RELREF32': 136, # 32 bit PC-relative reference to symbol
'EXT_RELCOMMON': 137, # 32 bit PC-relative reference to COMMON block
'EXT_ABSREF16': 138, # 16 bit absolute reference to symbol
'EXT_ABSREF8': 139, # 8 bit absolute reference to symbol
'EXT_RELREF26': 229
}
# Any hunks that have the HUNKB_ADVISORY bit set will be ignored if they
# aren't understood. When ignored, they're treated like HUNK_DEBUG hunks.
# NOTE: this handling of HUNKB_ADVISORY started as of V39 dos.library! If
# lading such executables is attempted under <V39 dos, it will fail with a
# bad hunk type.
HUNKB_ADVISORY = 29
HUNKB_CHIP = 30
HUNKB_FAST = 31
HunkFlagsMap = {
'HUNKF_ADVISORY': 1 << HUNKB_ADVISORY,
'HUNKF_CHIP': 1 << HUNKB_CHIP,
'HUNKF_FAST': 1 << HUNKB_FAST
}
def GetHunkName(number):
number &= 0x1fffffff
for name, value in HunkMap.items():
if value == number:
return name
raise ValueError('Unknown Hunk: %d' % number)
def GetHunkExtName(number):
for name, value in HunkExtMap.items():
if value == number:
return name
raise ValueError('Unknown HunkExt: %d' % number)
def GetHunkFlags(number):
flags = []
for name, value in HunkFlagsMap.items():
if value & number:
flags.append(name)
return flags
class Hunk(namedtuple('Hunk', 'name data flags')):
def __repr__(self):
if self.data:
if self.flags:
flags = ', flags=%s' % '|'.join(self.flags)
else:
flags = ''
return '%s(%r%s)' % (self.name, self.data, flags)
else:
return self.name
Header = namedtuple('Header', 'residents hunks first last specifiers')