diff 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 diff
--- a/python/ppci/objectfile.py	Tue Mar 25 19:36:51 2014 +0100
+++ b/python/ppci/objectfile.py	Fri Apr 11 15:47:50 2014 +0200
@@ -4,6 +4,8 @@
 is code, symbol table and relocation information.
 """
 
+import json
+import binascii
 from . import CompilerError
 
 class Symbol:
@@ -15,6 +17,10 @@
     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
@@ -28,6 +34,10 @@
     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):
@@ -45,6 +55,10 @@
     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.
@@ -68,6 +82,7 @@
     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
@@ -76,3 +91,64 @@
         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
+