Print this page
new smatch

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_data/db/smdb.py
          +++ new/usr/src/tools/smatch/src/smatch_data/db/smdb.py
   1    1  #!/usr/bin/python
   2    2  
   3    3  # Copyright (C) 2013 Oracle.
   4    4  #
   5    5  # Licensed under the Open Software License version 1.1
   6    6  
   7    7  import sqlite3
   8    8  import sys
   9    9  import re
       10 +import subprocess
  10   11  
  11   12  try:
  12   13      con = sqlite3.connect('smatch_db.sqlite')
  13   14  except sqlite3.Error, e:
  14   15      print "Error %s:" % e.args[0]
  15   16      sys.exit(1)
  16   17  
  17   18  def usage():
  18   19      print "%s" %(sys.argv[0])
  19   20      print "<function> - how a function is called"
  20   21      print "info <type> - how a function is called, filtered by type"
  21   22      print "return_states <function> - what a function returns"
  22   23      print "call_tree <function> - show the call tree"
  23   24      print "where <struct_type> <member> - where a struct member is set"
  24   25      print "type_size <struct_type> <member> - how a struct member is allocated"
  25   26      print "data_info <struct_type> <member> - information about a given data type"
  26   27      print "function_ptr <function> - which function pointers point to this"
  27   28      print "trace_param <function> <param> - trace where a parameter came from"
       29 +    print "find_tagged <function> <param> - find the source of a tagged value (arm64)"
       30 +    print "parse_warns_tagged <smatch_warns.txt> - parse warns file for summary of tagged issues (arm64)"
  28   31      print "locals <file> - print the local values in a file."
  29   32      sys.exit(1)
  30   33  
  31   34  function_ptrs = []
  32   35  searched_ptrs = []
  33   36  def get_function_pointers_helper(func):
  34   37      cur = con.cursor()
  35   38      cur.execute("select distinct ptr from function_ptr where function = '%s';" %(func))
  36   39      for row in cur:
  37   40          ptr = row[0]
↓ open down ↓ 222 lines elided ↑ open up ↑
 260  263              parsed += 1
 261  264          val = txt[1:parsed]
 262  265          parsed += 1
 263  266      elif txt[0] == 's' or txt[0] == 'u':
 264  267          parsed += 6
 265  268          val = txt[:parsed]
 266  269      else:
 267  270          if txt[0] == '-':
 268  271              parsed += 1
 269  272          for char in txt[parsed:]:
 270      -            if char == '-':
      273 +            if char == '-' or char == '[':
 271  274                  break
 272  275              parsed += 1
 273  276          val = txt[:parsed]
 274  277      return [parsed, val]
 275  278  
 276  279  def txt_to_rl(txt):
 277  280      if len(txt) == 0:
 278  281          return []
 279  282  
 280  283      ret = []
↓ open down ↓ 254 lines elided ↑ open up ↑
 535  538      global printed_funcs
 536  539      printed_funcs = []
 537  540      call_tree_helper(func)
 538  541  
 539  542  def function_type_value(struct_type, member):
 540  543      cur = con.cursor()
 541  544      cur.execute("select * from function_type_value where type like '(struct %s)->%s';" %(struct_type, member))
 542  545      for txt in cur:
 543  546          print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
 544  547  
      548 +def rl_too_big(txt):
      549 +    rl = txt_to_rl(txt)
      550 +    ret = ""
      551 +    for idx in range(len(rl)):
      552 +        cur_max = rl[idx][1]
      553 +        if (cur_max > 0xFFFFFFFFFFFFFF):
      554 +            return 1
      555 +
      556 +    return 0
      557 +
      558 +def rl_has_min_untagged(txt):
      559 +    rl = txt_to_rl(txt)
      560 +    ret = ""
      561 +    for idx in range(len(rl)):
      562 +        cur_min = rl[idx][0]
      563 +        if (cur_min == 0xff80000000000000):
      564 +            return 1
      565 +
      566 +    return 0
      567 +
      568 +def rl_is_tagged(txt):
      569 +    if not rl_too_big(txt):
      570 +        return 0
      571 +
      572 +    if rl_has_min_untagged(txt):
      573 +        return 0
      574 +
      575 +    return 1
      576 +
      577 +def rl_is_treat_untagged(txt):
      578 +    if "[u]" in txt:
      579 +        return 1;
      580 +
      581 +    return 0
      582 +
      583 +def parse_warns_tagged(filename):
      584 +    proc = subprocess.Popen(['cat %s | grep "potentially tagged" | sort | uniq' %(filename)], shell=True, stdout=subprocess.PIPE)
      585 +    while True:
      586 +        line = proc.stdout.readline()
      587 +        if not line:
      588 +            break
      589 +
      590 +        linepos = re.search("([^\s]+)", line).group(1)
      591 +        groupre = re.search("potentially tagged address \(([^,]+), ([^,]+), ([^\)]+)\)", line)
      592 +        groupre.group(1)
      593 +
      594 +        func = groupre.group(1)
      595 +        param = int(groupre.group(2))
      596 +        var = groupre.group(3)
      597 +
      598 +        if ("end" in var or "size" in var or "len" in var):
      599 +                continue
      600 +
      601 +        print "\n%s (func: %s, param: %d:%s) may be caused by:" %(linepos, func, param, var)
      602 +
      603 +        if (param != -1):
      604 +                if not find_tagged(func, param, 0, []):
      605 +                        print "    %s (param %d) (can't walk call tree)" % (func, param)
      606 +        else:
      607 +                print "    %s (variable %s (can't walk call tree)" % (func, var)
      608 +
      609 +def find_tagged(func, param, caller_call_id, printed):
      610 +
      611 +    callers = {}
      612 +    cur = con.cursor()
      613 +    ptrs = get_function_pointers(func)
      614 +    found = 0
      615 +
      616 +    for ptr in ptrs:
      617 +        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")))
      618 +
      619 +        for row in cur:
      620 +            if (row[1][0] == '$'):
      621 +                if row[0] not in callers:
      622 +                    callers[row[0]] = {}
      623 +                callers[row[0]]["param"] = int(row[1][1])
      624 +
      625 +    for ptr in ptrs:
      626 +        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")))
      627 +
      628 +        for row in cur:
      629 +            if not rl_is_tagged(row[2]):
      630 +                continue
      631 +            if rl_is_treat_untagged(row[2]):
      632 +                continue
      633 +            found = 1
      634 +            if row[1] not in callers:
      635 +                callers[row[1]] = {}
      636 +            if "param" not in callers[row[1]]:
      637 +                line = "    %s (param ?) -> %s (param %d)" % (row[0], func, param)
      638 +                if line not in printed:
      639 +                        printed.append(line)
      640 +                        print line
      641 +                continue
      642 +            if row[0] not in printed:
      643 +                printed.append(row[0])
      644 +                if not find_tagged(row[0], callers[row[1]]["param"], row[1], printed):
      645 +                    print "    %s (param %d)" % (row[0], param)
      646 +
      647 +    return found
      648 +
 545  649  def trace_callers(func, param):
 546  650      sources = []
 547  651      prev_type = 0
 548  652  
 549  653      cur = con.cursor()
 550  654      ptrs = get_function_pointers(func)
 551  655      for ptr in ptrs:
 552  656          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))
 553  657          for row in cur:
 554  658              data_type = int(row[0])
↓ open down ↓ 12 lines elided ↑ open up ↑
 567  671          return
 568  672      print "%s%s(param %d)" %(" " * indent, func, param)
 569  673      if func == "too common":
 570  674          return
 571  675      if indent > 20:
 572  676          return
 573  677      printed_funcs.append(func)
 574  678      sources = trace_callers(func, param)
 575  679      for path in sources:
 576  680  
 577      -        if len(path[1]) and path[1][0] == 'p' and path[1][1] == ' ':
 578      -            p = int(path[1][2:])
      681 +        if len(path[1]) and path[1][0] == '$':
      682 +            p = int(re.findall('\d+', path[1][1:])[0])
 579  683              trace_param_helper(path[0], p, indent + 2)
 580  684          elif len(path[0]) and path[0][0] == '%':
 581  685              print "  %s%s" %(" " * indent, path[1])
 582  686          else:
 583  687              print "* %s%s %s" %(" " * (indent - 1), path[0], path[1])
 584  688  
 585  689  def trace_param(func, param):
 586  690      global printed_funcs
 587  691      printed_funcs = []
 588  692      print "tracing %s %d" %(func, param)
↓ open down ↓ 45 lines elided ↑ open up ↑
 634  738      struct_type = sys.argv[2]
 635  739      member = sys.argv[3]
 636  740      print_type_size(struct_type, member)
 637  741  elif sys.argv[1] == "data_info":
 638  742      struct_type = sys.argv[2]
 639  743      member = sys.argv[3]
 640  744      print_data_info(struct_type, member)
 641  745  elif sys.argv[1] == "call_tree":
 642  746      func = sys.argv[2]
 643  747      print_call_tree(func)
      748 +elif sys.argv[1] == "find_tagged":
      749 +    func = sys.argv[2]
      750 +    param = int(sys.argv[3])
      751 +    find_tagged(func, param, 0, [])
      752 +elif sys.argv[1] == "parse_warns_tagged":
      753 +    filename = sys.argv[2]
      754 +    parse_warns_tagged(filename)
 644  755  elif sys.argv[1] == "where":
 645  756      if len(sys.argv) == 3:
 646  757          struct_type = "%"
 647  758          member = sys.argv[2]
 648  759      elif len(sys.argv) == 4:
 649  760          struct_type = sys.argv[2]
 650  761          member = sys.argv[3]
 651  762      function_type_value(struct_type, member)
 652  763  elif sys.argv[1] == "local":
 653  764      filename = sys.argv[2]
↓ open down ↓ 16 lines elided ↑ open up ↑
 670  781      filename = sys.argv[2]
 671  782      print_locals(filename);
 672  783  elif sys.argv[1] == "constraint":
 673  784      if len(sys.argv) == 3:
 674  785          struct_type = "%"
 675  786          member = sys.argv[2]
 676  787      elif len(sys.argv) == 4:
 677  788          struct_type = sys.argv[2]
 678  789          member = sys.argv[3]
 679  790      constraint(struct_type, member)
 680      -elif sys.argv[1] == "test":
 681      -    filename = sys.argv[2]
 682      -    func = sys.argv[3]
 683      -    caller_info_values(filename, func)
 684  791  else:
 685  792      usage()
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX