diff --git a/tools/dumphunks.py b/tools/dumphunks.py index 3b2ff34..9350d4e 100755 --- a/tools/dumphunks.py +++ b/tools/dumphunks.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2.7 -B import sys -from objtools.hunk import HunkParser +from objtools import hunk if __name__ == '__main__': @@ -9,6 +9,6 @@ if __name__ == '__main__': print 'Parsing "%s".' % path print '' - for hunk in HunkParser(path): - hunk.dump() + for h in hunk.ReadFile(path): + h.dump() print '' diff --git a/tools/objtools/aout.py b/tools/objtools/aout.py index d9c6aa4..6ddefa0 100644 --- a/tools/objtools/aout.py +++ b/tools/objtools/aout.py @@ -1,4 +1,5 @@ from collections import namedtuple, Sequence +import logging import os import struct from util import hexdump @@ -12,6 +13,9 @@ class Header(namedtuple('Header', ('mid', 'magic', 'text', 'data', 'bss', @classmethod def decode(cls, data): + if len(data) != 32: + raise ValueError('Not a valid a.out header!') + mid, magic, text, data, bss, syms, entry, trsize, drsize = \ struct.unpack('>HHIIIIIII', data) @@ -169,8 +173,8 @@ class Aout(object): self._path = path with open(path) as data: - print 'Reading {0} of size {1} bytes.'.format( - repr(path), os.stat(path)[6]) + logging.debug('Reading %r of size %d bytes.', + path, os.stat(path).st_size) self._header = Header.decode(data.read(32)) @@ -183,7 +187,7 @@ class Aout(object): strings = data.read() if str_size != len(strings): - print 'Warning: wrong size of string table!' + logging.warn('Wrong size of string table!') self._strings = StringTable.decode(strings) @@ -226,3 +230,9 @@ class Aout(object): for reloc in self._text_relocs: print ' ', reloc.as_string(self._strings) print '' + + +def ReadFile(path): + aout = Aout() + aout.read(path) + return aout diff --git a/tools/objtools/ar.py b/tools/objtools/ar.py index cf86f85..b3b35f6 100644 --- a/tools/objtools/ar.py +++ b/tools/objtools/ar.py @@ -1,3 +1,4 @@ +import logging import os import struct @@ -12,7 +13,7 @@ class ArEntry(namedtuple('ArEntry', struct.unpack('16s12s6s6s8s10s2s', ar.read(60)) length = int(length.strip()) - modtime = int(modtime.strip()) + modtime = int(modtime.strip() or '0') owner = int(owner.strip() or '0') group = int(group.strip() or '0') mode = mode.strip() or '100644' @@ -38,11 +39,18 @@ def ReadFile(path): with open(path) as ar: if ar.read(8) != '!\n': - raise RuntimeError('%s is not an ar archive', path) + raise ValueError('%s is not an ar archive' % path) ar_size = os.stat(path).st_size + logging.debug('Reading ar archive %r of size %d bytes.', path, ar_size) + while ar.tell() < ar_size: - entries.append(ArEntry.decode(ar)) + # Some archives have version information attached at the end of file, + # that confuses ArEntry parser, so just skip it. + try: + entries.append(ArEntry.decode(ar)) + except struct.error: + break return entries diff --git a/tools/objtools/hunk.py b/tools/objtools/hunk.py index d841d19..b6a74c4 100644 --- a/tools/objtools/hunk.py +++ b/tools/objtools/hunk.py @@ -1,3 +1,4 @@ +import logging import os import struct import textwrap @@ -35,6 +36,8 @@ HunkMap = { 'HUNK_ABSRELOC16': 1022 } +HunkMapRev = dict((v, k) for k, v in HunkMap.items()) + HunkExtMap = { 'EXT_SYMB': 0, # symbol table 'EXT_DEF': 1, # relocatable definition @@ -53,6 +56,8 @@ HunkExtMap = { 'EXT_ABSREF8': 139 # 8 bit absolute reference to symbol } +HunkExtMapRev = dict((v, k) for k, v in HunkExtMap.items()) + # 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 @@ -80,11 +85,10 @@ class Hunk(object): def getType(number): number &= 0x1fffffff - for name, value in HunkMap.items(): - if value == number: - return name - - raise ValueError('Unknown Hunk: %d' % number) + try: + return HunkMapRev[number] + except KeyError: + raise ValueError('Unknown Hunk: %d' % number) @staticmethod def getFlags(number): @@ -324,11 +328,10 @@ class HunkExt(Hunk): @staticmethod def getType(number): - for name, value in HunkExtMap.items(): - if value == number: - return name - - raise ValueError('Unknown HunkExt: %d' % number) + try: + return HunkExtMapRev[number] + except KeyError: + raise ValueError('Unknown HunkExt: %d' % number) @classmethod def parse(cls, hf): @@ -594,7 +597,7 @@ HunkClassMap = { } -def HunkParser(path): +def ReadFile(path): with HunkFile(path) as hf: hunks = [] units = 0 @@ -621,7 +624,7 @@ def HunkParser(path): try: hunks.append(hunk.parse(hf)) except ValueError: - print 'Parse error at position 0x%x.' % hf.tell() + logging.error('Parse error at position 0x%x.', hf.tell()) util.hexdump(hf.read()) return hunks