11f5207b7SJohn Levon#!/usr/bin/python
21f5207b7SJohn Levon
31f5207b7SJohn Levon# Copyright (C) 2013 Oracle.
41f5207b7SJohn Levon#
51f5207b7SJohn Levon# Licensed under the Open Software License version 1.1
61f5207b7SJohn Levon
71f5207b7SJohn Levonimport sqlite3
81f5207b7SJohn Levonimport sys
91f5207b7SJohn Levonimport re
10c85f09ccSJohn Levonimport subprocess
111f5207b7SJohn Levon
121f5207b7SJohn Levontry:
131f5207b7SJohn Levon    con = sqlite3.connect('smatch_db.sqlite')
141f5207b7SJohn Levonexcept sqlite3.Error, e:
151f5207b7SJohn Levon    print "Error %s:" % e.args[0]
161f5207b7SJohn Levon    sys.exit(1)
171f5207b7SJohn Levon
181f5207b7SJohn Levondef usage():
191f5207b7SJohn Levon    print "%s" %(sys.argv[0])
201f5207b7SJohn Levon    print "<function> - how a function is called"
21efe51d0cSJohn Levon    print "info <type> - how a function is called, filtered by type"
221f5207b7SJohn Levon    print "return_states <function> - what a function returns"
231f5207b7SJohn Levon    print "call_tree <function> - show the call tree"
241f5207b7SJohn Levon    print "where <struct_type> <member> - where a struct member is set"
251f5207b7SJohn Levon    print "type_size <struct_type> <member> - how a struct member is allocated"
261f5207b7SJohn Levon    print "data_info <struct_type> <member> - information about a given data type"
271f5207b7SJohn Levon    print "function_ptr <function> - which function pointers point to this"
281f5207b7SJohn Levon    print "trace_param <function> <param> - trace where a parameter came from"
29c85f09ccSJohn Levon    print "find_tagged <function> <param> - find the source of a tagged value (arm64)"
30c85f09ccSJohn Levon    print "parse_warns_tagged <smatch_warns.txt> - parse warns file for summary of tagged issues (arm64)"
311f5207b7SJohn Levon    print "locals <file> - print the local values in a file."
321f5207b7SJohn Levon    sys.exit(1)
331f5207b7SJohn Levon
341f5207b7SJohn Levonfunction_ptrs = []
351f5207b7SJohn Levonsearched_ptrs = []
361f5207b7SJohn Levondef get_function_pointers_helper(func):
371f5207b7SJohn Levon    cur = con.cursor()
381f5207b7SJohn Levon    cur.execute("select distinct ptr from function_ptr where function = '%s';" %(func))
391f5207b7SJohn Levon    for row in cur:
401f5207b7SJohn Levon        ptr = row[0]
411f5207b7SJohn Levon        if ptr in function_ptrs:
421f5207b7SJohn Levon            continue
431f5207b7SJohn Levon        function_ptrs.append(ptr)
441f5207b7SJohn Levon        if not ptr in searched_ptrs:
451f5207b7SJohn Levon            searched_ptrs.append(ptr)
461f5207b7SJohn Levon            get_function_pointers_helper(ptr)
471f5207b7SJohn Levon
481f5207b7SJohn Levondef get_function_pointers(func):
491f5207b7SJohn Levon    global function_ptrs
501f5207b7SJohn Levon    global searched_ptrs
511f5207b7SJohn Levon    function_ptrs = [func]
521f5207b7SJohn Levon    searched_ptrs = [func]
531f5207b7SJohn Levon    get_function_pointers_helper(func)
541f5207b7SJohn Levon    return function_ptrs
551f5207b7SJohn Levon
561f5207b7SJohn Levondb_types = {   0: "INTERNAL",
571f5207b7SJohn Levon             101: "PARAM_CLEARED",
581f5207b7SJohn Levon             103: "PARAM_LIMIT",
591f5207b7SJohn Levon             104: "PARAM_FILTER",
601f5207b7SJohn Levon            1001: "PARAM_VALUE",
611f5207b7SJohn Levon            1002: "BUF_SIZE",
621f5207b7SJohn Levon            1004: "CAPPED_DATA",
631f5207b7SJohn Levon            1005: "RETURN_VALUE",
641f5207b7SJohn Levon            1006: "DEREFERENCE",
651f5207b7SJohn Levon            1007: "RANGE_CAP",
661f5207b7SJohn Levon            1008: "LOCK_HELD",
671f5207b7SJohn Levon            1009: "LOCK_RELEASED",
681f5207b7SJohn Levon            1010: "ABSOLUTE_LIMITS",
691f5207b7SJohn Levon            1012: "PARAM_ADD",
701f5207b7SJohn Levon            1013: "PARAM_FREED",
711f5207b7SJohn Levon            1014: "DATA_SOURCE",
721f5207b7SJohn Levon            1015: "FUZZY_MAX",
731f5207b7SJohn Levon            1016: "STR_LEN",
741f5207b7SJohn Levon            1017: "ARRAY_LEN",
751f5207b7SJohn Levon            1018: "CAPABLE",
761f5207b7SJohn Levon            1019: "NS_CAPABLE",
77*6523a3aaSJohn Levon            1020: "CONTAINER",
781f5207b7SJohn Levon            1022: "TYPE_LINK",
791f5207b7SJohn Levon            1023: "UNTRACKED_PARAM",
801f5207b7SJohn Levon            1024: "CULL_PATH",
811f5207b7SJohn Levon            1025: "PARAM_SET",
821f5207b7SJohn Levon            1026: "PARAM_USED",
831f5207b7SJohn Levon            1027: "BYTE_UNITS",
841f5207b7SJohn Levon            1028: "COMPARE_LIMIT",
851f5207b7SJohn Levon            1029: "PARAM_COMPARE",
86efe51d0cSJohn Levon            1030: "EXPECTS_TYPE",
87efe51d0cSJohn Levon            1031: "CONSTRAINT",
88efe51d0cSJohn Levon            1032: "PASSES_TYPE",
89efe51d0cSJohn Levon            1033: "CONSTRAINT_REQUIRED",
90efe51d0cSJohn Levon            1034: "BIT_INFO",
91efe51d0cSJohn Levon            1035: "NOSPEC",
92efe51d0cSJohn Levon            1036: "NOSPEC_WB",
93efe51d0cSJohn Levon            1037: "STMT_CNT",
94efe51d0cSJohn Levon            1038: "TERMINATED",
95efe51d0cSJohn Levon            1039: "SLEEP",
96*6523a3aaSJohn Levon            1040: "PREEMPT_CNT",
97efe51d0cSJohn Levon            1041: "SMALLISH",
98efe51d0cSJohn Levon            1042: "FRESH_MTAG",
99efe51d0cSJohn Levon
100efe51d0cSJohn Levon            8017: "USER_DATA",
101efe51d0cSJohn Levon            9017: "USER_DATA_SET",
1021f5207b7SJohn Levon            8018: "NO_OVERFLOW",
1031f5207b7SJohn Levon            8019: "NO_OVERFLOW_SIMPLE",
1041f5207b7SJohn Levon            8020: "LOCKED",
1051f5207b7SJohn Levon            8021: "UNLOCKED",
106*6523a3aaSJohn Levon            9022: "HALF_LOCKED",
107*6523a3aaSJohn Levon            9023: "LOCK_RESTORED",
108*6523a3aaSJohn Levon            9024: "KNOWN_LOCKED",
109*6523a3aaSJohn Levon            9025: "KNOWN_UNLOCKED",
1101f5207b7SJohn Levon            8023: "ATOMIC_INC",
1111f5207b7SJohn Levon            8024: "ATOMIC_DEC",
1121f5207b7SJohn Levon};
1131f5207b7SJohn Levon
1141f5207b7SJohn Levondef add_range(rl, min_val, max_val):
1151f5207b7SJohn Levon    check_next = 0
1161f5207b7SJohn Levon    done = 0
1171f5207b7SJohn Levon    ret = []
1181f5207b7SJohn Levon    idx = 0
1191f5207b7SJohn Levon
1201f5207b7SJohn Levon    if len(rl) == 0:
1211f5207b7SJohn Levon        return [[min_val, max_val]]
1221f5207b7SJohn Levon
1231f5207b7SJohn Levon    for idx in range(len(rl)):
1241f5207b7SJohn Levon        cur_min = rl[idx][0]
1251f5207b7SJohn Levon        cur_max = rl[idx][1]
1261f5207b7SJohn Levon
1271f5207b7SJohn Levon        # we already merged the new range but we might need to change later
1281f5207b7SJohn Levon        # ranges if they over lap with more than one
1291f5207b7SJohn Levon        if check_next:
1301f5207b7SJohn Levon            # join with added range
1311f5207b7SJohn Levon            if max_val + 1 == cur_min:
1321f5207b7SJohn Levon                ret[len(ret) - 1][1] = cur_max
1331f5207b7SJohn Levon                done = 1
1341f5207b7SJohn Levon                break
1351f5207b7SJohn Levon            # don't overlap
1361f5207b7SJohn Levon            if max_val < cur_min:
1371f5207b7SJohn Levon                ret.append([cur_min, cur_max])
1381f5207b7SJohn Levon                done = 1
1391f5207b7SJohn Levon                break
1401f5207b7SJohn Levon            # partially overlap
1411f5207b7SJohn Levon            if max_val < cur_max:
1421f5207b7SJohn Levon                ret[len(ret) - 1][1] = cur_max
1431f5207b7SJohn Levon                done = 1
1441f5207b7SJohn Levon                break
1451f5207b7SJohn Levon            # completely overlap
1461f5207b7SJohn Levon            continue
1471f5207b7SJohn Levon
1481f5207b7SJohn Levon        # join 2 ranges into one
1491f5207b7SJohn Levon        if max_val + 1 == cur_min:
1501f5207b7SJohn Levon            ret.append([min_val, cur_max])
1511f5207b7SJohn Levon            done = 1
1521f5207b7SJohn Levon            break
1531f5207b7SJohn Levon        # range is entirely below
1541f5207b7SJohn Levon        if max_val < cur_min:
1551f5207b7SJohn Levon            ret.append([min_val, max_val])
1561f5207b7SJohn Levon            ret.append([cur_min, cur_max])
1571f5207b7SJohn Levon            done = 1
1581f5207b7SJohn Levon            break
1591f5207b7SJohn Levon        # range is partially below
1601f5207b7SJohn Levon        if min_val < cur_min:
1611f5207b7SJohn Levon            if max_val <= cur_max:
1621f5207b7SJohn Levon                ret.append([min_val, cur_max])
1631f5207b7SJohn Levon                done = 1
1641f5207b7SJohn Levon                break
1651f5207b7SJohn Levon            else:
1661f5207b7SJohn Levon                ret.append([min_val, max_val])
1671f5207b7SJohn Levon                check_next = 1
1681f5207b7SJohn Levon                continue
1691f5207b7SJohn Levon        # range already included
1701f5207b7SJohn Levon        if max_val <= cur_max:
1711f5207b7SJohn Levon            ret.append([cur_min, cur_max])
1721f5207b7SJohn Levon            done = 1
1731f5207b7SJohn Levon            break;
1741f5207b7SJohn Levon        # range partially above
1751f5207b7SJohn Levon        if min_val <= cur_max:
1761f5207b7SJohn Levon            ret.append([cur_min, max_val])
1771f5207b7SJohn Levon            check_next = 1
1781f5207b7SJohn Levon            continue
1791f5207b7SJohn Levon        # join 2 ranges on the other side
1801f5207b7SJohn Levon        if min_val - 1 == cur_max:
1811f5207b7SJohn Levon            ret.append([cur_min, max_val])
1821f5207b7SJohn Levon            check_next = 1
1831f5207b7SJohn Levon            continue
1841f5207b7SJohn Levon        # range is above
1851f5207b7SJohn Levon        ret.append([cur_min, cur_max])
1861f5207b7SJohn Levon
1871f5207b7SJohn Levon    if idx + 1 < len(rl):          # we hit a break statement
1881f5207b7SJohn Levon        ret = ret + rl[idx + 1:]
1891f5207b7SJohn Levon    elif done:                     # we hit a break on the last iteration
1901f5207b7SJohn Levon        pass
1911f5207b7SJohn Levon    elif not check_next:           # it's past the end of the rl
1921f5207b7SJohn Levon        ret.append([min_val, max_val])
1931f5207b7SJohn Levon
1941f5207b7SJohn Levon    return ret;
1951f5207b7SJohn Levon
1961f5207b7SJohn Levondef rl_union(rl1, rl2):
1971f5207b7SJohn Levon    ret = []
1981f5207b7SJohn Levon    for r in rl1:
1991f5207b7SJohn Levon        ret = add_range(ret, r[0], r[1])
2001f5207b7SJohn Levon    for r in rl2:
2011f5207b7SJohn Levon        ret = add_range(ret, r[0], r[1])
2021f5207b7SJohn Levon
2031f5207b7SJohn Levon    if (rl1 or rl2) and not ret:
2041f5207b7SJohn Levon        print "bug: merging %s + %s gives empty" %(rl1, rl2)
2051f5207b7SJohn Levon
2061f5207b7SJohn Levon    return ret
2071f5207b7SJohn Levon
2081f5207b7SJohn Levondef txt_to_val(txt):
2091f5207b7SJohn Levon    if txt == "s64min":
2101f5207b7SJohn Levon        return -(2**63)
2111f5207b7SJohn Levon    elif txt == "s32min":
2121f5207b7SJohn Levon        return -(2**31)
2131f5207b7SJohn Levon    elif txt == "s16min":
2141f5207b7SJohn Levon        return -(2**15)
2151f5207b7SJohn Levon    elif txt == "s64max":
2161f5207b7SJohn Levon        return 2**63 - 1
2171f5207b7SJohn Levon    elif txt == "s32max":
2181f5207b7SJohn Levon        return 2**31 - 1
2191f5207b7SJohn Levon    elif txt == "s16max":
2201f5207b7SJohn Levon        return 2**15 - 1
2211f5207b7SJohn Levon    elif txt == "u64max":
2221f5207b7SJohn Levon        return 2**64 - 1
223efe51d0cSJohn Levon    elif txt == "ptr_max":
224efe51d0cSJohn Levon        return 2**64 - 1
2251f5207b7SJohn Levon    elif txt == "u32max":
2261f5207b7SJohn Levon        return 2**32 - 1
2271f5207b7SJohn Levon    elif txt == "u16max":
2281f5207b7SJohn Levon        return 2**16 - 1
2291f5207b7SJohn Levon    else:
2301f5207b7SJohn Levon        try:
2311f5207b7SJohn Levon            return int(txt)
2321f5207b7SJohn Levon        except ValueError:
2331f5207b7SJohn Levon            return 0
2341f5207b7SJohn Levon
2351f5207b7SJohn Levondef val_to_txt(val):
2361f5207b7SJohn Levon    if val == -(2**63):
2371f5207b7SJohn Levon        return "s64min"
2381f5207b7SJohn Levon    elif val == -(2**31):
2391f5207b7SJohn Levon        return "s32min"
2401f5207b7SJohn Levon    elif val == -(2**15):
2411f5207b7SJohn Levon        return "s16min"
2421f5207b7SJohn Levon    elif val == 2**63 - 1:
2431f5207b7SJohn Levon        return "s64max"
2441f5207b7SJohn Levon    elif val == 2**31 - 1:
2451f5207b7SJohn Levon        return "s32max"
2461f5207b7SJohn Levon    elif val == 2**15 - 1:
2471f5207b7SJohn Levon        return "s16max"
2481f5207b7SJohn Levon    elif val == 2**64 - 1:
2491f5207b7SJohn Levon        return "u64max"
2501f5207b7SJohn Levon    elif val == 2**32 - 1:
2511f5207b7SJohn Levon        return "u32max"
2521f5207b7SJohn Levon    elif val == 2**16 - 1:
2531f5207b7SJohn Levon        return "u16max"
2541f5207b7SJohn Levon    elif val < 0:
2551f5207b7SJohn Levon        return "(%d)" %(val)
2561f5207b7SJohn Levon    else:
2571f5207b7SJohn Levon        return "%d" %(val)
2581f5207b7SJohn Levon
2591f5207b7SJohn Levondef get_next_str(txt):
2601f5207b7SJohn Levon    val = ""
2611f5207b7SJohn Levon    parsed = 0
2621f5207b7SJohn Levon
2631f5207b7SJohn Levon    if txt[0] == '(':
2641f5207b7SJohn Levon        parsed += 1
2651f5207b7SJohn Levon        for char in txt[1:]:
2661f5207b7SJohn Levon            if char == ')':
2671f5207b7SJohn Levon                break
2681f5207b7SJohn Levon            parsed += 1
2691f5207b7SJohn Levon        val = txt[1:parsed]
2701f5207b7SJohn Levon        parsed += 1
2711f5207b7SJohn Levon    elif txt[0] == 's' or txt[0] == 'u':
2721f5207b7SJohn Levon        parsed += 6
2731f5207b7SJohn Levon        val = txt[:parsed]
2741f5207b7SJohn Levon    else:
2751f5207b7SJohn Levon        if txt[0] == '-':
2761f5207b7SJohn Levon            parsed += 1
2771f5207b7SJohn Levon        for char in txt[parsed:]:
278c85f09ccSJohn Levon            if char == '-' or char == '[':
2791f5207b7SJohn Levon                break
2801f5207b7SJohn Levon            parsed += 1
2811f5207b7SJohn Levon        val = txt[:parsed]
2821f5207b7SJohn Levon    return [parsed, val]
2831f5207b7SJohn Levon
2841f5207b7SJohn Levondef txt_to_rl(txt):
2851f5207b7SJohn Levon    if len(txt) == 0:
2861f5207b7SJohn Levon        return []
2871f5207b7SJohn Levon
2881f5207b7SJohn Levon    ret = []
2891f5207b7SJohn Levon    pairs = txt.split(",")
2901f5207b7SJohn Levon    for pair in pairs:
2911f5207b7SJohn Levon        cnt, min_str = get_next_str(pair)
2921f5207b7SJohn Levon        if cnt == len(pair):
2931f5207b7SJohn Levon            max_str = min_str
2941f5207b7SJohn Levon        else:
2951f5207b7SJohn Levon            cnt, max_str = get_next_str(pair[cnt + 1:])
2961f5207b7SJohn Levon        min_val = txt_to_val(min_str)
2971f5207b7SJohn Levon        max_val = txt_to_val(max_str)
2981f5207b7SJohn Levon        ret.append([min_val, max_val])
2991f5207b7SJohn Levon
3001f5207b7SJohn Levon#    Hm...  Smatch won't call INT_MAX s32max if the variable is unsigned.
3011f5207b7SJohn Levon#    if txt != rl_to_txt(ret):
3021f5207b7SJohn Levon#        print "bug: converting: text = %s rl = %s internal = %s" %(txt, rl_to_txt(ret), ret)
3031f5207b7SJohn Levon
3041f5207b7SJohn Levon    return ret
3051f5207b7SJohn Levon
3061f5207b7SJohn Levondef rl_to_txt(rl):
3071f5207b7SJohn Levon    ret = ""
3081f5207b7SJohn Levon    for idx in range(len(rl)):
3091f5207b7SJohn Levon        cur_min = rl[idx][0]
3101f5207b7SJohn Levon        cur_max = rl[idx][1]
3111f5207b7SJohn Levon
3121f5207b7SJohn Levon        if idx != 0:
3131f5207b7SJohn Levon            ret += ","
3141f5207b7SJohn Levon
3151f5207b7SJohn Levon        if cur_min == cur_max:
3161f5207b7SJohn Levon            ret += val_to_txt(cur_min)
3171f5207b7SJohn Levon        else:
3181f5207b7SJohn Levon            ret += val_to_txt(cur_min)
3191f5207b7SJohn Levon            ret += "-"
3201f5207b7SJohn Levon            ret += val_to_txt(cur_max)
3211f5207b7SJohn Levon    return ret
3221f5207b7SJohn Levon
3231f5207b7SJohn Levondef type_to_str(type_int):
3241f5207b7SJohn Levon
3251f5207b7SJohn Levon    t = int(type_int)
3261f5207b7SJohn Levon    if db_types.has_key(t):
3271f5207b7SJohn Levon        return db_types[t]
3281f5207b7SJohn Levon    return type_int
3291f5207b7SJohn Levon
3301f5207b7SJohn Levondef type_to_int(type_string):
3311f5207b7SJohn Levon    for k in db_types.keys():
3321f5207b7SJohn Levon        if db_types[k] == type_string:
3331f5207b7SJohn Levon            return k
3341f5207b7SJohn Levon    return -1
3351f5207b7SJohn Levon
3361f5207b7SJohn Levondef display_caller_info(printed, cur, param_names):
3371f5207b7SJohn Levon    for txt in cur:
3381f5207b7SJohn Levon        if not printed:
3391f5207b7SJohn Levon            print "file | caller | function | type | parameter | key | value |"
3401f5207b7SJohn Levon        printed = 1
3411f5207b7SJohn Levon
3421f5207b7SJohn Levon        parameter = int(txt[6])
3431f5207b7SJohn Levon        key = txt[7]
3441f5207b7SJohn Levon        if len(param_names) and parameter in param_names:
3451f5207b7SJohn Levon            key = key.replace("$", param_names[parameter])
3461f5207b7SJohn Levon
3471f5207b7SJohn Levon        print "%20s | %20s | %20s |" %(txt[0], txt[1], txt[2]),
3481f5207b7SJohn Levon        print " %10s |" %(type_to_str(txt[5])),
3491f5207b7SJohn Levon        print " %d | %s | %s" %(parameter, key, txt[8])
3501f5207b7SJohn Levon    return printed
3511f5207b7SJohn Levon
3521f5207b7SJohn Levondef get_caller_info(filename, ptrs, my_type):
3531f5207b7SJohn Levon    cur = con.cursor()
3541f5207b7SJohn Levon    param_names = get_param_names(filename, func)
3551f5207b7SJohn Levon    printed = 0
3561f5207b7SJohn Levon    type_filter = ""
3571f5207b7SJohn Levon    if my_type != "":
3581f5207b7SJohn Levon        type_filter = "and type = %d" %(type_to_int(my_type))
3591f5207b7SJohn Levon    for ptr in ptrs:
3601f5207b7SJohn Levon        cur.execute("select * from caller_info where function = '%s' %s;" %(ptr, type_filter))
3611f5207b7SJohn Levon        printed = display_caller_info(printed, cur, param_names)
3621f5207b7SJohn Levon
3631f5207b7SJohn Levondef print_caller_info(filename, func, my_type = ""):
3641f5207b7SJohn Levon    ptrs = get_function_pointers(func)
3651f5207b7SJohn Levon    get_caller_info(filename, ptrs, my_type)
3661f5207b7SJohn Levon
3671f5207b7SJohn Levondef merge_values(param_names, vals, cur):
3681f5207b7SJohn Levon    for txt in cur:
3691f5207b7SJohn Levon        parameter = int(txt[0])
3701f5207b7SJohn Levon        name = txt[1]
3711f5207b7SJohn Levon        rl = txt_to_rl(txt[2])
3721f5207b7SJohn Levon        if parameter in param_names:
3731f5207b7SJohn Levon            name = name.replace("$", param_names[parameter])
3741f5207b7SJohn Levon
3751f5207b7SJohn Levon        if not parameter in vals:
3761f5207b7SJohn Levon            vals[parameter] = {}
3771f5207b7SJohn Levon
3781f5207b7SJohn Levon        # the first item on the list is the number of rows.  it's incremented
3791f5207b7SJohn Levon        # every time we call merge_values().
3801f5207b7SJohn Levon        if name in vals[parameter]:
3811f5207b7SJohn Levon            vals[parameter][name] = [vals[parameter][name][0] + 1, rl_union(vals[parameter][name][1], rl)]
3821f5207b7SJohn Levon        else:
3831f5207b7SJohn Levon            vals[parameter][name] = [1, rl]
3841f5207b7SJohn Levon
3851f5207b7SJohn Levondef get_param_names(filename, func):
3861f5207b7SJohn Levon    cur = con.cursor()
3871f5207b7SJohn Levon    param_names = {}
3881f5207b7SJohn Levon    cur.execute("select parameter, value from parameter_name where file = '%s' and function = '%s';" %(filename, func))
3891f5207b7SJohn Levon    for txt in cur:
3901f5207b7SJohn Levon        parameter = int(txt[0])
3911f5207b7SJohn Levon        name = txt[1]
3921f5207b7SJohn Levon        param_names[parameter] = name
3931f5207b7SJohn Levon    if len(param_names):
3941f5207b7SJohn Levon        return param_names
3951f5207b7SJohn Levon
3961f5207b7SJohn Levon    cur.execute("select parameter, value from parameter_name where function = '%s';" %(func))
3971f5207b7SJohn Levon    for txt in cur:
3981f5207b7SJohn Levon        parameter = int(txt[0])
3991f5207b7SJohn Levon        name = txt[1]
4001f5207b7SJohn Levon        param_names[parameter] = name
4011f5207b7SJohn Levon    return param_names
4021f5207b7SJohn Levon
4031f5207b7SJohn Levondef get_caller_count(ptrs):
4041f5207b7SJohn Levon    cur = con.cursor()
4051f5207b7SJohn Levon    count = 0
4061f5207b7SJohn Levon    for ptr in ptrs:
4071f5207b7SJohn Levon        cur.execute("select count(distinct(call_id)) from caller_info where function = '%s';" %(ptr))
4081f5207b7SJohn Levon        for txt in cur:
4091f5207b7SJohn Levon            count += int(txt[0])
4101f5207b7SJohn Levon    return count
4111f5207b7SJohn Levon
4121f5207b7SJohn Levondef print_merged_caller_values(filename, func, ptrs, param_names, call_cnt):
4131f5207b7SJohn Levon    cur = con.cursor()
4141f5207b7SJohn Levon    vals = {}
4151f5207b7SJohn Levon    for ptr in ptrs:
4161f5207b7SJohn Levon        cur.execute("select parameter, key, value from caller_info where function = '%s' and type = %d;" %(ptr, type_to_int("PARAM_VALUE")))
4171f5207b7SJohn Levon        merge_values(param_names, vals, cur);
4181f5207b7SJohn Levon
4191f5207b7SJohn Levon    for param in sorted(vals):
4201f5207b7SJohn Levon        for name in sorted(vals[param]):
4211f5207b7SJohn Levon            if vals[param][name][0] != call_cnt:
4221f5207b7SJohn Levon                continue
4231f5207b7SJohn Levon            print "%d %s -> %s" %(param, name, rl_to_txt(vals[param][name][1]))
4241f5207b7SJohn Levon
4251f5207b7SJohn Levon
4261f5207b7SJohn Levondef print_unmerged_caller_values(filename, func, ptrs, param_names):
4271f5207b7SJohn Levon    cur = con.cursor()
4281f5207b7SJohn Levon    for ptr in ptrs:
4291f5207b7SJohn Levon        prev = -1
4301f5207b7SJohn Levon        cur.execute("select file, caller, call_id, parameter, key, value from caller_info where function = '%s' and type = %d;" %(ptr, type_to_int("PARAM_VALUE")))
4311f5207b7SJohn Levon        for filename, caller, call_id, parameter, name, value in cur:
4321f5207b7SJohn Levon            if prev != int(call_id):
4331f5207b7SJohn Levon                prev = int(call_id)
4341f5207b7SJohn Levon
4351f5207b7SJohn Levon            parameter = int(parameter)
4361f5207b7SJohn Levon            if parameter < len(param_names):
4371f5207b7SJohn Levon                name = name.replace("$", param_names[parameter])
4381f5207b7SJohn Levon            else:
4391f5207b7SJohn Levon                name = name.replace("$", "$%d" %(parameter))
4401f5207b7SJohn Levon
4411f5207b7SJohn Levon            print "%s | %s | %s | %s" %(filename, caller, name, value)
4421f5207b7SJohn Levon        print "=========================="
4431f5207b7SJohn Levon
4441f5207b7SJohn Levondef print_caller_values(filename, func, ptrs):
4451f5207b7SJohn Levon    param_names = get_param_names(filename, func)
4461f5207b7SJohn Levon    call_cnt = get_caller_count(ptrs)
4471f5207b7SJohn Levon
4481f5207b7SJohn Levon    print_merged_caller_values(filename, func, ptrs, param_names, call_cnt)
4491f5207b7SJohn Levon    print "=========================="
4501f5207b7SJohn Levon    print_unmerged_caller_values(filename, func, ptrs, param_names)
4511f5207b7SJohn Levon
4521f5207b7SJohn Levondef caller_info_values(filename, func):
4531f5207b7SJohn Levon    ptrs = get_function_pointers(func)
4541f5207b7SJohn Levon    print_caller_values(filename, func, ptrs)
4551f5207b7SJohn Levon
4561f5207b7SJohn Levondef print_return_states(func):
4571f5207b7SJohn Levon    cur = con.cursor()
4581f5207b7SJohn Levon    cur.execute("select * from return_states where function = '%s';" %(func))
4591f5207b7SJohn Levon    count = 0
4601f5207b7SJohn Levon    for txt in cur:
4611f5207b7SJohn Levon        printed = 1
4621f5207b7SJohn Levon        if count == 0:
4631f5207b7SJohn Levon            print "file | function | return_id | return_value | type | param | key | value |"
4641f5207b7SJohn Levon        count += 1
4651f5207b7SJohn Levon        print "%s | %s | %2s | %13s" %(txt[0], txt[1], txt[3], txt[4]),
4661f5207b7SJohn Levon        print "| %13s |" %(type_to_str(txt[6])),
4671f5207b7SJohn Levon        print " %2d | %20s | %20s |" %(txt[7], txt[8], txt[9])
4681f5207b7SJohn Levon
4691f5207b7SJohn Levondef print_return_implies(func):
4701f5207b7SJohn Levon    cur = con.cursor()
4711f5207b7SJohn Levon    cur.execute("select * from return_implies where function = '%s';" %(func))
4721f5207b7SJohn Levon    count = 0
4731f5207b7SJohn Levon    for txt in cur:
4741f5207b7SJohn Levon        if not count:
4751f5207b7SJohn Levon            print "file | function | type | param | key | value |"
4761f5207b7SJohn Levon        count += 1
4771f5207b7SJohn Levon        print "%15s | %15s" %(txt[0], txt[1]),
4781f5207b7SJohn Levon        print "| %15s" %(type_to_str(txt[4])),
4791f5207b7SJohn Levon        print "| %3d | %s | %15s |" %(txt[5], txt[6], txt[7])
4801f5207b7SJohn Levon
4811f5207b7SJohn Levondef print_type_size(struct_type, member):
4821f5207b7SJohn Levon    cur = con.cursor()
4831f5207b7SJohn Levon    cur.execute("select * from type_size where type like '(struct %s)->%s';" %(struct_type, member))
4841f5207b7SJohn Levon    print "type | size"
4851f5207b7SJohn Levon    for txt in cur:
4861f5207b7SJohn Levon        print "%-15s | %s" %(txt[0], txt[1])
4871f5207b7SJohn Levon
4881f5207b7SJohn Levon    cur.execute("select * from function_type_size where type like '(struct %s)->%s';" %(struct_type, member))
4891f5207b7SJohn Levon    print "file | function | type | size"
4901f5207b7SJohn Levon    for txt in cur:
4911f5207b7SJohn Levon        print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[1], txt[2], txt[3])
4921f5207b7SJohn Levon
4931f5207b7SJohn Levondef print_data_info(struct_type, member):
4941f5207b7SJohn Levon    cur = con.cursor()
4951f5207b7SJohn Levon    cur.execute("select * from data_info where data like '(struct %s)->%s';" %(struct_type, member))
4961f5207b7SJohn Levon    print "file | data | type | value"
4971f5207b7SJohn Levon    for txt in cur:
4981f5207b7SJohn Levon        print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[1], type_to_str(txt[2]), txt[3])
4991f5207b7SJohn Levon
5001f5207b7SJohn Levondef print_fn_ptrs(func):
5011f5207b7SJohn Levon    ptrs = get_function_pointers(func)
5021f5207b7SJohn Levon    if not ptrs:
5031f5207b7SJohn Levon        return
5041f5207b7SJohn Levon    print "%s = " %(func),
5051f5207b7SJohn Levon    print(ptrs)
5061f5207b7SJohn Levon
5071f5207b7SJohn Levondef print_functions(member):
5081f5207b7SJohn Levon    cur = con.cursor()
5091f5207b7SJohn Levon    cur.execute("select * from function_ptr where ptr like '%%->%s';" %(member))
5101f5207b7SJohn Levon    print "File | Pointer | Function | Static"
5111f5207b7SJohn Levon    for txt in cur:
5121f5207b7SJohn Levon        print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[2], txt[1], txt[3])
5131f5207b7SJohn Levon
5141f5207b7SJohn Levondef get_callers(func):
5151f5207b7SJohn Levon    ret = []
5161f5207b7SJohn Levon    cur = con.cursor()
5171f5207b7SJohn Levon    ptrs = get_function_pointers(func)
5181f5207b7SJohn Levon    for ptr in ptrs:
5191f5207b7SJohn Levon        cur.execute("select distinct caller from caller_info where function = '%s';" %(ptr))
5201f5207b7SJohn Levon        for row in cur:
5211f5207b7SJohn Levon            ret.append(row[0])
5221f5207b7SJohn Levon    return ret
5231f5207b7SJohn Levon
5241f5207b7SJohn Levonprinted_funcs = []
5251f5207b7SJohn Levondef call_tree_helper(func, indent = 0):
5261f5207b7SJohn Levon    global printed_funcs
5271f5207b7SJohn Levon    if func in printed_funcs:
5281f5207b7SJohn Levon        return
5291f5207b7SJohn Levon    print "%s%s()" %(" " * indent, func)
5301f5207b7SJohn Levon    if func == "too common":
5311f5207b7SJohn Levon        return
5321f5207b7SJohn Levon    if indent > 6:
5331f5207b7SJohn Levon        return
5341f5207b7SJohn Levon    printed_funcs.append(func)
5351f5207b7SJohn Levon    callers = get_callers(func)
5361f5207b7SJohn Levon    if len(callers) >= 20:
5371f5207b7SJohn Levon        print "Over 20 callers for %s()" %(func)
5381f5207b7SJohn Levon        return
5391f5207b7SJohn Levon    for caller in callers:
5401f5207b7SJohn Levon        call_tree_helper(caller, indent + 2)
5411f5207b7SJohn Levon
5421f5207b7SJohn Levondef print_call_tree(func):
5431f5207b7SJohn Levon    global printed_funcs
5441f5207b7SJohn Levon    printed_funcs = []
5451f5207b7SJohn Levon    call_tree_helper(func)
5461f5207b7SJohn Levon
5471f5207b7SJohn Levondef function_type_value(struct_type, member):
5481f5207b7SJohn Levon    cur = con.cursor()
5491f5207b7SJohn Levon    cur.execute("select * from function_type_value where type like '(struct %s)->%s';" %(struct_type, member))
5501f5207b7SJohn Levon    for txt in cur:
5511f5207b7SJohn Levon        print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
5521f5207b7SJohn Levon
553c85f09ccSJohn Levondef rl_too_big(txt):
554c85f09ccSJohn Levon    rl = txt_to_rl(txt)
555c85f09ccSJohn Levon    ret = ""
556c85f09ccSJohn Levon    for idx in range(len(rl)):
557c85f09ccSJohn Levon        cur_max = rl[idx][1]
558c85f09ccSJohn Levon        if (cur_max > 0xFFFFFFFFFFFFFF):
559c85f09ccSJohn Levon            return 1
560c85f09ccSJohn Levon
561c85f09ccSJohn Levon    return 0
562c85f09ccSJohn Levon
563c85f09ccSJohn Levondef rl_has_min_untagged(txt):
564c85f09ccSJohn Levon    rl = txt_to_rl(txt)
565c85f09ccSJohn Levon    ret = ""
566c85f09ccSJohn Levon    for idx in range(len(rl)):
567c85f09ccSJohn Levon        cur_min = rl[idx][0]
568c85f09ccSJohn Levon        if (cur_min == 0xff80000000000000):
569c85f09ccSJohn Levon            return 1
570c85f09ccSJohn Levon
571c85f09ccSJohn Levon    return 0
572c85f09ccSJohn Levon
573c85f09ccSJohn Levondef rl_is_tagged(txt):
574c85f09ccSJohn Levon    if not rl_too_big(txt):
575c85f09ccSJohn Levon        return 0
576c85f09ccSJohn Levon
577c85f09ccSJohn Levon    if rl_has_min_untagged(txt):
578c85f09ccSJohn Levon        return 0
579c85f09ccSJohn Levon
580c85f09ccSJohn Levon    return 1
581c85f09ccSJohn Levon
582c85f09ccSJohn Levondef rl_is_treat_untagged(txt):
583c85f09ccSJohn Levon    if "[u]" in txt:
584c85f09ccSJohn Levon        return 1;
585c85f09ccSJohn Levon
586c85f09ccSJohn Levon    return 0
587c85f09ccSJohn Levon
588c85f09ccSJohn Levondef parse_warns_tagged(filename):
589c85f09ccSJohn Levon    proc = subprocess.Popen(['cat %s | grep "potentially tagged" | sort | uniq' %(filename)], shell=True, stdout=subprocess.PIPE)
590c85f09ccSJohn Levon    while True:
591c85f09ccSJohn Levon        line = proc.stdout.readline()
592c85f09ccSJohn Levon        if not line:
593c85f09ccSJohn Levon            break
594c85f09ccSJohn Levon
595c85f09ccSJohn Levon	linepos = re.search("([^\s]+)", line).group(1)
596c85f09ccSJohn Levon	groupre = re.search("potentially tagged address \(([^,]+), ([^,]+), ([^\)]+)\)", line)
597c85f09ccSJohn Levon	groupre.group(1)
598c85f09ccSJohn Levon
599c85f09ccSJohn Levon	func = groupre.group(1)
600c85f09ccSJohn Levon	param = int(groupre.group(2))
601c85f09ccSJohn Levon	var = groupre.group(3)
602c85f09ccSJohn Levon
603c85f09ccSJohn Levon	if ("end" in var or "size" in var or "len" in var):
604c85f09ccSJohn Levon		continue
605c85f09ccSJohn Levon
606c85f09ccSJohn Levon	print "\n%s (func: %s, param: %d:%s) may be caused by:" %(linepos, func, param, var)
607c85f09ccSJohn Levon
608c85f09ccSJohn Levon	if (param != -1):
609c85f09ccSJohn Levon		if not find_tagged(func, param, 0, []):
610c85f09ccSJohn Levon			print "    %s (param %d) (can't walk call tree)" % (func, param)
611c85f09ccSJohn Levon	else:
612c85f09ccSJohn Levon		print "    %s (variable %s (can't walk call tree)" % (func, var)
613c85f09ccSJohn Levon
614c85f09ccSJohn Levondef find_tagged(func, param, caller_call_id, printed):
615c85f09ccSJohn Levon
616c85f09ccSJohn Levon    callers = {}
617c85f09ccSJohn Levon    cur = con.cursor()
618c85f09ccSJohn Levon    ptrs = get_function_pointers(func)
619c85f09ccSJohn Levon    found = 0
620c85f09ccSJohn Levon
621c85f09ccSJohn Levon    for ptr in ptrs:
622c85f09ccSJohn Levon        cur.execute("select call_id, value from caller_info where function = '%s' and parameter=%d and type=%d" %(ptr, param, type_to_int("DATA_SOURCE")))
623c85f09ccSJohn Levon
624c85f09ccSJohn Levon        for row in cur:
625c85f09ccSJohn Levon            if (row[1][0] == '$'):
626c85f09ccSJohn Levon                if row[0] not in callers:
627c85f09ccSJohn Levon                    callers[row[0]] = {}
628c85f09ccSJohn Levon                callers[row[0]]["param"] = int(row[1][1])
629c85f09ccSJohn Levon
630c85f09ccSJohn Levon    for ptr in ptrs:
631c85f09ccSJohn Levon        cur.execute("select caller, call_id, value from caller_info where function = '%s' and parameter=%d and type=%d" %(ptr, param, type_to_int("USER_DATA")))
632c85f09ccSJohn Levon
633c85f09ccSJohn Levon        for row in cur:
634c85f09ccSJohn Levon            if not rl_is_tagged(row[2]):
635c85f09ccSJohn Levon                continue
636c85f09ccSJohn Levon	    if rl_is_treat_untagged(row[2]):
637c85f09ccSJohn Levon	        continue
638c85f09ccSJohn Levon            found = 1
639c85f09ccSJohn Levon            if row[1] not in callers:
640c85f09ccSJohn Levon                callers[row[1]] = {}
641c85f09ccSJohn Levon            if "param" not in callers[row[1]]:
642c85f09ccSJohn Levon                line = "    %s (param ?) -> %s (param %d)" % (row[0], func, param)
643c85f09ccSJohn Levon                if line not in printed:
644c85f09ccSJohn Levon                        printed.append(line)
645c85f09ccSJohn Levon                        print line
646c85f09ccSJohn Levon                continue
647c85f09ccSJohn Levon            if row[0] not in printed:
648c85f09ccSJohn Levon                printed.append(row[0])
649c85f09ccSJohn Levon                if not find_tagged(row[0], callers[row[1]]["param"], row[1], printed):
650c85f09ccSJohn Levon                    print "    %s (param %d)" % (row[0], param)
651c85f09ccSJohn Levon
652c85f09ccSJohn Levon    return found
653c85f09ccSJohn Levon
6541f5207b7SJohn Levondef trace_callers(func, param):
6551f5207b7SJohn Levon    sources = []
6561f5207b7SJohn Levon    prev_type = 0
6571f5207b7SJohn Levon
6581f5207b7SJohn Levon    cur = con.cursor()
6591f5207b7SJohn Levon    ptrs = get_function_pointers(func)
6601f5207b7SJohn Levon    for ptr in ptrs:
6611f5207b7SJohn Levon        cur.execute("select type, caller, value from caller_info where function = '%s' and (type = 0 or type = 1014 or type = 1028) and (parameter = -1 or parameter = %d);" %(ptr, param))
6621f5207b7SJohn Levon        for row in cur:
6631f5207b7SJohn Levon            data_type = int(row[0])
6641f5207b7SJohn Levon            if data_type == 1014:
6651f5207b7SJohn Levon                sources.append((row[1], row[2]))
6661f5207b7SJohn Levon            elif data_type == 1028:
6671f5207b7SJohn Levon                sources.append(("%", row[2])) # hack...
6681f5207b7SJohn Levon            elif data_type == 0 and prev_type == 0:
6691f5207b7SJohn Levon                sources.append((row[1], ""))
6701f5207b7SJohn Levon            prev_type = data_type
6711f5207b7SJohn Levon    return sources
6721f5207b7SJohn Levon
6731f5207b7SJohn Levondef trace_param_helper(func, param, indent = 0):
6741f5207b7SJohn Levon    global printed_funcs
6751f5207b7SJohn Levon    if func in printed_funcs:
6761f5207b7SJohn Levon        return
6771f5207b7SJohn Levon    print "%s%s(param %d)" %(" " * indent, func, param)
6781f5207b7SJohn Levon    if func == "too common":
6791f5207b7SJohn Levon        return
6801f5207b7SJohn Levon    if indent > 20:
6811f5207b7SJohn Levon        return
6821f5207b7SJohn Levon    printed_funcs.append(func)
6831f5207b7SJohn Levon    sources = trace_callers(func, param)
6841f5207b7SJohn Levon    for path in sources:
6851f5207b7SJohn Levon
686c85f09ccSJohn Levon        if len(path[1]) and path[1][0] == '$':
687c85f09ccSJohn Levon            p = int(re.findall('\d+', path[1][1:])[0])
6881f5207b7SJohn Levon            trace_param_helper(path[0], p, indent + 2)
6891f5207b7SJohn Levon        elif len(path[0]) and path[0][0] == '%':
6901f5207b7SJohn Levon            print "  %s%s" %(" " * indent, path[1])
6911f5207b7SJohn Levon        else:
6921f5207b7SJohn Levon            print "* %s%s %s" %(" " * (indent - 1), path[0], path[1])
6931f5207b7SJohn Levon
6941f5207b7SJohn Levondef trace_param(func, param):
6951f5207b7SJohn Levon    global printed_funcs
6961f5207b7SJohn Levon    printed_funcs = []
6971f5207b7SJohn Levon    print "tracing %s %d" %(func, param)
6981f5207b7SJohn Levon    trace_param_helper(func, param)
6991f5207b7SJohn Levon
7001f5207b7SJohn Levondef print_locals(filename):
7011f5207b7SJohn Levon    cur = con.cursor()
7021f5207b7SJohn Levon    cur.execute("select file,data,value from data_info where file = '%s' and type = 8029 and value != 0;" %(filename))
7031f5207b7SJohn Levon    for txt in cur:
7041f5207b7SJohn Levon        print "%s | %s | %s" %(txt[0], txt[1], txt[2])
7051f5207b7SJohn Levon
7061f5207b7SJohn Levondef constraint(struct_type, member):
7071f5207b7SJohn Levon    cur = con.cursor()
7081f5207b7SJohn Levon    cur.execute("select * from constraints_required where data like '(struct %s)->%s' or bound like '(struct %s)->%s';" %(struct_type, member, struct_type, member))
7091f5207b7SJohn Levon    for txt in cur:
7101f5207b7SJohn Levon        print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
7111f5207b7SJohn Levon
7121f5207b7SJohn Levonif len(sys.argv) < 2:
7131f5207b7SJohn Levon    usage()
7141f5207b7SJohn Levon
7151f5207b7SJohn Levonif len(sys.argv) == 2:
7161f5207b7SJohn Levon    func = sys.argv[1]
7171f5207b7SJohn Levon    print_caller_info("", func)
718efe51d0cSJohn Levonelif sys.argv[1] == "info":
719efe51d0cSJohn Levon    my_type = ""
720efe51d0cSJohn Levon    if len(sys.argv) == 4:
721efe51d0cSJohn Levon        my_type = sys.argv[3]
722efe51d0cSJohn Levon    func = sys.argv[2]
723efe51d0cSJohn Levon    print_caller_info("", func, my_type)
7241f5207b7SJohn Levonelif sys.argv[1] == "call_info":
7251f5207b7SJohn Levon    if len(sys.argv) != 4:
7261f5207b7SJohn Levon        usage()
7271f5207b7SJohn Levon    filename = sys.argv[2]
7281f5207b7SJohn Levon    func = sys.argv[3]
7291f5207b7SJohn Levon    caller_info_values(filename, func)
7301f5207b7SJohn Levon    print_caller_info(filename, func)
7311f5207b7SJohn Levonelif sys.argv[1] == "function_ptr" or sys.argv[1] == "fn_ptr":
7321f5207b7SJohn Levon    func = sys.argv[2]
7331f5207b7SJohn Levon    print_fn_ptrs(func)
7341f5207b7SJohn Levonelif sys.argv[1] == "return_states":
7351f5207b7SJohn Levon    func = sys.argv[2]
7361f5207b7SJohn Levon    print_return_states(func)
7371f5207b7SJohn Levon    print "================================================"
7381f5207b7SJohn Levon    print_return_implies(func)
7391f5207b7SJohn Levonelif sys.argv[1] == "return_implies":
7401f5207b7SJohn Levon    func = sys.argv[2]
7411f5207b7SJohn Levon    print_return_implies(func)
7421f5207b7SJohn Levonelif sys.argv[1] == "type_size" or sys.argv[1] == "buf_size":
7431f5207b7SJohn Levon    struct_type = sys.argv[2]
7441f5207b7SJohn Levon    member = sys.argv[3]
7451f5207b7SJohn Levon    print_type_size(struct_type, member)
7461f5207b7SJohn Levonelif sys.argv[1] == "data_info":
7471f5207b7SJohn Levon    struct_type = sys.argv[2]
7481f5207b7SJohn Levon    member = sys.argv[3]
7491f5207b7SJohn Levon    print_data_info(struct_type, member)
7501f5207b7SJohn Levonelif sys.argv[1] == "call_tree":
7511f5207b7SJohn Levon    func = sys.argv[2]
7521f5207b7SJohn Levon    print_call_tree(func)
753c85f09ccSJohn Levonelif sys.argv[1] == "find_tagged":
754c85f09ccSJohn Levon    func = sys.argv[2]
755c85f09ccSJohn Levon    param = int(sys.argv[3])
756c85f09ccSJohn Levon    find_tagged(func, param, 0, [])
757c85f09ccSJohn Levonelif sys.argv[1] == "parse_warns_tagged":
758c85f09ccSJohn Levon    filename = sys.argv[2]
759c85f09ccSJohn Levon    parse_warns_tagged(filename)
7601f5207b7SJohn Levonelif sys.argv[1] == "where":
7611f5207b7SJohn Levon    if len(sys.argv) == 3:
7621f5207b7SJohn Levon        struct_type = "%"
7631f5207b7SJohn Levon        member = sys.argv[2]
7641f5207b7SJohn Levon    elif len(sys.argv) == 4:
7651f5207b7SJohn Levon        struct_type = sys.argv[2]
7661f5207b7SJohn Levon        member = sys.argv[3]
7671f5207b7SJohn Levon    function_type_value(struct_type, member)
7681f5207b7SJohn Levonelif sys.argv[1] == "local":
7691f5207b7SJohn Levon    filename = sys.argv[2]
7701f5207b7SJohn Levon    variable = ""
7711f5207b7SJohn Levon    if len(sys.argv) == 4:
7721f5207b7SJohn Levon        variable = sys.argv[3]
7731f5207b7SJohn Levon    local_values(filename, variable)
7741f5207b7SJohn Levonelif sys.argv[1] == "functions":
7751f5207b7SJohn Levon    member = sys.argv[2]
7761f5207b7SJohn Levon    print_functions(member)
7771f5207b7SJohn Levonelif sys.argv[1] == "trace_param":
7781f5207b7SJohn Levon    if len(sys.argv) != 4:
7791f5207b7SJohn Levon        usage()
7801f5207b7SJohn Levon    func = sys.argv[2]
7811f5207b7SJohn Levon    param = int(sys.argv[3])
7821f5207b7SJohn Levon    trace_param(func, param)
7831f5207b7SJohn Levonelif sys.argv[1] == "locals":
7841f5207b7SJohn Levon    if len(sys.argv) != 3:
7851f5207b7SJohn Levon        usage()
7861f5207b7SJohn Levon    filename = sys.argv[2]
7871f5207b7SJohn Levon    print_locals(filename);
7881f5207b7SJohn Levonelif sys.argv[1] == "constraint":
7891f5207b7SJohn Levon    if len(sys.argv) == 3:
7901f5207b7SJohn Levon        struct_type = "%"
7911f5207b7SJohn Levon        member = sys.argv[2]
7921f5207b7SJohn Levon    elif len(sys.argv) == 4:
7931f5207b7SJohn Levon        struct_type = sys.argv[2]
7941f5207b7SJohn Levon        member = sys.argv[3]
7951f5207b7SJohn Levon    constraint(struct_type, member)
7961f5207b7SJohn Levonelse:
7971f5207b7SJohn Levon    usage()
798