• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import sys, os, subprocess, ConfigParser
2from optparse import OptionParser
3
4class2jar = dict()
5jars_to_process = set()
6
7opt_parser = OptionParser()
8opt_parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="set verbosity")
9opt_parser.add_option("-c", "--config", dest="config", default=os.path.dirname(sys.argv[0])+"/android-jar.conf", help="configuration file path")
10(options, args) = opt_parser.parse_args()
11if not os.path.isfile(options.config):
12  sys.exit('Error! No configuration file at: '+options.config)
13config_parser = ConfigParser.SafeConfigParser()
14config_parser.read(options.config)
15ajars_dir = config_parser.get('android-paths', 'aosp-out-dir')
16stubs_jar = config_parser.get('android-paths', 'android-stubs-jar')
17jarinfer = config_parser.get('jar-infer-paths', 'jar-infer-path')
18wrk_dir = config_parser.get('android-model', 'wrk-dir')
19astubx_file = config_parser.get('android-model', 'astubx-path')
20
21### Finding android libraries ###
22print "> Finding android libraries..."
23# Since SDK 31, the directory structure mixes classes.jar and classes-header.jar files, we use
24# only the former, as classes-header.jar files are missing methods' bytecode.
25cmd = "find " + ajars_dir + " -name \"*.jar\" | grep -v classes-header.jar"
26ajars = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).stdout.read().splitlines()
27for ajar in ajars:
28  cmd = "jar tvf " + ajar + " | grep \"\.class$\" | awk '{print $8}'"
29  ajar_classes = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).stdout.read().splitlines()
30  for ajar_class in ajar_classes:
31    if ajar_class in class2jar:
32      if options.verbose:
33        print "[Warn] Same class in multiple jars : " + ajar_class + " in " + class2jar[ajar_class] + " , " + ajar
34    else:
35      class2jar[ajar_class] = ajar
36cmd = "jar tvf " + stubs_jar + " | grep \"\.class$\" | awk '{print $8}'"
37ajar_classes = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).stdout.read().splitlines()
38found = 0
39for ajar_class in ajar_classes:
40  if ajar_class in class2jar:
41    found += 1
42    jars_to_process.add(class2jar[ajar_class])
43  else:
44    if options.verbose:
45      print "[Warn] Class not found in any jar : " + ajar_class
46print ",".join(list(jars_to_process))
47print "Found " + str(found) + " / " + str(len(ajar_classes)) + " in " + str(len(jars_to_process)) + " jars"
48
49### Running jarinfer ###
50print "> Running jarinfer on android jars..."
51cmd = "java -jar " + jarinfer + " -i " + ",".join(list(jars_to_process)) + " -o " + wrk_dir + "/" + astubx_file
52if options.verbose:
53  cmd += " -dv"
54print cmd
55returncode = subprocess.call(cmd, shell=True)
56sys.exit(returncode)
57