Mercurial > lcfOS
view python/ppci/objectfile.py @ 377:9667d78ba79e
Switched to xml for project description
author | Windel Bouwman |
---|---|
date | Fri, 11 Apr 2014 15:47:50 +0200 |
parents | 86b02c98a717 |
children | 0c44e494ef58 |
line wrap: on
line source
""" Object files are used to store assembled code. Information contained is code, symbol table and relocation information. """ import json import binascii from . import CompilerError class Symbol: def __init__(self, name, value, section): self.name = name self.value = value self.section = section def __repr__(self): return 'SYM {}, val={} sec={}'.format(self.name, self.value, self.section) def __eq__(self, other): return (self.name, self.value, self.section) == \ (other.name, other.value, other.section) class Relocation: """ Represents a relocation entry. A relocation always has a symbol to refer to and a relocation type """ def __init__(self, sym, offset, typ, section): self.sym = sym self.offset = offset self.typ = typ self.section = section def __repr__(self): return 'RELOC {} off={} t={} sec={}'.format(self.sym, self.offset, self.typ, self.section) def __eq__(self, other): return (self.sym, self.offset, self.typ, self.section) ==\ (other.sym, other.offset, other.typ, other.section) class Section: def __init__(self, name): self.name = name self.address = 0 self.data = bytearray() def add_data(self, data): self.data += data @property def Size(self): return len(self.data) def __repr__(self): return 'SECTION {}'.format(self.name) def __eq__(self, other): return (self.name == other.name) and (self.address == other.address) \ and (self.data == other.data) class ObjectFile: """ Container for sections with compiled code or data. Also contains symbols and relocation entries """ def __init__(self): self.symbols = {} self.sections = {} self.relocations = [] def find_symbol(self, name): return self.symbols[name] def add_symbol(self, name, value, section): if name in self.symbols: raise CompilerError('{} already defined'.format(name)) assert section in self.sections sym = Symbol(name, value, section) self.symbols[name] = sym return sym def add_relocation(self, sym_name, offset, typ, section): assert type(sym_name) is str, str(sym_name) assert section in self.sections # assert sym_name in self.symbols reloc = Relocation(sym_name, offset, typ, section) self.relocations.append(reloc) return reloc def get_section(self, name): if not name in self.sections: self.sections[name] = Section(name) return self.sections[name] def __eq__(self, other): return (self.symbols == other.symbols) and \ (self.sections == other.sections) and \ (self.relocations == other.relocations) def save(self, f): save_object(self, f) def save_object(o, f): json.dump(serialize(o), f, indent=2, sort_keys=True) def load_object(f): return deserialize(json.load(f)) def serialize(x): res = {} if isinstance(x, ObjectFile): res['sections'] = [] for sname in sorted(x.sections.keys()): s = x.sections[sname] res['sections'].append(serialize(s)) res['symbols'] = [] for sname in sorted(x.symbols.keys()): s = x.symbols[sname] res['symbols'].append(serialize(s)) res['relocations'] = [] for reloc in x.relocations: res['relocations'].append(serialize(reloc)) elif isinstance(x, Section): res['name'] = x.name res['address'] = hex(x.address) res['data'] = binascii.hexlify(x.data).decode('ascii') elif isinstance(x, Symbol): res['name'] = x.name res['value'] = hex(x.value) res['section'] = x.section elif isinstance(x, Relocation): res['symbol'] = x.sym res['offset'] = hex(x.offset) res['type'] = x.typ res['section'] = x.section return res def deserialize(d): obj = ObjectFile() for section in d['sections']: so = obj.get_section(section['name']) so.address = int(section['address'][2:], 16) so.data = bytearray(binascii.unhexlify(section['data'].encode('ascii'))) for reloc in d['relocations']: obj.add_relocation(reloc['symbol'], int(reloc['offset'][2:], 16), reloc['type'], reloc['section']) for sym in d['symbols']: obj.add_symbol(sym['name'], int(sym['value'][2:], 16), sym['section']) return obj