Unified · Split
| @@ -28,12 +28,11 @@ def _read(f, format): · 27 unmodified lines | ||
| 28 | 28 | return unpack(format, f.read(size))[0] |
| 29 | 29 | |
| 30 | 30 | def read_B(f): |
| 31 | − | |
| 31 | + # byte, 8-bit unsigned | |
| 32 | 32 | return unpack(">B", f.read(1))[0] |
| 33 | 33 | |
| 34 | 34 | def read_OP(f): |
| 35 | 35 | |
| 36 | − at = f.tell() | |
| 37 | 36 | s = f.read(1) |
| 38 | 37 | v = unpack(">B", s)[0] |
| 39 | 38 | |
| @@ -62,24 +61,44 @@ def read_OP(f): · 22 unmodified lines | ||
| 62 | 61 | return v |
| 63 | 62 | |
| 64 | 63 | def read_W(f): |
| 65 | − | |
| 66 | − return unpack(">i", f.read(4)) | |
| 64 | + # 32-bit word | |
| 65 | + return unpack(">i", f.read(4))[0] | |
| 67 | 66 | |
| 68 | 67 | def read_F(f): |
| 69 | − | |
| 70 | − return unpack(">d", f.read(8)) | |
| 68 | + # 64-bit float | |
| 69 | + return unpack(">d", f.read(8))[0] | |
| 70 | + | |
| 71 | +def read_L(f): | |
| 72 | + # 64-bit big integer | |
| 73 | + # Signed or unsigned? Assume signed for now. | |
| 74 | + return unpack(">q", f.read(8))[0] | |
| 75 | + | |
| 76 | +def read_P(f): | |
| 77 | + # 32-bit pointer | |
| 78 | + return unpack(">I", f.read(4))[0] | |
| 79 | + | |
| 80 | +def read_C(f): | |
| 81 | + # UTF-8 encoded string | |
| 82 | + s = "" | |
| 83 | + while True: | |
| 84 | + c = f.read(1) | |
| 85 | + if c == "\x00": | |
| 86 | + break | |
| 87 | + s += c | |
| 88 | + | |
| 89 | + return s | |
| 71 | 90 | |
| 72 | 91 | def read_SO(f): |
| 73 | 92 | |
| 74 | − return unpack(">H", f.read(2)) | |
| 93 | + return unpack(">H", f.read(2))[0] | |
| 75 | 94 | |
| 76 | 95 | def read_SI(f): |
| 77 | 96 | |
| 78 | − return unpack(">h", f.read(2)) | |
| 97 | + return unpack(">h", f.read(2))[0] | |
| 79 | 98 | |
| 80 | 99 | def read_LO(f): |
| 81 | 100 | |
| 82 | − return unpack(">i", f.read(4)) | |
| 101 | + return unpack(">i", f.read(4))[0] | |
| 83 | 102 | |
| 84 | 103 | |
| 85 | 104 | class DisError(Exception): |
| @@ -130,16 +149,61 @@ class Dis: · 44 unmodified lines | ||
| 130 | 149 | self.entry_type = read_OP(f) |
| 131 | 150 | |
| 132 | 151 | self.read_code(f) |
| 152 | + self.read_types(f) | |
| 153 | + self.read_data(f) | |
| 154 | + | |
| 155 | + self.module_name = read_C(f) | |
| 156 | + | |
| 157 | + self.read_link(f) | |
| 133 | 158 | |
| 134 | 159 | def read_code(self, f): |
| 135 | 160 | |
| 136 | 161 | self.code = [] |
| 137 | − | |
| 138 | 162 | i = 0 |
| 139 | − while i < self.code_size: | |
| 140 | 163 | |
| 164 | + while i < self.code_size: | |
| 141 | 165 | self.code.append(Instruction(f)) |
| 142 | 166 | i += 1 |
| 167 | + | |
| 168 | + def read_types(self, f): | |
| 169 | + | |
| 170 | + self.types = [] | |
| 171 | + i = 0 | |
| 172 | + | |
| 173 | + while i < self.type_size: | |
| 174 | + self.types.append(Type(f)) | |
| 175 | + i += 1 | |
| 176 | + | |
| 177 | + def read_data(self, f): | |
| 178 | + | |
| 179 | + self.data = [] | |
| 180 | + | |
| 181 | + while True: | |
| 182 | + | |
| 183 | + at = f.tell() | |
| 184 | + | |
| 185 | + code = read_B(f) | |
| 186 | + if code == 0: | |
| 187 | + break | |
| 188 | + | |
| 189 | + array_type = code >> 4 | |
| 190 | + if not 1 <= array_type <= 8: | |
| 191 | + raise self.error("Unknown type in data item at 0x%x" % at) | |
| 192 | + | |
| 193 | + self.data.append(Data(f, code, array_type)) | |
| 194 | + | |
| 195 | + def read_link(self, f): | |
| 196 | + | |
| 197 | + self.link = [] | |
| 198 | + i = 0 | |
| 199 | + | |
| 200 | + while i < self.link_size: | |
| 201 | + self.link.append(Link(f)) | |
| 202 | + i += 1 | |
| 203 | + | |
| 204 | + def list(self): | |
| 205 | + | |
| 206 | + print "\n".join(map(str, self.code)) | |
| 143 | 207 | |
| 144 | 208 | |
| 145 | 209 | class RuntimeFlag: |
| @@ -165,19 +229,7 @@ class Instruction: · 19 unmodified lines | ||
| 165 | 229 | self.address_mode = read_B(f) |
| 166 | 230 | |
| 167 | 231 | middle = self.address_mode & 0xc0 |
| 168 | − | |
| 169 | − if middle == 0x40: | |
| 170 | − self.middle = read_OP(f) | |
| 171 | − self.middle_type = "$SI" | |
| 172 | − elif middle == 0x80: | |
| 173 | − self.middle = read_OP(f) | |
| 174 | − self.middle_type = "SO(FP)" | |
| 175 | − elif middle == 0xc0: | |
| 176 | − self.middle = read_OP(f) | |
| 177 | − self.middle_type = "SO(MP)" | |
| 178 | − else: | |
| 179 | − self.middle = None | |
| 180 | − self.middle_type = None | |
| 232 | + self.middle, self.middle_type = self.read_middle_operand(middle, f) | |
| 181 | 233 | |
| 182 | 234 | source = (self.address_mode & 0x38) >> 3 |
| 183 | 235 | self.source, self.source_type = self.read_operand(source, f) |
| @@ -187,6 +239,9 @@ class Instruction: · 3 unmodified lines | ||
| 187 | 239 | |
| 188 | 240 | def read_operand(self, operand, f): |
| 189 | 241 | |
| 242 | + # Since we shift the address flags for the source operand, we can | |
| 243 | + # check both source and destination operands using the same values. | |
| 244 | + | |
| 190 | 245 | if operand == 0x00: |
| 191 | 246 | operand = read_OP(f) |
| 192 | 247 | operand_type = "LO(MP)" |
| @@ -208,6 +263,25 @@ class Instruction: · 15 unmodified lines | ||
| 208 | 263 | |
| 209 | 264 | return operand, operand_type |
| 210 | 265 | |
| 266 | + def read_middle_operand(self, operand, f): | |
| 267 | + | |
| 268 | + # The middle operand bits are not shifted. | |
| 269 | + | |
| 270 | + if operand == 0x40: | |
| 271 | + operand = read_OP(f) | |
| 272 | + operand_type = "$SI" | |
| 273 | + elif operand == 0x80: | |
| 274 | + operand = read_OP(f) | |
| 275 | + operand_type = "SO(FP)" | |
| 276 | + elif operand == 0xc0: | |
| 277 | + operand = read_OP(f) | |
| 278 | + operand_type = "SO(MP)" | |
| 279 | + else: | |
| 280 | + operand = None | |
| 281 | + operand_type = None | |
| 282 | + | |
| 283 | + return operand, operand_type | |
| 284 | + | |
| 211 | 285 | def __repr__(self): |
| 212 | 286 | |
| 213 | 287 | try: |
| @@ -222,17 +296,119 @@ class Instruction: · 8 unmodified lines | ||
| 222 | 296 | (self.middle, self.middle_type), \ |
| 223 | 297 | (self.destination, self.destination_type): |
| 224 | 298 | |
| 225 | − if optype in ["$SI", "SO(FP)", "SO(MP)"]: | |
| 226 | − operands.append(op) | |
| 227 | − comments.append(optype) | |
| 228 | − elif optype in ["LO(MP)", "LO(FP)", "$OP"]: | |
| 229 | − operands.append(op) | |
| 230 | − comments.append(optype) | |
| 231 | − elif optype in ["SO(SO(MP))", "SO(SO(FP))"]: | |
| 232 | − operands += list(op) | |
| 233 | − comments.append(optype) | |
| 234 | − | |
| 235 | − if comments: | |
| 236 | − return name + " " + ", ".join(map(hex, operands)) + " ; " + ", ".join(comments) | |
| 299 | + if optype == "$SI": | |
| 300 | + operands.append("$%s" % op) | |
| 301 | + elif optype == "SO(FP)": | |
| 302 | + operands.append("%i(fp)" % op) | |
| 303 | + elif optype == "SO(MP)": | |
| 304 | + operands.append("%i(mp)" % op) | |
| 305 | + elif optype == "LO(MP)": | |
| 306 | + operands.append("%i(mp)" % op) | |
| 307 | + elif optype == "LO(FP)": | |
| 308 | + operands.append("%i(fp)" % op) | |
| 309 | + elif optype == "$OP": | |
| 310 | + operands.append("$%s" % op) | |
| 311 | + elif optype == "SO(SO(MP))": | |
| 312 | + operands.append("%i(%i(mp))" % op) | |
| 313 | + elif optype == "SO(SO(FP))": | |
| 314 | + operands.append("%i(%i(fp))" % op) | |
| 315 | + | |
| 316 | + return name + " " + ", ".join(operands) | |
| 317 | + | |
| 318 | + | |
| 319 | +class Type: | |
| 320 | + | |
| 321 | + def __init__(self, f): | |
| 322 | + | |
| 323 | + self.desc_number = read_OP(f) | |
| 324 | + self.size = read_OP(f) | |
| 325 | + self.number_ptrs = read_OP(f) | |
| 326 | + self.array = f.read(self.number_ptrs) | |
| 327 | + | |
| 328 | + def is_pointer(self, address): | |
| 329 | + | |
| 330 | + # Convert the address of a word to a bit offset in the array. | |
| 331 | + bit = address / 4 | |
| 332 | + # Extract the byte containing the bit we want to check. | |
| 333 | + byte = self.array[bit / 8] | |
| 334 | + # Check whether the bit is 1 or 0, returning True for 1 and False for 0. | |
| 335 | + mask = 1 << (bit % 8) | |
| 336 | + return (ord(byte) & mask) != 0 | |
| 337 | + | |
| 338 | + | |
| 339 | +class Data: | |
| 340 | + | |
| 341 | + array_types = ["Invalid", "8-bit byte", "32-bit word", | |
| 342 | + "UTF-8 encoded string", "64-bit float", "Array", | |
| 343 | + "Set array address", "Restore load address"] | |
| 344 | + | |
| 345 | + def __init__(self, f, code, array_type): | |
| 346 | + | |
| 347 | + self.code = code | |
| 348 | + self.count = code & 0x0f | |
| 349 | + | |
| 350 | + if self.count == 0: | |
| 351 | + self.count = read_OP(f) | |
| 352 | + | |
| 353 | + self.offset = read_OP(f) | |
| 354 | + self.array_type = array_type | |
| 355 | + | |
| 356 | + self.array = [] | |
| 357 | + base = 0 | |
| 358 | + i = 0 | |
| 359 | + while i < self.count: | |
| 360 | + | |
| 361 | + if array_type == 1: | |
| 362 | + # 8-bit byte | |
| 363 | + self.array.append(read_B(f)) | |
| 364 | + elif array_type == 2: | |
| 365 | + # 32-bit word | |
| 366 | + self.array.append(read_W(f)) | |
| 367 | + elif array_type == 3: | |
| 368 | + # UTF-8 encoded string (each item is a character) | |
| 369 | + self.array.append(f.read(1)) | |
| 370 | + elif array_type == 4: | |
| 371 | + # 64-bit float | |
| 372 | + self.array.append(read_F(f)) | |
| 373 | + elif array_type == 5: | |
| 374 | + # Array | |
| 375 | + index = _read(f, ">I") | |
| 376 | + length = _read(f, ">I") | |
| 377 | + print "Array", index, length, self.count | |
| 378 | + #self.array.append(read_F(f)) | |
| 379 | + elif array_type == 6: | |
| 380 | + # Set array address | |
| 381 | + index = _read(f, ">I") | |
| 382 | + print "Set array address", index, self.count | |
| 383 | + #self.array.append(read_F(f)) | |
| 384 | + elif array_type == 7: | |
| 385 | + # Restore load address | |
| 386 | + print "Restore load address" | |
| 387 | + #self.array.append(read_F(f)) | |
| 388 | + elif array_type == 8: | |
| 389 | + # 64-bit integer | |
| 390 | + self.array.append(read_L(f)) | |
| 391 | + | |
| 392 | + i += 1 | |
| 393 | + | |
| 394 | + def data(self): | |
| 395 | + | |
| 396 | + if self.array_type == 3: | |
| 397 | + return "".join(self.array) | |
| 237 | 398 | else: |
| 238 | − return name + " " + ", ".join(map(hex, operands)) | |
| 399 | + return self.array | |
| 400 | + | |
| 401 | + def __repr__(self): | |
| 402 | + | |
| 403 | + return "<%s.%s (%s) %s>" % (self.__module__, self.__class__.__name__, | |
| 404 | + self.array_types[self.array_type], repr(self.data())) | |
| 405 | + | |
| 406 | + | |
| 407 | +class Link: | |
| 408 | + | |
| 409 | + def __init__(self, f): | |
| 410 | + | |
| 411 | + self.pc = read_OP(f) | |
| 412 | + self.desc_number = read_OP(f) | |
| 413 | + self.sig = read_W(f) | |
| 414 | + self.name = read_C(f) | |