#TODO write a description for this script
#@author
#@category _NEW_
#@keybinding
#@menupath
#@toolbar


#TODO Add User Code Here

from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor
from ghidra.program.model.symbol import SymbolType
from ghidra.util.exception import DuplicateNameException
from ghidra.program.model.data import DataTypeConflictHandler
from ghidra.program.model.data import TypedefDataType
from ghidra.program.model.symbol import SourceType
from ghidra.program.model.listing import Program
from ghidra.framework.options import Options

import sys
import json
import signal

number = sys.argv[0].replace('preprocess_', '')
number = number.replace('.py', '')

program = getCurrentProgram()
program.setImageBase(toAddr(0), 0)
function = getFirstFunction()
ifc = DecompInterface()
ifc.openProgram(program)
origtype = None


func_idx = 1

answer = {}
while function is not None:
    funcname = function.name
    startaddr = str(function.getEntryPoint().toString())
    functype = function.getReturnType()
    answer[startaddr] = {}
    answer[startaddr][startaddr] = [str(funcname), str(functype)]

    called_funcs = function.getCalledFunctions(ConsoleTaskMonitor())

    # Function
    for called_func in called_funcs:
        called_funcname = called_func.name
        called_funcaddr = called_func.getEntryPoint().toString()
        answer[startaddr][str(called_funcaddr)] = str(called_funcname)

    results = ifc.decompileFunction(function, 3, ConsoleTaskMonitor())
    if results.decompileCompleted():
        high_func = results.getHighFunction()
        symbol_table = high_func.getGlobalSymbolMap()
        for symbol in symbol_table.getSymbols():
            if symbol.isGlobal():
                answer[startaddr][str(symbol.getSymbol().getAddress().toString())] = str(symbol.getName())

    locals = function.getAllVariables()

    for idx in range(len(locals)):
        if locals[idx].getSymbol() != None:
            answer[startaddr][str(locals[idx].getMinAddress().toString())] = [str(locals[idx].getName()), str(locals[idx].getDataType().getName())]

    stack_addr = 0
    while True:
        var = function.getStackFrame().getVariableContaining(stack_addr)
        if var != None:
            temp = 'Stack[' + str(hex(stack_addr)) + ']'
            answer[startaddr][temp] = [str(var.getName()), str(var.getDataType().getName())]
        stack_addr -= 1

        if -stack_addr > function.getStackFrame().getFrameSize():
            break

    function = getFunctionAfter(function)



with open("temp_" + str(number) + ".json", 'w') as fp:
    json.dump(answer, fp, indent=2)
