Skip to content

Instantly share code, notes, and snippets.

@altendky
Forked from eliotb/aisgen.py
Last active March 20, 2019 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save altendky/28a99c9cc6d221264820ed56f90dc62d to your computer and use it in GitHub Desktop.
Save altendky/28a99c9cc6d221264820ed56f90dc62d to your computer and use it in GitHub Desktop.
Tools for working with Texas Instruments COFF and AIS files
#!/usr/bin/env python
'''Read fully linked TI COFF file, and generate AIS format file
Commandline parameters
enable sequential read,
pll and emifb configuration
pinmux configuration
enable checksums
'Eliot Blennerhassett' <eblennerhassett@audioscience.com>
AudioScience Inc. 2011
'''
from struct import pack, unpack
from collections import namedtuple
from ticoff import Coff
#from binascii import crc32
#from numpy import array, fromstring, uint32
class aisgen(object):
def __init__(self, aisgen_compatible=False):
self.funcs = {}
self.crc_enabled = False
self.aisgen_compatible = aisgen_compatible
self.verbosity = 0
def magic(self):
self.f.write(pack('<I', 0x41504954))
def enable_crc(self):
if self.verbosity > 1:
print 'Enable CRC'
self.crc_enabled = True
self.f.write(pack('<I', 0x58535903))
def disable_crc(self):
if self.verbosity > 1:
print 'Disable CRC'
self.crc_enabled = False
self.f.write(pack('<I', 0x58535904))
def validate_crc(self, crc, seek):
if self.verbosity > 1:
print 'Validate CRC 0x%08X, seek %d' % (crc, seek)
self.f.write(pack('<III', 0x58535902, crc, 0x100000000 + seek))
def section_load(self, s):
wlen = len(s.data)
odd = wlen % 4
write_data = s.data
npad = 0
spad = ''
if odd:
npad = (4 - odd)
write_data += ('\0' * npad)
#write_data += '\x48\x00\x00' # Test to match particular example from AISgen :(
spad = ' + %d bytes padding' % npad
command = pack('<I', 0x58535901)
if self.aisgen_compatible:
# Generate matching TI AISgen, size in header includes padding
if self.verbosity > 1:
print 'Load section 0x%X[0x%06X] %s' % (s.virt_addr, len(write_data), s.name)
params = pack('<II', s.virt_addr, len(write_data))
else:
# Generate according to spec, size in header excludes padding
if self.verbosity > 1:
print 'Load section 0x%X[0x%06X]%s %s' % (s.virt_addr, wlen, spad, s.name)
params = pack('<II', s.virt_addr, wlen)
crc_data = params + write_data
self.f.write(command + crc_data)
if self.crc_enabled and self.crc_calc:
crc = self.crc_calc(crc_data)
# Seek backwards, over section data + 2 headers
seek = -(len(crc_data) + 16)
self.validate_crc(crc, seek)
# These values obtained here:
# http://e2e.ti.com/support/dsp/tms320c6000_high_performance_dsps/f/115/p/118006/423501.aspx
fill_types = {'8bit' : 0, '16bit' : 1, '32bit' : 2}
def section_fill(self, addr, nbytes, fill):
remainder_to_fill_type = [2, 0, 1, 0]
if self.verbosity > 1:
print 'Fill section 0x%X[0x%06X] = 0x%X' % (addr, nbytes, fill)
odd = nbytes % 4
fill_type = remainder_to_fill_type[odd]
command = pack('<I', 0x5853590a)
params = pack('<IIII', addr, nbytes, fill_type, fill)
self.f.write(command + params)
if self.crc_enabled:
npad = 0
if odd:
npad = (4 - odd)
crc_data = params + chr(fill & 0xFF) * (nbytes + npad)
crc = self.crc_calc(crc_data)
seek = -(4 * (5 + 3)) # back over section fill + validate crc commands
self.validate_crc(crc, seek)
def section(self, s):
f = s.fill_value()
if f is not None:
self.section_fill(s.virt_addr, len(s.data), f)
else:
self.section_load(s)
def execute_function(self, fname, params):
if self.verbosity > 1:
print 'Execute function %s' % fname,
for p in params:
print '0x%X' % p,
print
fnum, nparams = self.funcs[fname]
if len(params) != nparams:
raise ValueError('Expected %d params for %s', nparams, fname)
fh = (len(params) << 16) + fnum
self.f.write(pack('<II', 0x5853590D, fh))
self.f.write(pack('<%dI' % len(params), *params))
PllAndClockParams = namedtuple('PllAndClockParams',
'pllm postdiv plldiv3 plldiv5 plldiv7 ' +
'clkmode pll_lock_cnt spi_prescale')
def pll_and_spi_clock_config(self, c):
'''expects parameters to be instance of PllAndClockParams'''
#print c
param1 = (c.pllm << 24) + (c.postdiv << 16) + (c.plldiv3 << 8) + c.plldiv5
param2 = (c.clkmode << 24) + (c.plldiv7 << 16) + c.pll_lock_cnt
self.execute_function('PLL and Clock Configuration', (param1, param2, c.spi_prescale))
EmifbParams = namedtuple('EmifbParams', 'sdcfg sdtim1 sdtim2 sdrfc')
def emifb_config(self, c):
'''expects parameters to be instance of EmifbParams'''
#print c
self.execute_function('EMIFB SDRAM Configuration', c)
def pinmux_config(self, c):
'''expects parameters to be 2 or 3 element tuple
(index, value [, mask])
'''
c = c + (0xFFFFFFFF, ) # default mask if not provided
self.execute_function('Pinmux Configuration', (c[0], c[2], c[1]))
def sequential_read(self):
if self.verbosity > 1:
print 'Sequential read enable'
self.f.write(pack('<I', 0x58535963))
def jump_and_close(self, addr):
if self.verbosity > 1:
print 'Jump and close 0x%X' % addr
self.f.write(pack('<II', 0x58535906, addr))
def generate(self, filename, coff, options):
if self.verbosity > 0:
print 'Generating for %s...' % self.rom,
load_sections = coff.loadable_sections
entry_point = coff.entry_point
with open(filename, 'wb') as self.f:
self.magic()
if options.sequential_read:
self.sequential_read()
if options.pll_config:
pll_params = eval('self.PllAndClockParams(%s)' % options.pll_config)
self.pll_and_spi_clock_config(pll_params)
if options.emifb_config:
emifb_params = eval('self.EmifbParams(%s)' % options.emifb_config)
self.emifb_config(emifb_params)
for c in options.pinmux_config:
params = eval('(%s)' % c)
self.pinmux_config(params)
if options.enable_crc:
self.enable_crc()
for s in load_sections:
self.section(s)
self.jump_and_close(entry_point)
class aisgen_d800k001(aisgen):
'''Instance of aisgen that implements ROM d800k001
CRC calculation and special functions'''
def __init__(self):
aisgen.__init__(self)
self.rom = 'd800k001'
self.funcs = {
# func name : (id, param count)
'PLL0 Configuration' : (0, 2),
'Peripheral Clock Configuration' : (1, 1),
'EMIFB SDRAM Configuration' : (2, 4),
'EMIFA SDRAM Configuration' : (3, 4),
'EMIFA CE Space Configuration' : (4, 4),
'PLL and Clock Configuration' : (5, 3),
}
def _crc_calc_direct(self, data, crc=0):
'''Reference implementation of CRC
Process 32 bit words MSB first
Data is little endian. Very SLOW!'''
words = fromstring(data, dtype=uint32)
for word in words:
bit_no = 31;
while bit_no >= 0:
msb_bit = crc & 0x80000000
crc = ((word >> bit_no) & 0x1) | (crc << 1)
if msb_bit:
crc ^= 0x04C11DB7
bit_no -= 1
return crc & 0xFFFFFFFF
def crc_calc(self, in_str, crc=0):
'''Generate CRC to match TI AISgen output, from data zero padded to N*4 bytes.
This is not the same as standard CRC calculation, lacking the augmentation of
the input data with 32 zero bits.
Applies to C6747/5/3 devices ROM d800k003, but not C6748/6/2, see
http://e2e.ti.com/support/dsp/tms320c6000_high_performance_dsps/f/115/p/119062/426491.aspx
'''
nbytes = len(in_str)
for w in range(0, nbytes, 4):
# in-place endian reversal to
# process little endian words MSbyte first
for b in range(3, -1, -1):
ofs = w + b
c = in_str[ofs]
octet = ord(c)
for i in range(8):
topbit = crc & 0x80000000
crc = ((octet >> (7 - i)) & 0x01) | ((crc << 1) & 0xFFFFFFFF)
if topbit:
crc ^= 0x04C11DB7
return crc
class aisgen_d800k003(aisgen_d800k001):
'''Instance of aisgen that implements ROM d800k003
CRC calculation and special functions'''
def __init__(self):
aisgen_d800k001.__init__(self)
self.rom = 'd800k003'
self.funcs['Power and Sleep Controller Configuration'] = (6, 1)
self.funcs['Pinmux Configuration'] = (7, 3)
roms = {
'd800k001' : aisgen_d800k001,
'd800k003' : aisgen_d800k003
}
if __name__ == '__main__':
from optparse import OptionParser
from sys import exit
parser = OptionParser(usage='%prog [options] input.coff output.ais')
parser.add_option('-c', '--enable-crc', action='store_true',
default=False, help='enable per-section CRCs')
parser.add_option('-r', '--rom', action='store', choices=roms.keys(), metavar='ROM_VERSION',
default='d800k003', help='one of %s' % roms.keys())
parser.add_option('-s', '--sequential-read', action='store_true',
default=False, help='use SPI sequential read')
parser.add_option('-v', '--verbosity', action='store', type='int',
default=1, help='verbosity of output')
parser.add_option('-b', '--emifb-config', action='store', type='string',
help='E.g. --emifb-config="sdcfg=0x10620, sdtim1=0x01912a08, sdtim2=0x70080005, sdrfc=0x8000079e"')
parser.add_option('-p', '--pll-config', action='store', type='string',
help='E.g. --pll-config="pllm=29, postdiv=1, plldiv3=3, plldiv5=2, plldiv7=5, clkmode=1, pll_lock_cnt=402, spi_prescale=6"')
parser.add_option('-m', '--pinmux-config', action='append', type='string',
default=[], help='PINMUX_CONFIG=regnum,value[,optional mask]. May be used more than once\n'+
'E.g. --pinmux-config=0,0x10011101 -m1,0x1001,0xFFFF')
options, args = parser.parse_args()
#
if args[0][0] == '@':
fa = []
with open(args[0][1:]) as f:
for l in f:
fa.append(l.strip())
fa = fa + args[1:]
options, args = parser.parse_args(args=fa, values=options)
if len(args) < 2:
parser.print_help()
exit()
coff = Coff(args[0])
gen = roms[options.rom]()
gen.verbosity = options.verbosity
gen.generate(args[1], coff, options)
if options.verbosity:
print 'Finished'
#!/usr/bin/env python
"""
Parse AIS file, and optionally generate C array
"Eliot Blennerhassett" <eblennerhassett@audioscience.com>
AudioScience Inc. 2011
"""
import os
import struct
import sys
from optparse import OptionParser
def read(format):
datalen = struct.calcsize(format)
data = Input.read(datalen)
if len(data) != datalen:
raise EOFError
ret = struct.unpack(format, data)
if len(ret) < 2:
ret = ret[0]
return ret
def section_load():
address = read('I')
size = read('I')
# data length is rounded up from size to multiple o4
data = read('%dI' % ((size + 3) / 4))
try:
len(data)
except TypeError:
data = [data]
print '// Section load %#x[%#x]' % (address, size)
if all([d == data[0] for d in data]):
print '// ^ could use Section fill with %#x command' % data[0]
if gen_h:
print '%#x, %#x,' % (address, size)
for i in xrange(len(data)):
print '0x%08x,' % data[i],
if not((i + 1) % 8):
print
if (i + 1) % 8:
print
def section_fill():
address = read('I')
size = read('I')
type = read('I')
pattern = read('I')
print '// Section Fill type %d %#x[%#x] = %#x' % (type, address, size, pattern)
if gen_h:
print '%#x, %#x, %#x, %#x' % (address, size, type, pattern)
def boot_table():
type = read('I')
address = read('I')
data = read('I')
sleep = read('I')
print '// Boot table type %d *%#x = %#x, sleep %d' % (type, address, data, sleep )
if gen_h:
print '%#x, %#x, %#x, %#x' % (type, address, data, sleep)
# This function list comes from sprab1b.pdf 'Using the TMS320C6747/45/43 Bootloader'
funcs = {
0 : ('PLL0 Configuration', 2),
1 : ('Peripheral Clock Configuration', 1),
2 : ('EMIFB SDRAM Configuration', 4),
3 : ('EMIFA SDRAM Configuration', 4),
4 : ('EMIFA CE Space Configuration', 4),
5 : ('PLL and Clock Configuration', 3),
6 : ('Power and Sleep Controller Configuration', 1),
7 : ('Pinmux Configuration', 3),
}
def function_execute():
arg = read('I')
func = arg & 0xFFFF
ac = (arg & 0xFFFF0000) >> 16
try:
fn, ac1 = funcs[func]
except KeyError:
fn = 'Unkown %#x' % func
ac1 = 0
assert ac == ac1, 'Arg count mismatch %d %d' % (ac, ac1)
print '// Function %d : %s(' % (func, fn),
args = []
for i in range(ac):
args.append(read('I'))
print '%#x, ' % args[i],
print ')'
if gen_h:
print '%#x,' % arg,
for i in range(ac):
print '%#x, ' % args[i],
print
def jump_and_close():
address = read('I')
print '// Close and jump to %#x' % address
if gen_h:
print '%#x,' % address
def jump(op):
address = read('I')
print '// Jump to %#x' % address
if gen_h:
print '%#x,' % address
def validate_crc():
crc = read('I')
seek = read('I')
print '// Validate CRC %#x, seek %x' % (crc, seek)
if gen_h:
print '%#x, %#x,' % (crc, seek)
def enable_crc():
print '// Enable CRC'
def disable_crc():
print '// Enable CRC'
def sequential_read():
print '// Sequential read enable'
opcodes = {
0x58535901 : section_load,
0x58535902 : validate_crc,
0x58535903 : enable_crc,
0x58535904 : disable_crc,
0x58535905 : jump,
0x58535906 : jump_and_close,
0x58535907 : boot_table,
0x5853590a : section_fill,
0x5853590D : function_execute,
0x58535963 : sequential_read,
}
parser = OptionParser()
parser.add_option("-g", "--generate-header",
action="store_true", dest="gen_h", default=False,
help="generate full header file on stdout")
(options, args) = parser.parse_args()
fname = args[0]
fsize = os.path.getsize(fname)
gen_h = options.gen_h
if gen_h:
print '''// Generated from %s
#include <stdint.h>
uint32_t ais_array[] = {'''
with open (fname, 'rb') as Input:
magic = read('I')
if not (magic == 0x41504954):
sys.exit('Incorrect magic, not an AIS file?')
print '// AIS magic ID'
if gen_h:
print '%#x,' % magic
while True:
try:
opcode = read('I')
except EOFError:
break
try:
command = opcodes[opcode]
except KeyError:
print 'unknown opcode %#x' % opcode
if gen_h:
print '%#x,' % opcode,
command()
if gen_h:
print '};'
assert Input.tell() == fsize, 'file not consumed?'
#!/usr/bin/env python
'''Read TI pinmux data files, and pinmux config file
and generate pinmux register values, and comments.
Requires mux[1-5].txt from TI pinsetup utility OMAP-L1x7_C6747-5-3_pinsetup
There are 20 pinmux registers, each with 8 4-bit fields
"Eliot Blennnerhassett" <eblennerhassett@audioscience.com>
'''
from sys import exit
def read_pin_data():
'''Read pin data into 2 dictionaries.
pd key is pin function name, value is (reg_idx, field_idx, field value, ?)
pf key (reg_idx, field_idx), value is [list of pin names]
pin data files contain lines like
AXR0[0],10,1,1,830
pin_func_name, reg_idx, field_idx, field_value, ??
not sure what the last value represents?
'''
pd = {} # setups per pin function
pf = {} # pin functions per register field
for fi in range(1, 6):
fn = 'mux%d.txt' % fi
with open(fn) as f:
for l in f:
t = l.strip().split(',')
if len(l) < 5:
continue
pin_name = t[0]
p = tuple([int(s) for s in t[1:]])
pi = p[0:2]
# ((reg_idx, field_idx) : ['pin_name', ...]
if pf.has_key(pi):
pf[pi].append(pin_name)
else:
pf[pi] = [pin_name]
# 'pin_name' : (reg_idx, field_idx, field value, ?)
pd[pin_name] = p
return pd, pf
def read_pin_config(fn, pd):
'''read pin config from file named fn, and add pinmux setup data from pd
pin config is a list of pin function names, one per line
'''
pins = []
with open(fn) as f:
for l in f:
n = l.strip()
if not len(n):
continue
ps = pd[n]
pins.append((n, ps))
return pins
def print_alpha_pinlist(pins):
'''print list of pin names in alphabetical order'''
pins.sort() # pin name order
print '/*\nDefined pins:',
wrap = 0
for pin in pins:
if wrap > 70:
print
wrap = 0
print pin[0],
wrap += len(pin[0]) + 1
print '\n*/'
def print_muxfield_pinlist(pins):
'''print list of pin names grouped by mux field value'''
pins.sort(key=lambda p : (p[1][2], p[1][0], p[1][1]))
prev_mux = None
print '/*\nPins by mux field setting:',
for pin in pins:
mux = pin[1][2]
if mux != prev_mux:
print '\n\nMUX%d Pins:' % mux
prev_mux = mux
wrap = 0
if wrap > 70:
print
wrap = 0
print pin[0],
wrap += len(pin[0]) + 1
print '\n*/'
def print_pinmux_pinlist(pins):
'''print list of pin names grouped by pinmux register'''
pins.sort(key=lambda p : (p[1][0], p[1][1]))
print '/* Pins by pinmux register'
prev_regidx = None
for pin in pins:
regidx = pin[1][0]
if regidx != prev_regidx:
print '\npinmux[%d] pins' % regidx
prev_regidx = regidx
print pin[0],
print '\n*/'
def calculate_pinmux_values(pins, pd, pf):
'''convert the selected pin data into appropriate bitfields
in registers
'''
regs = [0] * 20
error = False
for pin in pins:
ps = pin[1]
reg = ps[0]
field_ofs = ps[1] * 4
field_mask = 0xF << field_ofs
field_val = ps[2] << field_ofs
if (regs[reg] & field_mask):
fv = (regs[reg] & field_mask) >> field_ofs
# find which pin already assigned to the field
current = (reg, ps[1], fv)
shared = pf[ps[0:2]]
for name in shared:
id = pd[name][0:3]
if current == id:
break;
print 'Conflict setting %s : pinmux[%d][%d] already set to %s' % (pin[0], reg, ps[1], name)
error = True
else:
regs[reg] = regs[reg] | field_val;
if error:
exit(1)
return regs
formats = {
'aisgen' : '--pinmux-config=%d,0x%08X',
'array' : '\t/* %d */ 0x%08X,',
'define' : '#define PINMUX%d_VALUE 0x%08X',
}
def print_pinmux_values(format, regs):
'''print the pinmux register value list
formatted for various uses
'''
fs = formats[format]
if format == 'array':
print 'unsigned int pinmux_values = {'
for i in range(len(regs)):
print fs % (i, regs[i])
if format == 'array':
print '};'
def print_known_pins(pf):
pl = list( pf.iteritems())
pl.sort(key=lambda p : (p[0][0], p[0][1]))
for p in pl:
print 'pinmux %s selects %s' % p
if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser(usage='%prog [options] input.pin')
parser.add_option('-a', '--print-alpha', action='store_true',
default=False, help='Print alphabetical pinlist comment')
parser.add_option('-m', '--print-muxfield', action='store_true',
default=False, help='Print pinlist by mux value comment')
parser.add_option('-r', '--print-register', action='store_true',
default=False, help='Print pinlist by register comment')
parser.add_option('-f', '--format', action='store', choices=formats.keys(),
default='define', help='one of %s' % formats.keys())
parser.add_option('-p', '--print-known', action='store_true',
default=False, help='print known pins')
options, args = parser.parse_args()
pd, pf = read_pin_data()
if options.print_known:
print_known_pins(pf)
exit(0)
pins = read_pin_config(args[0], pd)
regs = calculate_pinmux_values(pins, pd, pf)
if options.print_alpha:
print_alpha_pinlist(pins)
if options.print_muxfield:
print_muxfield_pinlist(pins)
if options.print_register:
print_pinmux_pinlist(pins)
print_pinmux_values(options.format, regs)
#!/usr/bin/env python
"""
Read TI COFF file into a python object
"Eliot Blennerhassett" <eblennerhassett@audioscience.com>
AudioScience Inc. 2011
"""
from __future__ import print_function
from builtins import bytes, object, range
from array import array
from collections import namedtuple
from optparse import OptionParser
from struct import unpack, calcsize
def read_struct(file, format):
'''read struct data formatted according to format'''
datalen = calcsize(format)
data = file.read(datalen)
if len(data) != datalen:
raise EOFError
ret = unpack(format, data)
if len(ret) < 2:
ret = ret[0]
return ret
def read_cstr(file):
'''read zero terminated c string from file'''
output = ""
while True:
char = file.read(1)
if len(char) == 0:
raise RuntimeError ("EOF while reading cstr")
char = chr(bytes(char)[0])
if char == '\0':
break
output += char
return output
# From spraao8.pdf table 7
class Section(namedtuple('Section',
'name, virt_size, virt_addr, raw_data_size, raw_data_ptr, relocation_ptr,' +
'linenum_ptr, linenum_count, reloc_count, flags, reserved, mem_page, data')):
__slots__ = () # prevent creation of instance dictionaries
section_fmt = '<8s9L2H'
section_flags = [
(0x00000001, 'STYP_DSECT'), (0x00000002, 'STYP_NOLOAD'),
(0x00000004, 'STYP_GROUPED'), (0x00000008, 'STYP_PAD'),
(0x00000010, 'STYP_COPY'), (0x00000020, 'STYP_TEXT'),
(0x00000040, 'STYP_DATA'), (0x00000080, 'STYP_BSS'),
(0x00000100, 'STYP_100'), (0x00000200, 'STYP_200'),
(0x00000200, 'STYP_400'), (0x00000800, 'STYP_800'),
(0x00001000, 'STYP_BLOCK'), (0x00002000, 'STYP_PASS'),
(0x00004000, 'STYP_CLINK'),(0x00008000, 'STYP_VECTOR'),
(0x00010000, 'STYP_PADDED'),
]
@property
def is_zero_filled(self):
return (self.data is not None) and not any([d != '\0' for d in self.data])
def fill_value(self):
if self.data is None:
return None
if len(self.data) % 4:
return None # only handle 32 bit fill
a = array('I', self.data)
if all([d == a[0] for d in a]):
return a[0]
else:
return None
@property
def is_loadable(self):
return not(self.flags & 0x00000010 or self.data is None)
def __str__(self):
s = 'Section %s' % self.name
if self.flags:
s += ' Flags ='
for f in Section.section_flags:
if self.flags & f[0]:
s = s + ' ' + f[1]
for fv in self._asdict().items():
if fv[0] == 'data' or fv[0] == 'name': continue
s = s + '\n\t%s = 0x%X' % fv
return s
class Coff(object):
Header = namedtuple('Header',
'machine_type, section_count, time_date, symbol_table_ptr, ' +
'symbol_count, optional_header_size, flags, target_id')
header_fmt = '<2H3L3H'
OptionalHeader = namedtuple('OptionalHeader',
'magic, version, exe_size, init_data_size, uninit_data_size, entry_point, exe_start, init_start')
optheader_fmt = '<2H6L'
def __init__(self, filename=None):
self.header = None
self.optheader = None
self.sections = []
if filename is not None:
self.from_file(filename)
def from_file(self, name):
with open(name, 'rb') as f:
self.from_stream(f)
def from_stream(self, f):
self.header = self.Header(*read_struct(f, self.header_fmt))
self.optheader = self.OptionalHeader(*read_struct(f, self.optheader_fmt))
self.sections = []
for i in range(self.header.section_count):
section = Section(*read_struct(f, Section.section_fmt), data=None)
section = section._replace(name=self.symname(f, section.name))
if section.raw_data_ptr and section.raw_data_size:
here = f.tell()
f.seek(section.raw_data_ptr)
# TODO: `2 *` is hard coded to handle the 2-bytes per
# address scenario. This should obviously be
# detected somehow, unless it is always correct.
data = bytes(f.read(2 * section.raw_data_size))
f.seek(here)
section = section._replace(data=data)
self.sections.append(section)
self.entry_point = self.optheader.entry_point
self.sections.sort(key=lambda s: s.virt_addr)
@property
def loadable_sections(self):
return [s for s in self.sections if s.is_loadable]
def string_table_entry (self, f, offset):
here = f.tell()
seek = self.header.symbol_table_ptr + self.header.symbol_count * 18 + offset
f.seek(seek)
s = read_cstr(f)
f.seek(here)
return s
def symname(self, f, value):
parts = unpack("<2L", value)
if parts[0] == 0:
return self.string_table_entry(f, parts[1])
else:
return str(value.decode('ascii').rstrip('\0'))
def __str__(self):
s = 'TI coff file'
if self.header is not None:
for fv in self.header._asdict().items():
s = s + '\n\t%s = 0x%X' % fv
if self.optheader is not None:
s += '\nOptional Header'
for fv in self.optheader._asdict().items():
s = s + '\n\t%s = 0x%X' % fv
return s
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-d", "--dump_data",
action="store_true", dest="dump", default=False,
help="dump section data")
options, args = parser.parse_args()
c = Coff(args[0])
print(c)
for section in c.sections:
print(section)
if section.data is not None and options.dump:
print(repr(section))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment