1#!/usr/bin/env python 2# coding:utf-8 3 4# 5# Copyright (C) 2022 Huawei Technologies Co., Ltd. 6# Licensed under the Mulan PSL v2. 7# You can use this software according to the terms and conditions of the Mulan 8# PSL v2. 9# You may obtain a copy of Mulan PSL v2 at: 10# http://license.coscl.org.cn/MulanPSL2 11# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 12# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 13# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14# See the Mulan PSL v2 for more details. 15# 16 17 18''' tools for generate whitelist and check TA undefined symbols are in whitelist ''' 19 20import subprocess 21import os 22import sys 23import CppHeaderParser 24import shutil 25import logging 26import stat 27 28exception_files = [] 29script_dir = os.path.dirname(os.path.realpath(__file__)) 30whitelist_path = "temp/whitelist.txt" 31headers_check_path = os.path.join(script_dir, 'headers_check.txt') 32 33 34class SymbolInfo: 35 ''' symbol table param ''' 36 def __init__(self, value, flag, part, size, name): 37 self.value = value 38 self.flag = flag 39 self.part = part 40 self.size = size 41 self.name = name 42 43 def __str__(self): 44 return "symbol information:" + " Value:" + self.value + " Flag:" + self.flag + \ 45 " Part:" + self.part + " Size:" + self.size + " Name:" + self.name 46 47 def __len__(self): 48 return len(self.__dict__) 49 50 51def save_elf_symbol(elf_path): 52 ''' get symbol table and save ''' 53 if not os.path.exists(elf_path): 54 logging.error("elf path not exist: " + elf_path) 55 return [] 56 57 sym_info = SymbolInfo(0, 0, 0, 0, 0) 58 cmd = "objdump -T %s" % elf_path 59 process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 60 output, error = process.communicate() 61 output = (output.decode('utf-8')).split('\n')[4:] 62 63 symbol_table = [] 64 for (i, _) in enumerate(output): 65 info = output[i].split() 66 if len(info) < len(sym_info): 67 continue 68 sym_info = SymbolInfo(info[0], info[1], info[2], info[3], info[len(info) - 1]) 69 if sym_info.name.startswith("__"): 70 continue 71 symbol_table.append(sym_info) 72 73 return symbol_table 74 75 76def find_undefine_symbol(symbol_table): 77 ''' get undefined symbols ''' 78 return [info.name for info in symbol_table if info.part == "*UND*"] 79 80 81def clean_temp_file(): 82 ''' del temp file ''' 83 if os.path.exists("temp"): 84 shutil.rmtree("temp") 85 86 87def get_whitelist(whitelist_path_name): 88 ''' get whitelist info from file ''' 89 if not os.path.exists(whitelist_path_name): 90 logging.error("whitelist path not exist: %s", whitelist_path_name) 91 return [] 92 93 with open(whitelist_path_name, 'r') as f: 94 return [line.strip('\n') for line in f.readlines()] 95 96 97def check_symbol_in_whitelist(whitelist, function_table): 98 ''' check if symbol is in whitelist and find diff ''' 99 if whitelist == []: 100 return False 101 102 if set(function_table).issubset(set(whitelist)): 103 logging.critical("success to check TA symbols!") 104 return True 105 else: 106 logging.error("Fail! These functions are not in whitelist:") 107 logging.error(set(function_table).difference(set(whitelist))) 108 return False 109 110 111def get_all_headers_file_path(headers_path): 112 ''' get all headers file ''' 113 result = [] 114 for one_path in headers_path: 115 real_path = os.path.realpath(one_path) 116 if not os.path.exists(real_path): 117 logging.error("path not exist: %s", real_path) 118 continue 119 120 for maindir, _, filename_list in os.walk(real_path): 121 for filename in filename_list: 122 if '.h' in filename: 123 path = os.path.join(maindir, filename) 124 result.append(path) 125 126 return result 127 128 129def gen_whitelist_from_headers(headers_path): 130 ''' generate whitelist by header files ''' 131 if not os.path.exists("temp"): 132 os.mkdir("temp") 133 134 if not os.path.exists(whitelist_path): 135 flag = os.O_RDWR | os.O_TRUNC | os.O_CREAT 136 mode = stat.S_IWUSR | stat.S_IRUSR 137 else: 138 flag = os.O_RDWR 139 mode = 0o600 140 whitelist_path_fd = os.open(whitelist_path, flag, mode) 141 with os.fdopen(whitelist_path_fd, 'a+') as f: 142 paths = get_all_headers_file_path(headers_path) 143 if paths == []: 144 logging.critical("Not found any headers files!") 145 return 146 for file_name in paths: 147 try: 148 header = CppHeaderParser.CppHeader(file_name) 149 for func in header.functions: 150 f.write('%s\n' % func['name']) 151 except Exception as e: 152 exception_files.append(file_name) 153 logging.critical("%s has exception, skip it.", file_name) 154 155 156def gen_temp_headers_without_note(exception_file): 157 ''' del chinese words note in file ''' 158 file_name = "temp/" + exception_file.split("/")[-1] 159 file_name_fd = os.open(file_name, os.O_RDWR | os.O_TRUNC | os.O_CREAT, \ 160 stat.S_IWUSR | stat.S_IRUSR) 161 with os.fdopen(file_name_fd, "w+") as f_f: 162 with open(exception_file, 'r', encoding='GBK') as e_f: 163 for line in e_f.readlines(): 164 if line.strip().startswith("*") or line.strip().startswith("/*") or line.strip().startswith("*/"): 165 continue 166 f_f.write(line) 167 168 return file_name 169 170 171def proc_exception_files(exception_files_list): 172 ''' proccess all exceptional file ''' 173 [logging.critical("exceptional file " + file.split("/")[-1] + " processing") 174 for file in list(map(gen_temp_headers_without_note, exception_files_list))] 175 176 177def get_headers_path(headers_check_path_name): 178 ''' read headers_check.txt and get headers path ''' 179 if not os.path.exists(headers_check_path_name): 180 logging.error("Not found headers_check.txt.") 181 return [] 182 183 with open(os.path.realpath(headers_check_path_name), 'r') as f: 184 return [script_dir + '/' + line.strip('\n') for line in f.readlines()] 185 186 187def main(): 188 ''' main ''' 189 argv_data = sys.argv 190 if len(argv_data) != 2: 191 logging.error("argv need one param") 192 exit(1) 193 194 elf_path = argv_data[1] 195 temp_path = ["temp"] 196 197 # Get the header file path configured in the file and generate a whitelist 198 headers_path = get_headers_path(headers_check_path) 199 gen_whitelist_from_headers(headers_path) 200 201 # Handle header files for exceptions, add whitelist 202 proc_exception_files(exception_files) 203 gen_whitelist_from_headers(temp_path) 204 205 # Get the symbol table of elf 206 symbol_table = save_elf_symbol(elf_path) 207 if symbol_table == []: 208 clean_temp_file() 209 exit(1) 210 211 # Get undefined function in symbol table 212 function_table = find_undefine_symbol(symbol_table) 213 214 # Check whether the functions in the symbol table correspond to the whitelist 215 if check_symbol_in_whitelist(get_whitelist(whitelist_path), function_table) == False: 216 clean_temp_file() 217 exit(1) 218 219 220if __name__ == '__main__': 221 main() 222 clean_temp_file() 223 224