'Trace function calls made by the program
Usage:
MYNAME ["func1,func2"] [mapname1,mapname2]
MYNAME ["-func1,func2"] [mapname1,mapname2] (inverse)
default is to trace internal calls made by the program'

def tracecall(self, *arg):

    (funcs, mapname) = normalize_argv(arg, 2)
    if (not self._is_running()):
        return
    if (not mapname):
        mapname = 'binary'
    fnames = ['']
    if funcs:
        if to_int(funcs):
            funcs = ('0x%x' % funcs)
        fnames = funcs.replace(',', '    ').split()
    for (idx, fn) in enumerate(fnames):
        if to_int(fn):
            fnames[idx] = ('0x%x' % to_int(fn))
    inverse = 0
    for (idx, fn) in enumerate(fnames):
        if fn.startswith('-'):
            fnames[idx] = fn[1:]
            inverse = 1
    binname = peda.getfile()
    logname = peda.get_config_filename('tracelog')
    if (mapname is None):
        mapname = binname
    peda.save_user_command('hook-stop')
    msg(("Tracing    calls    %s    '%s',    Ctrl-C    to    stop..." % (('match' if (not inverse) else 'not    match'), ','.join(fnames))))
    prev_depth = peda.backtrace_depth(peda.getreg('sp'))
    logfd = open(logname, 'w')
    while True:
        result = peda.stepuntil('call', mapname, prev_depth)
        if (result is None):
            break
        (call_depth, code) = result
        prev_depth += call_depth
        if (not code.startswith('=>')):
            break
        if (not inverse):
            matched = False
            for fn in fnames:
                fn = fn.strip()
                if re.search(fn, code.split(': DCTB ')[(-1)]):
                    matched = True
                    break
        else:
            matched = True
            for fn in fnames:
                fn = fn.strip()
                if re.search(fn, code.split(': DCTB ')[(-1)]):
                    matched = False
                    break
        if matched:
            code = format_disasm_code(code)
            msg(('%s%s%s' % (('    ' * (prev_depth - 1)), ('    dep:%02d    ' % (prev_depth - 1)), colorize(code.strip()))), teefd=logfd)
            args = peda.get_function_args()
            if args:
                for (i, a) in enumerate(args):
                    chain = peda.examine_mem_reference(a)
                    text = ('%s                                |--    arg[%d]:    %s' % (('    ' * (prev_depth - 1)), i, format_reference_chain(chain)))
                    msg(text, teefd=logfd)
    msg(code, 'red')
    peda.restore_user_command('hook-stop')
    if ('STOP' not in peda.get_status()):
        peda.execute('stop')
    logfd.close()
    msg(("Saved    trace    information    in    file    %s,    view    with    'less    -r    file'" % logname))
    return
