aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/moddis.py
blob: 0dac19bbbe48306ce26d406c20c535d550753c99 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"""Disassemble named functions out of ras2.elf (no IDA instance exists for RAS)."""
import json, struct, sys
from capstone import *
from capstone.arm import *

import os
MOD = os.environ.get('MOD','ras')
ELF = '/Users/user/dev/amd-psp-re/psp_out/handover/elf/%s2.elf' % MOD
SYM = '/Users/user/dev/amd-psp-re/psp_out/handover/symbols/%s.json' % MOD

raw = open(ELF, 'rb').read()
ph = struct.unpack('<I', raw[28:32])[0]
off, vaddr, paddr, fsz = struct.unpack('<IIII', raw[ph+4:ph+20])
body = raw[off:off+fsz]

d = json.load(open(SYM))
funcs = {int(k, 16): v for k, v in d['functions'].items()}
names = {int(k, 16): v for k, v in d.get('names', {}).items()}
byname = {v['name']: k for k, v in funcs.items()}

md = Cs(CS_ARCH_ARM, CS_MODE_THUMB)
md.detail = True

def dis(name_or_ea, limit=200):
    ea = byname.get(name_or_ea) if isinstance(name_or_ea, str) else name_or_ea
    if ea is None:
        print("?? %s" % name_or_ea); return
    f = funcs.get(ea, {})
    end = f.get('end', ea + 0x80)
    print("==== %s @ %#x  (%d bytes) ====" % (f.get('name', '?'), ea, end - ea))
    if f.get('cmt'): print("  ; " + f['cmt'].replace('\n', '\n  ; '))
    if f.get('proto'): print("  ; proto: " + f['proto'])
    o = ea - vaddr
    n = 0
    for i in md.disasm(body[o:o + (end - ea)], ea):
        tgt = ''
        for op in i.operands:
            if op.type == ARM_OP_IMM and op.imm in funcs:
                tgt = '  -> ' + funcs[op.imm]['name']
            elif op.type == ARM_OP_IMM and op.imm in names:
                tgt = '  -> ' + names[op.imm]
        print("  %#08x  %-9s %s%s" % (i.address, i.mnemonic, i.op_str, tgt))
        n += 1
        if n > limit: print("  ..."); break
    print()

if __name__ == '__main__':
    for a in sys.argv[1:]:
        dis(a)