From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com ([217.140.110.172]:38118 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728056AbfJGPf5 (ORCPT ); Mon, 7 Oct 2019 11:35:57 -0400 From: Andrew Murray Subject: [RFC PATCH 4/7] smdb.py: add find_tagged and parse_warns_tagged commands Date: Mon, 7 Oct 2019 16:35:42 +0100 Message-Id: <20191007153545.23231-5-andrew.murray@arm.com> In-Reply-To: <20191007153545.23231-1-andrew.murray@arm.com> References: <20191007153545.23231-1-andrew.murray@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: smatch-owner@vger.kernel.org List-ID: To: Dan Carpenter , Catalin.Marinas@arm.com Cc: smatch@vger.kernel.org The find_tagged command follows a given parameter up the call stack as far as it can, so long as the parameter contains user data and the top byte is non-zero. This is helpful to identify functions that should untag a tagged address. The parse_warns_tagged command parses the smatch_warns.txt file and calls find_tagged for each tagged related warning, thus providing a summary of all issues found and their potential causes. Signed-off-by: Andrew Murray --- smatch_data/db/smdb.py | 103 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/smatch_data/db/smdb.py b/smatch_data/db/smdb.py index 80c2df59af01..ba46b01a4d08 100755 --- a/smatch_data/db/smdb.py +++ b/smatch_data/db/smdb.py @@ -7,6 +7,7 @@ import sqlite3 import sys import re +import subprocess try: con = sqlite3.connect('smatch_db.sqlite') @@ -25,6 +26,8 @@ def usage(): print "data_info - information about a given data type" print "function_ptr - which function pointers point to this" print "trace_param - trace where a parameter came from" + print "find_tagged - find the source of a tagged value (arm64)" + print "parse_warns_tagged - parse warns file for summary of tagged issues (arm64)" print "locals - print the local values in a file." sys.exit(1) @@ -542,6 +545,99 @@ def function_type_value(struct_type, member): for txt in cur: print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3]) +def rl_too_big(txt): + rl = txt_to_rl(txt) + ret = "" + for idx in range(len(rl)): + cur_max = rl[idx][1] + if (cur_max > 0xFFFFFFFFFFFFFF): + return 1 + + return 0 + +def rl_has_min_untagged(txt): + rl = txt_to_rl(txt) + ret = "" + for idx in range(len(rl)): + cur_min = rl[idx][0] + if (cur_min == 0xff80000000000000): + return 1 + + return 0 + +def rl_is_tagged(txt): + if not rl_too_big(txt): + return 0 + + if rl_has_min_untagged(txt): + return 0 + + return 1 + +def parse_warns_tagged(filename): + proc = subprocess.Popen(['cat %s | grep "potentially tagged" | sort | uniq' %(filename)], shell=True, stdout=subprocess.PIPE) + while True: + line = proc.stdout.readline() + if not line: + break + + linepos = re.search("([^\s]+)", line).group(1) + groupre = re.search("potentially tagged address \(([^,]+), ([^,]+), ([^\)]+)\)", line) + groupre.group(1) + + func = groupre.group(1) + param = int(groupre.group(2)) + var = groupre.group(3) + + if ("end" in var or "size" in var or "len" in var): + continue + + print "\n%s (func: %s, param: %d:%s) may be caused by:" %(linepos, func, param, var) + + if (param != -1): + if not find_tagged(func, param, 0, []): + print " %s (param %d) (can't walk call tree)" % (func, param) + else: + print " %s (variable %s (can't walk call tree)" % (func, var) + +def find_tagged(func, param, caller_call_id, printed): + + callers = {} + cur = con.cursor() + ptrs = get_function_pointers(func) + found = 0 + + for ptr in ptrs: + 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"))) + + for row in cur: + if (row[1][0] == '$'): + if row[0] not in callers: + callers[row[0]] = {} + callers[row[0]]["param"] = int(row[1][1]) + + for ptr in ptrs: + 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"))) + + for row in cur: + if not rl_is_tagged(row[2]): + continue + found = 1 + if row[1] not in callers: + callers[row[1]] = {} + if "param" not in callers[row[1]]: + line = " %s (param ?) -> %s (param %d)" % (row[0], func, param) + if line not in printed: + printed.append(line) + print line + continue + if row[0] not in printed: + printed.append(row[0]) + if not find_tagged(row[0], callers[row[1]]["param"], row[1], printed): + print " %s (param %d)" % (row[0], param) + + return found + def trace_callers(func, param): sources = [] prev_type = 0 @@ -641,6 +737,13 @@ elif sys.argv[1] == "data_info": elif sys.argv[1] == "call_tree": func = sys.argv[2] print_call_tree(func) +elif sys.argv[1] == "find_tagged": + func = sys.argv[2] + param = int(sys.argv[3]) + find_tagged(func, param, 0, []) +elif sys.argv[1] == "parse_warns_tagged": + filename = sys.argv[2] + parse_warns_tagged(filename) elif sys.argv[1] == "where": if len(sys.argv) == 3: struct_type = "%" -- 2.21.0