from ghidra.app.decompiler import DecompInterface
from collections import defaultdict
import json

lst = currentProgram.getListing()

decompintf = DecompInterface()
decompintf.openProgram(currentProgram)

def handle_func(func_addr):
    cfg = defaultdict(list)

    addr = func_addr.getValue()
    func_name = "ptf_%r" % (addr,)
    createFunction(addr, func_name)
    analyzeChanges(currentProgram)
    func = getFunctionAt(addr)
    end_addr = max(i.getMaxAddress() for i in list(func.getBody().getAddressRanges()))
    results = decompintf.decompileFunction(func, 30, None)
    highfunc = results.getHighFunction()
    blocks = highfunc.getBasicBlocks()
    for block in blocks:
        for n in range(block.getOutSize()):
            cfg[str(block.getStart())].append(str(block.getOut(n).getStart()))

    return (func_name + "_%r" % (end_addr,), cfg)

def main():
    array_base = toAddr("414540")
    func_addr = lst.getDataAt(array_base)

    cfgs = {}

    while True:
        name, cfg = handle_func(func_addr)
        cfgs[name] = cfg
        func_addr = lst.getDataAfter(func_addr.getAddress())
        if func_addr.getLength() == 1:
            # we're past the function array
            break

    with open('cfgs.json', 'w') as f:
        json.dump(cfgs, f)

main()
