class ServiceImplAnalyzer: SERVICE_FILE_PATH = CONFIG.local_path("data/services_path.json") FUZZY_GEN_PATH = CONFIG.local_path("data/fuzzy") def __init__(self): self.service_file_mp = {} self.service_ctx_str = {} self.__init_service_file_mp() def __init_service_file_mp(self): if os.path.exists(self.SERVICE_FILE_PATH): utils.write_log("Load service path from cache: %s", self.SERVICE_FILE_PATH) self.service_file_mp = utils.load_json(self.SERVICE_FILE_PATH) return sr_cls = osp.join(CONFIG.DEFAULT_AOSP_PATH, CONFIG.SERVICE_REGISTER_CLS) service_manager = get_service_registers(sr_cls) from core.JniAPIExtractor import SourceFileScanner jni = SourceFileScanner(CONFIG.DEFAULT_AOSP_PATH) java_files = jni.get_files(".java") for jf in java_files: for k, it in service_manager.items(): cls = it["cls"] + ".java" fi = jf.split(os.sep).pop() if fi == cls: self.service_file_mp[it["cls"]] = jf utils.write_json(self.service_file_mp, self.SERVICE_FILE_PATH) def __init_service_ctx_str(self): # get service register string: Context.XXX_SERVICE if self.service_ctx_str: return sr_cls = osp.join(CONFIG.DEFAULT_AOSP_PATH, CONFIG.SERVICE_REGISTER_CLS) service_manager = get_service_registers(sr_cls) for k, v in service_manager.items(): self.service_ctx_str[v["cls"]] = k def gen_api_params(self): utils.check_and_mkdir(self.FUZZY_GEN_PATH) # test_file = self.service_file_mp["TvInputManager"] # print(test_file) # jp = JavaClassParser(test_file, "TvInputManager") # print(jp.get_available_api()) self.__init_service_ctx_str() for cls, path in self.service_file_mp.items(): print(path) jp = JavaClassParser(path, cls) svr = jp.get_available_api() svr.atr_ctx_str = self.service_ctx_str[cls] utils.write_json(svr.dump(), CONFIG.local_path(f"data/fuzzy/{cls}.json"))
def build_callgraph_test(): pt = CONFIG.local_path("data/jni.json") with open(pt, "r") as fp: entry_points = json.load(fp) cg = CppCallgraph() for mtd in entry_points: mp = entry_points[mtd] cpp = mp["cpp"] print(mtd, cpp) cg.load_cpp_file(cpp) # cg.add_entry_point(cpp, mtd) # cg._extract_func_in_files(cpp) break
def gen_api_params(self): utils.check_and_mkdir(self.FUZZY_GEN_PATH) # test_file = self.service_file_mp["TvInputManager"] # print(test_file) # jp = JavaClassParser(test_file, "TvInputManager") # print(jp.get_available_api()) self.__init_service_ctx_str() for cls, path in self.service_file_mp.items(): print(path) jp = JavaClassParser(path, cls) svr = jp.get_available_api() svr.atr_ctx_str = self.service_ctx_str[cls] utils.write_json(svr.dump(), CONFIG.local_path(f"data/fuzzy/{cls}.json"))
# coding: utf-8 # created at 2019/3/27 from config import CONFIG from core.JniAPIExtractor import SourceFileScanner __author__ = "fripSide" import javalang TEST_JAVA_CLS = CONFIG.local_path("data/test/DynamicDispatchExample.java") AIDL_FILES_LIST = CONFIG.local_path("data/aidl.txt") def get_aidl(): sc = SourceFileScanner() files = sc.get_files("aidl") files = list(files) with open(AIDL_FILES_LIST, "w") as fp: for fi in files: print(fi) fp.write(f"{fi}\n") print(len(files)) if __name__ == "__main__": get_aidl()
# created at 2019/2/24 __author__ = "fripSide" import os import sys from config import CONFIG import clang.cindex from clang.cindex import * """ Build callgraph for given h/c https://github.com/bluhm/lockfish """ TEST_FILE = CONFIG.local_path("data/test/test.cpp") TEST_JNI_FILE = CONFIG.aosp_file(r"frameworks\base\core\jni\android_util_Binder.cpp") def find_typerefs(node, typename): """ Find all references to the type named 'typename' """ if node.kind.is_reference(): ref_node = node.get_definition() if ref_node.spelling == typename: print('Found %s [line=%s, col=%s]' % ( typename, node.location.line, node.location.column)) # Recurse for children of this node for c in node.get_children(): find_typerefs(c, typename)
class SourceFileScanner: """ 通过扫每一个文件,根据后缀找出java、c/c++文件,然后找出JNI接口的定义。 TODO: 1. (完成)获取目录下所有目标文件。 2.初步提取Java和C++ JNI接口。 """ FILE_LIST_PATH = CONFIG.local_path("data/file_list.txt") TARGET_EXT = [".java", ".h", ".cc", ".c", ".cpp", ".aidl"] CPP_EXT = [".h", ".cc", ".cpp", ".c"] SCAN_DIRS = ["frameworks"] def __init__(self, aosp_path=CONFIG.DEFAULT_AOSP_PATH): self.file_list = [] self.file_ext_mp = {} self.__scan_files(aosp_path) self.__process_files() def __scan_files(self, base_dir): if osp.exists(self.FILE_LIST_PATH): utils.write_log("Load file list from cache: %s", self.FILE_LIST_PATH) with open(self.FILE_LIST_PATH) as fp: for line in fp: self.file_list.append(line.rstrip()) return for ch in self.SCAN_DIRS: dir_path = osp.join(base_dir, ch) files = self.__walk_dir(dir_path) with open(self.FILE_LIST_PATH, "wb") as fp: for fi in files: fp.write((fi + "\n").encode("utf-8")) self.file_list += files def __walk_dir(self, pt): all_files = [] files = os.listdir(pt) for fp in files: cur_path = osp.join(pt, fp) if osp.isdir(cur_path): all_files += self.__walk_dir(cur_path) else: if os.path.isfile(cur_path): name, ext = osp.splitext(fp) if ext in self.TARGET_EXT: all_files.append(cur_path) # else: # print("is not file", cur_path, os.path.exists(cur_path)) return all_files def __process_files(self): processor_map = { ".java": self.__process_java_file, ".c": self.__process_cpp_file, ".cc": self.__process_cpp_file, ".cpp": self.__process_cpp_file, ".h": self.__process_cpp_file, ".aidl": self.__process_aidl } # for fp in self.file_list: # pass def __process_java_file(self, file): pass def __process_cpp_file(self, file): pass def __process_aidl(self, file): pass def get_files(self, ext): if ext not in self.file_ext_mp: self.file_ext_mp[ext] = filter(lambda f: f.endswith(ext), self.file_list) return self.file_ext_mp[ext] def get_cpp_files(self): for ext in self.CPP_EXT: for item in self.get_files(ext): yield item def statistics(self): num = len(self.file_list) utils.write_log("Total Files: %d", num) java_num = len(list(filter(lambda f: f.endswith(".java"), self.file_list))) cpp_num = len(list(filter(lambda f: f.endswith(".c") or f.endswith("h") or f.endswith("cc") or f.endswith("cpp"), self.file_list))) aidl_num = len(list(filter(lambda f: f.endswith(".aidl"), self.file_list))) utils.write_log("java files: %d", java_num) utils.write_log("cpp files: %d", cpp_num) utils.write_log("aidl files: %d", aidl_num)
def process_cpp_files(self, files): for fi in files: self.__parser_jni_cpp_register_func(fi) print(len(self.jni_bridge_map), self.jni_bridge_map) utils.write_json(self.jni_bridge_map, CONFIG.local_path("data/jni.json"))