• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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