Unified · Split
| @@ -28,12 +28,11 @@ def _read(f, format): · 27 unmodified lines | |||
| 28 | return unpack(format, f.read(size))[0] | 28 | return unpack(format, f.read(size))[0] |
| 29 | 29 | ||
| 30 | def read_B(f): | 30 | def read_B(f): |
| 31 | 31 | # byte, 8-bit unsigned | |
| 32 | return unpack(">B", f.read(1))[0] | 32 | return unpack(">B", f.read(1))[0] |
| 33 | 33 | ||
| 34 | def read_OP(f): | 34 | def read_OP(f): |
| 35 | 35 | ||
| 36 | at = f.tell() | ||
| 37 | s = f.read(1) | 36 | s = f.read(1) |
| 38 | v = unpack(">B", s)[0] | 37 | v = unpack(">B", s)[0] |
| 39 | 38 | ||
| @@ -62,24 +61,44 @@ def read_OP(f): · 22 unmodified lines | |||
| 62 | return v | 61 | return v |
| 63 | 62 | ||
| 64 | def read_W(f): | 63 | def read_W(f): |
| 65 | 64 | # 32-bit word | |
| 66 | return unpack(">i", f.read(4)) | 65 | return unpack(">i", f.read(4))[0] |
| 67 | 66 | ||
| 68 | def read_F(f): | 67 | def read_F(f): |
| 69 | 68 | # 64-bit float | |
| 70 | return unpack(">d", f.read(8)) | 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 | def read_SO(f): | 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 | def read_SI(f): | 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 | def read_LO(f): | 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 | class DisError(Exception): | 104 | class DisError(Exception): |
| @@ -130,16 +149,61 @@ class Dis: · 44 unmodified lines | |||
| 130 | self.entry_type = read_OP(f) | 149 | self.entry_type = read_OP(f) |
| 131 | 150 | ||
| 132 | self.read_code(f) | 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 | def read_code(self, f): | 159 | def read_code(self, f): |
| 135 | 160 | ||
| 136 | self.code = [] | 161 | self.code = [] |
| 137 | |||
| 138 | i = 0 | 162 | i = 0 |
| 139 | while i < self.code_size: | ||
| 140 | 163 | ||
| 164 | while i < self.code_size: | ||
| 141 | self.code.append(Instruction(f)) | 165 | self.code.append(Instruction(f)) |
| 142 | i += 1 | 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 | class RuntimeFlag: | 209 | class RuntimeFlag: |
| @@ -165,19 +229,7 @@ class Instruction: · 19 unmodified lines | |||
| 165 | self.address_mode = read_B(f) | 229 | self.address_mode = read_B(f) |
| 166 | 230 | ||
| 167 | middle = self.address_mode & 0xc0 | 231 | middle = self.address_mode & 0xc0 |
| 168 | 232 | self.middle, self.middle_type = self.read_middle_operand(middle, f) | |
| 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 | ||
| 181 | 233 | ||
| 182 | source = (self.address_mode & 0x38) >> 3 | 234 | source = (self.address_mode & 0x38) >> 3 |
| 183 | self.source, self.source_type = self.read_operand(source, f) | 235 | self.source, self.source_type = self.read_operand(source, f) |
| @@ -187,6 +239,9 @@ class Instruction: · 3 unmodified lines | |||
| 187 | 239 | ||
| 188 | def read_operand(self, operand, f): | 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 | if operand == 0x00: | 245 | if operand == 0x00: |
| 191 | operand = read_OP(f) | 246 | operand = read_OP(f) |
| 192 | operand_type = "LO(MP)" | 247 | operand_type = "LO(MP)" |
| @@ -208,6 +263,25 @@ class Instruction: · 15 unmodified lines | |||
| 208 | 263 | ||
| 209 | return operand, operand_type | 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 | def __repr__(self): | 285 | def __repr__(self): |
| 212 | 286 | ||
| 213 | try: | 287 | try: |
| @@ -222,17 +296,119 @@ class Instruction: · 8 unmodified lines | |||
| 222 | (self.middle, self.middle_type), \ | 296 | (self.middle, self.middle_type), \ |
| 223 | (self.destination, self.destination_type): | 297 | (self.destination, self.destination_type): |
| 224 | 298 | ||
| 225 | if optype in ["$SI", "SO(FP)", "SO(MP)"]: | 299 | if optype == "$SI": |
| 226 | operands.append(op) | 300 | operands.append("$%s" % op) |
| 227 | comments.append(optype) | 301 | elif optype == "SO(FP)": |
| 228 | elif optype in ["LO(MP)", "LO(FP)", "$OP"]: | 302 | operands.append("%i(fp)" % op) |
| 229 | operands.append(op) | 303 | elif optype == "SO(MP)": |
| 230 | comments.append(optype) | 304 | operands.append("%i(mp)" % op) |
| 231 | elif optype in ["SO(SO(MP))", "SO(SO(FP))"]: | 305 | elif optype == "LO(MP)": |
| 232 | operands += list(op) | 306 | operands.append("%i(mp)" % op) |
| 233 | comments.append(optype) | 307 | elif optype == "LO(FP)": |
| 234 | 308 | operands.append("%i(fp)" % op) | |
| 235 | if comments: | 309 | elif optype == "$OP": |
| 236 | return name + " " + ", ".join(map(hex, operands)) + " ; " + ", ".join(comments) | 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 | else: | 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) | ||