History

Added basic writing support. Removed the string representations of instructions and changed instruction reading to ensure that an instance of a specific class is created for each instruction. Fixed the definition of the frame instruction.

David Boddie committed 9 years ago

Commit 9bbb0591 parent b2622162 files · +245 −57Browse files

Unified · Split

2 files
  1. dis.py +187 −13
  2. opcodes.py +58 −44
dis.py+187−13
@@ -19,7 +19,9 @@ from struct import calcsize, pack, unpack · 18 unmodified lines
19 19
20import opcodes20import opcodes
21from utils import _read, read_B, read_C, read_OP, read_F, read_L, read_P, \21from utils import _read, read_B, read_C, read_OP, read_F, read_L, read_P, \
22 read_W22 read_W, \
23 _write, write_B, write_C, write_OP, write_F, write_L, \
24 write_P, write_W
23 25
24XMAGIC = 0x0c803026XMAGIC = 0x0c8030
25SMAGIC = 0x0e172227SMAGIC = 0x0e1722
@@ -72,6 +74,7 @@ class Dis: · 46 unmodified lines
72 self.entry_pc = read_OP(f)74 self.entry_pc = read_OP(f)
73 self.entry_type = read_OP(f)75 self.entry_type = read_OP(f)
74 76
77 # Read the other sections.
75 self.read_code(f)78 self.read_code(f)
76 self.read_types(f)79 self.read_types(f)
77 self.read_data(f)80 self.read_data(f)
@@ -114,6 +117,7 @@ class Dis: · 36 unmodified lines
114 # Use a list as a load address stack with an initial base address of 0.117 # Use a list as a load address stack with an initial base address of 0.
115 addresses = []118 addresses = []
116 base = 0119 base = 0
120 type_ = None
117 121
118 while True:122 while True:
119 123
@@ -139,20 +143,26 @@ class Dis: · 19 unmodified lines
139 type_index = _read(f, ">I")143 type_index = _read(f, ">I")
140 length = _read(f, ">I")144 length = _read(f, ">I")
141 type_ = self.types[type_index]145 type_ = self.types[type_index]
142 #print "Array", type_, type_.size, length146 #print "Array", offset
147
143 elif array_type == 6:148 elif array_type == 6:
144 # Set array address149 # Set array index
145 index = _read(f, ">I")150 index = _read(f, ">I")
146 #print "Set array address", index, "(offset=%i)" % offset151 # Store the current base first.
147 addresses.append(base)152 addresses.append(base)
153 #print "Set", base, offset, index
148 base = offset + index154 base = offset + index
155
149 elif array_type == 7:156 elif array_type == 7:
150 # Restore load address157 # Restore load address
151 #print "Restore load address"
152 base = addresses.pop()158 base = addresses.pop()
159 type_ = None
160 #print "Restore", base, offset
161
153 else:162 else:
163 #print "Data", offset
154 address = base + offset164 address = base + offset
155 item = Data(f, code, count, address, array_type)165 item = Data(f, code, count, offset, base, array_type, type_)
156 self.data_items.append(item)166 self.data_items.append(item)
157 if address in self.data:167 if address in self.data:
158 print "Overwriting existing data item at %x." % address168 print "Overwriting existing data item at %x." % address
@@ -183,11 +193,109 @@ class Dis: · 24 unmodified lines
183 if value == 0:193 if value == 0:
184 break194 break
185 195
196 sequence = []
197
186 i = 0198 i = 0
187 while i < value:199 while i < value:
188 200
189 self.ldt.append(LDT(f))201 sequence.append(LDT(f))
190 i += 1202 i += 1
203
204 self.ldt.append(sequence)
205
206 def write(self, f):
207
208 # Write the header.
209 self.code_size = len(self.code)
210
211 # Only unsigned files are currently supported.
212 write_OP(f, XMAGIC)
213
214 self.runtime_flag.write(f)
215 write_OP(f, self.stack_extent)
216 write_OP(f, self.code_size)
217 write_OP(f, self.data_size)
218 write_OP(f, self.type_size)
219 write_OP(f, self.link_size)
220 write_OP(f, self.entry_pc)
221 write_OP(f, self.entry_type)
222
223 # Write the other sections.
224 self.write_code(f)
225 self.write_types(f)
226 self.write_data(f)
227
228 write_C(f, self.module_name)
229
230 self.write_link(f)
231
232 if self.runtime_flag.contains(RuntimeFlag.HASLDT):
233 self.write_ldt(f)
234
235 write_C(f, self.path)
236
237 def write_code(self, f):
238
239 for ins in self.code:
240 ins.write(f)
241
242 def write_types(self, f):
243
244 for type_ in self.types:
245 type_.write(f)
246
247 def write_data(self, f):
248
249 # Sort the dictionary items by address.
250 items = self.data.items()
251 items.sort()
252
253 addresses = []
254 base = 0
255
256 for address, item in items:
257
258 if item.base != base:
259
260 # Array
261 write_B(f, 0x51) # use count=1 to save a word
262 write_OP(f, item.base - base) # offset
263 _write(f, ">I", self.types.index(item.type_))
264 _write(f, ">I", len(item.data))
265
266 # Set array address
267 write_B(f, 0x61) # use count=1 to save a word
268 write_OP(f, item.base - base) # offset
269 _write(f, ">I", 0) # index
270
271 item.write(f)
272
273 if item.base != base:
274
275 # Restore load address
276 write_B(f, 0x71) # use count=1 to save a word
277 write_OP(f, 0) # offset
278 base = addresses.pop()
279
280 write_OP(f, 0)
281
282 def write_link(self, f):
283
284 for link in self.link:
285 link.write(f)
286
287 def write_ldt(self, f):
288
289 write_OP(f, self.initialised_globals)
290
291 for sequence in self.ldt:
292
293 write_OP(f, len(sequence))
294
295 for ldt in sequence:
296 ldt.write(f)
297
298 write_OP(f, 0)
191 299
192 def list(self):300 def list(self):
193 301
@@ -213,6 +321,9 @@ class RuntimeFlag: · 19 unmodified lines
213 def contains(self, flags):321 def contains(self, flags):
214 322
215 return self.value & flags != 0323 return self.value & flags != 0
324
325 def write(self, f):
326 write_OP(f, self.value)
216 327
217 328
218class Type:329class Type:
@@ -224,6 +335,11 @@ class Type: · 5 unmodified lines
224 self.number_ptrs = read_OP(f)335 self.number_ptrs = read_OP(f)
225 self.array = f.read(self.number_ptrs)336 self.array = f.read(self.number_ptrs)
226 337
338 def __repr__(self):
339
340 return "Type(desc=%i, size=%i, ptrs=%i)" % (self.desc_number,
341 self.size, self.number_ptrs)
342
227 def is_pointer(self, address):343 def is_pointer(self, address):
228 344
229 # Each bit in the array represents a word in the type. If the bit is 1345 # Each bit in the array represents a word in the type. If the bit is 1
@@ -236,6 +352,13 @@ class Type: · 6 unmodified lines
236 # Check whether the bit is 1 or 0, returning True for 1 and False for 0.352 # Check whether the bit is 1 or 0, returning True for 1 and False for 0.
237 mask = 1 << (bit % 8)353 mask = 1 << (bit % 8)
238 return (ord(byte) & mask) != 0354 return (ord(byte) & mask) != 0
355
356 def write(self, f):
357
358 write_OP(f, self.desc_number)
359 write_OP(f, self.size)
360 write_OP(f, self.number_ptrs)
361 f.write(self.array)
239 362
240 363
241class Data:364class Data:
@@ -244,12 +367,14 @@ class Data: · 2 unmodified lines
244 "UTF-8 encoded string", "64-bit float", "Array",367 "UTF-8 encoded string", "64-bit float", "Array",
245 "Set array address", "Restore load address"]368 "Set array address", "Restore load address"]
246 369
247 def __init__(self, f, code, count, address, array_type):370 def __init__(self, f, code, count, offset, base, array_type, type_):
248 371
249 self.code = code372 self.code = code
250 self.count = count373 self.count = count
251 self.address = address374 self.offset = offset
375 self.base = base
252 self.array_type = array_type376 self.array_type = array_type
377 self.type_ = type_
253 378
254 self.array = []379 self.array = []
255 base = 0380 base = 0
@@ -276,8 +401,14 @@ class Data: · 20 unmodified lines
276 401
277 def __repr__(self):402 def __repr__(self):
278 403
279 return "<%s.%s (%s) %s>" % (self.__module__, self.__class__.__name__,404 if self.type_:
280 self.array_types[self.array_type], repr(self.data()))405 return "Data(base=%i offset=%i raw='%s' type=%s data=%s>" % (
406 self.base, self.offset, self.array_types[self.array_type],
407 self.type_, repr(self.data()))
408 else:
409 return "Data(base=%i offset=%i raw='%s' data=%s>" % (
410 self.base, self.offset, self.array_types[self.array_type],
411 repr(self.data()))
281 412
282 def data(self):413 def data(self):
283 414
@@ -288,8 +419,8 @@ class Data: · 4 unmodified lines
288 419
289 def encoded(self):420 def encoded(self):
290 421
291 """Returns the contents of the array in the form they would take in the422 """Returns the contents of the array in the form they would take if
292 module area on a big-endian system."""423 serialised on a big-endian system."""
293 424
294 data = ""425 data = ""
295 426
@@ -307,6 +438,28 @@ class Data: · 11 unmodified lines
307 data += pack(">q", item)438 data += pack(">q", item)
308 439
309 return data440 return data
441
442 def write(self, f):
443
444 write_B(f, self.code)
445
446 if self.count >= 16:
447 write_OP(f, self.count)
448
449 write_OP(f, self.offset)
450
451 for item in self.array:
452
453 if self.array_type == 1:
454 write_B(f, item)
455 elif self.array_type == 2:
456 write_W(f, item)
457 elif self.array_type == 3:
458 f.write(item)
459 elif self.array_type == 4:
460 write_F(f, item)
461 elif self.array_type == 8:
462 write_L(f, item)
310 463
311 464
312class Link:465class Link:
@@ -317,6 +470,18 @@ class Link: · 4 unmodified lines
317 self.desc_number = read_OP(f)470 self.desc_number = read_OP(f)
318 self.sig = read_W(f) # unsigned for hashes471 self.sig = read_W(f) # unsigned for hashes
319 self.name = read_C(f)472 self.name = read_C(f)
473
474 def __repr__(self):
475
476 return "Link(pc=%s, desc=%i, sig=%s, name='%s')" % (
477 hex(self.pc), self.desc_number, hex(self.sig), self.name)
478
479 def write(self, f):
480
481 write_OP(f, self.pc)
482 write_OP(f, self.desc_number)
483 write_W(f, self.sig)
484 write_C(f, self.name)
320 485
321 486
322class LDT:487class LDT:
@@ -325,3 +490,12 @@ class LDT: · 2 unmodified lines
325 490
326 self.sig = _read(f, ">I") # unsigned for hashes491 self.sig = _read(f, ">I") # unsigned for hashes
327 self.name = read_C(f)492 self.name = read_C(f)
493
494 def __repr__(self):
495
496 return "LDT(sig=0x%x, name='%s')" % (self.sig, self.name)
497
498 def write(self, f):
499
500 _write(f, ">I", self.sig)
501 write_C(f, self.name)
opcodes.py+58−44
@@ -21,34 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. · 20 unmodified lines
21 21
22from utils import read_B, read_OP, write_B, write_OP22from utils import read_B, read_OP, write_B, write_OP
23 23
24# Define string representations of the opcodes.
25
26instruction_names = [
27 "nop", "alt", "nbalt", "goto", "call", "frame", "spawn", "runt",
28 "load", "mcall", "mspawn", "mframe", "ret", "jmp", "case", "exit",
29 "new", "newa", "newcb", "newcw", "newcf", "newcp", "newcm", "newcmp",
30 "send", "recv", "consb", "consw", "consp", "consf", "consm", "consmp",
31 "headb", "headw", "headp", "headf", "headm", "headmp", "tail", "lea",
32 "indx", "movp", "movm", "movmp", "movb", "movw", "movf", "cvtbw",
33 "cvtwb", "cvtfw", "cvtwf", "cvtca", "cvtac", "cvtwc", "cvtcw", "cvtfc",
34 "cvtcf", "addb", "addw", "addf", "subb", "subw", "subf", "mulb",
35 "mulw", "mulf", "divb", "divw", "divf", "modw", "modb", "andb",
36 "andw", "orb", "orw", "xorb", "xorw", "shlb", "shlw", "shrb",
37 "shrw", "insc", "indc", "addc", "lenc", "lena", "lenl", "beqb",
38 "bneb", "bltb", "bleb", "bgtb", "bgeb", "beqw", "bnew", "bltw",
39 "blew", "bgtw", "bgew", "beqf", "bnef", "bltf", "blef", "bgtf",
40 "bgef", "beqc", "bnec", "bltc", "blec", "bgtc", "bgec", "slicea",
41 "slicela", "slicec", "indw", "indf", "indb", "negf", "movl", "addl",
42 "subl", "divl", "modl", "mull", "andl", "orl", "xorl", "shll",
43 "shrl", "bnel", "bltl", "blel", "bgtl", "bgel", "beql", "cvtlf",
44 "cvtfl", "cvtlw", "cvtwl", "cvtlc", "cvtcl", "headl", "consl", "newcl",
45 "casec", "indl", "movpc", "tcmp", "mnewz", "cvtrf", "cvtfr", "cvtws",
46 "cvtsw", "lsrw", "lsrl", "eclr", "newz", "newaz", "raise", "casel",
47 "mulx", "divx", "cvtxx", "mulx0", "divx0", "cvtxx0", "mulx1", "divx1",
48 "cvtxx1", "cvtfx", "cvtxf", "expw", "expl", "expf", "self"
49 ]
50
51
52class Instruction:24class Instruction:
53 25
54 def __init__(self):26 def __init__(self):
@@ -60,19 +32,34 @@ class Instruction: · 5 unmodified lines
60 32
61 def read(self, f):33 def read(self, f):
62 34
63 self.opcode = read_B(f)35 opcode = read_B(f)
64 self.address_mode = read_B(f)36 class_ = instructions[opcode]
37
38 address_mode = read_B(f)
65 39
66 middle = self.address_mode & 0xc040 middle = address_mode & 0xc0
67 self.middle = self.read_middle_operand(middle, f)41 middle = self.read_middle_operand(middle, f)
68 42
69 source = (self.address_mode & 0x38) >> 343 source = (address_mode & 0x38) >> 3
70 self.source = self.read_operand(source, f)44 source = self.read_operand(source, f)
71 45
72 destination = self.address_mode & 0x0746 destination = address_mode & 0x07
73 self.destination = self.read_operand(destination, f)47 destination = self.read_operand(destination, f)
74 48
75 return self49 if issubclass(class_, Src):
50 return class_(source)
51 elif issubclass(class_, Src_Src):
52 return class_(source, middle)
53 elif issubclass(class_, Src_Dst):
54 return class_(source, destination)
55 elif issubclass(class_, Src_Src_Dst):
56 return class_(source, middle, destination)
57 elif issubclass(class_, Src_Src_Src):
58 return class_(source, middle, destination)
59 elif issubclass(class_, Dst):
60 return class_(destination)
61 else:
62 return class_()
76 63
77 def set_address_mode(self):64 def set_address_mode(self):
78 65
@@ -130,7 +117,7 @@ class Instruction: · 51 unmodified lines
130 def __repr__(self):117 def __repr__(self):
131 118
132 try:119 try:
133 name = instruction_names[self.opcode]120 name = self.__class__.__name__
134 except IndexError:121 except IndexError:
135 name = hex(self.opcode)122 name = hex(self.opcode)
136 123
@@ -203,11 +190,11 @@ class DoubleShortOffset(Operand): · 66 unmodified lines
203 write_OP(f, self.value[0] & 0xffff)190 write_OP(f, self.value[0] & 0xffff)
204 write_OP(f, self.value[1] & 0xffff)191 write_OP(f, self.value[1] & 0xffff)
205 192
206class DoubleShortOffsetMP(Operand):193class DoubleShortOffsetMP(DoubleShortOffset):
207 str_pattern = "%i(%i(mp))"194 str_pattern = "%i(%i(mp))"
208 address_mode = 0x04195 address_mode = 0x04
209 196
210class DoubleShortOffsetFP(Operand):197class DoubleShortOffsetFP(DoubleShortOffset):
211 str_pattern = "%i(%i(fp))"198 str_pattern = "%i(%i(fp))"
212 address_mode = 0x05199 address_mode = 0x05
213 200
@@ -250,7 +237,7 @@ class Src_Src_Dst(Instruction): · 36 unmodified lines
250 self.destination = dst237 self.destination = dst
251 self.set_address_mode()238 self.set_address_mode()
252 239
253class Src_Src_src(Instruction):240class Src_Src_Src(Instruction):
254 241
255 def __init__(self, src1, src2, src3):242 def __init__(self, src1, src2, src3):
256 243
@@ -380,7 +367,7 @@ class exit(Instruction): opcode = 0x0f · 123 unmodified lines
380class expf(Src_Src_Dst): opcode = 0xad # word word -> float (xec.c)367class expf(Src_Src_Dst): opcode = 0xad # word word -> float (xec.c)
381class expl(Src_Src_Dst): opcode = 0xac # word long -> long (xec.c)368class expl(Src_Src_Dst): opcode = 0xac # word long -> long (xec.c)
382class expw(Src_Src_Dst): opcode = 0xab # word word -> word (xec.c)369class expw(Src_Src_Dst): opcode = 0xab # word word -> word (xec.c)
383class frame(Src_Src): opcode = 0x05370class frame(Src_Dst): opcode = 0x05 # not src1, src2 as in documentation
384class goto(Src_Dst): opcode = 0x03371class goto(Src_Dst): opcode = 0x03
385class headb(headx): opcode = 0x20372class headb(headx): opcode = 0x20
386class headf(headx): opcode = 0x23373class headf(headx): opcode = 0x23
@@ -404,7 +391,7 @@ class lenl(Src_Dst): opcode = 0x56 · 17 unmodified lines
404class load(Src_Src_Dst): opcode = 0x08391class load(Src_Src_Dst): opcode = 0x08
405class lsrl(lsrx): opcode = 0x9a392class lsrl(lsrx): opcode = 0x9a
406class lsrw(lsrx): opcode = 0x99393class lsrw(lsrx): opcode = 0x99
407class mcall(Src_Src_src): opcode = 0x09394class mcall(Src_Src_Src): opcode = 0x09
408class mframe(Src_Src_Dst): opcode = 0x0b395class mframe(Src_Src_Dst): opcode = 0x0b
409class mnewz(Src_Src_Dst): opcode = 0x94396class mnewz(Src_Src_Dst): opcode = 0x94
410class modb(modx): opcode = 0x46397class modb(modx): opcode = 0x46
@@ -418,7 +405,7 @@ class movmp(Src_Src_Dst): opcode = 0x2b · 7 unmodified lines
418class movpc(Src_Dst): opcode = 0x92405class movpc(Src_Dst): opcode = 0x92
419class movp(Src_Dst): opcode = 0x29406class movp(Src_Dst): opcode = 0x29
420class movw(movx): opcode = 0x2d407class movw(movx): opcode = 0x2d
421class mspawn(Src_Src_src): opcode = 0x0a408class mspawn(Src_Src_Src): opcode = 0x0a
422class mulb(mulx_): opcode = 0x3f409class mulb(mulx_): opcode = 0x3f
423class mulf(mulx_): opcode = 0x41410class mulf(mulx_): opcode = 0x41
424class mull(mulx_): opcode = 0x7b411class mull(mulx_): opcode = 0x7b
@@ -468,3 +455,30 @@ class tcmp(Src_Dst): opcode = 0x93 · 43 unmodified lines
468class xorb(xorx): opcode = 0x4b455class xorb(xorx): opcode = 0x4b
469class xorl(xorx): opcode = 0x7e456class xorl(xorx): opcode = 0x7e
470class xorw(xorx): opcode = 0x4c457class xorw(xorx): opcode = 0x4c
458
459# Define a list to map opcodes to instruction classes.
460
461instructions = [
462 nop, alt, nbalt, goto, call, frame, spawn, runt,
463 load, mcall, mspawn, mframe, ret, jmp, case, exit,
464 new, newa, newcb, newcw, newcf, newcp, newcm, newcmp,
465 send, recv, consb, consw, consp, consf, consm, consmp,
466 headb, headw, headp, headf, headm, headmp, tail, lea,
467 indx, movp, movm, movmp, movb, movw, movf, cvtbw,
468 cvtwb, cvtfw, cvtwf, cvtca, cvtac, cvtwc, cvtcw, cvtfc,
469 cvtcf, addb, addw, addf, subb, subw, subf, mulb,
470 mulw, mulf, divb, divw, divf, modw, modb, andb,
471 andw, orb, orw, xorb, xorw, shlb, shlw, shrb,
472 shrw, insc, indc, addc, lenc, lena, lenl, beqb,
473 bneb, bltb, bleb, bgtb, bgeb, beqw, bnew, bltw,
474 blew, bgtw, bgew, beqf, bnef, bltf, blef, bgtf,
475 bgef, beqc, bnec, bltc, blec, bgtc, bgec, slicea,
476 slicela, slicec, indw, indf, indb, negf, movl, addl,
477 subl, divl, modl, mull, andl, orl, xorl, shll,
478 shrl, bnel, bltl, blel, bgtl, bgel, beql, cvtlf,
479 cvtfl, cvtlw, cvtwl, cvtlc, cvtcl, headl, consl, newcl,
480 casec, indl, movpc, tcmp, mnewz, cvtrf, cvtfr, cvtws,
481 cvtsw, lsrw, lsrl, eclr, newz, newaz, raise_, casel,
482 mulx, divx, cvtxx, mulx0, divx0, cvtxx0, mulx1, divx1,
483 cvtxx1, cvtfx, cvtxf, expw, expl, expf, self
484 ]