1#!/usr/bin/env python 2# coding:utf-8 3# Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import sys,string,re,os 17from ctypes import * 18 19DEFINE_SUCCESS=0 20DEFINE_FAIL=1 21 22class Sysmbol: 23 """符号表中的符号 24 """ 25 def __init__(self): 26 self.addr=None #符号地址 27 self.key_name = None #符号名 28 self.class_type=None #符号类型 'a','t','b','d'... 29 self.type = None #符号类型 'FUNC','OBJECT','NOTYPE' ... 30 self.size = None #符号size,不是都有 31 self.section=None #符号落在哪个段 32 self.guess_size=None #计算出的符号大小(不准),TBD 33 34class _BasicCtrl: 35 def __init__(self): 36 self.temp_memory = bytearray(4096) # 临时空间,用于计算 37 38def uapi_str_to_int(str,num): 39 """字符串转数字 40 Args 41 str: 字符串 42 num: 进制 43 return 44 int:数值 45 """ 46 if num!=None: 47 return int(str,num) 48 match1=re.match(r'\s*0x',str) 49 match2=re.match(r'\s*0X',str) 50 if match1 or match2: 51 return int(str,16) 52 else: 53 return int(str,10) 54 55 56def uapi_is_hex_word(word): 57 """判断是否是16进制字符串 58 Args 59 str: 字符串 60 return 61 True:是 62 False:不是 63 """ 64 if word is None: 65 return False 66 for char in word: 67 if char not in string.hexdigits: 68 return False 69 return True 70 71_g_ctype_x16_class=[c_byte,c_ubyte,c_short,c_ushort,c_int,c_uint,c_long,c_ulong,c_longlong,c_ulonglong,c_size_t,c_ssize_t] 72_g_ctype_float_class=[c_float,c_double,c_longdouble] 73_g_ctype_char=[c_char,c_bool] 74 75def _print_ctypes_obj(var_name,obj,t,fd): 76 if type(obj)==int: 77 print('%s=0x%x'%(var_name,obj),file=fd) 78 return 79 if type(obj)==bytes: 80 print('%s'%(var_name),obj,file=fd) 81 return 82 if type(obj)==bool: 83 print('%s'%(var_name),obj,file=fd) 84 return 85 if type(obj)==float: 86 print('%s=%f'%(var_name,obj),file=fd) 87 return 88 89 if type(obj) in _g_ctype_x16_class: 90 print('%s=0x%x'%(var_name,obj.value),file=fd) 91 return 92 if type(obj) in _g_ctype_float_class: 93 print('%s=%f'%(var_name,obj.value),file=fd) 94 return 95 if type(obj) in _g_ctype_char: 96 print('%s'%(var_name),obj.value,file=fd) 97 return 98 99 if hasattr(obj, '_length_'): 100 if hasattr(obj,'value'): 101 print('%s='%(var_name),obj.value,file=fd) 102 else: 103 i=0 104 for m in obj: 105 prefix="%s[%d]"%(var_name,i) 106 _print_ctypes_obj(prefix,m,getattr(obj,'_type_'),fd) 107 i=i+1 108 return 109 if hasattr(obj, '_fields_'): 110 for field in obj._fields_: 111 name = field[0] 112 val = getattr(obj, field[0]) 113 _print_ctypes_obj(var_name+'.'+name,val,field[1],fd) 114 return 115 116 assert(False) 117 118def uapi_print_ctypes_obj(var_name,obj,fd=sys.stdout): 119 """打印ctypes object 120 Args 121 var_name: 打印名称 122 obj: 被打印的obj 123 fd: 输出目标 124 return 125 """ 126 print(var_name+'{',file=fd) 127 _print_ctypes_obj(' ',obj,type(obj),fd) 128 print('}',file=fd) 129 130def ctype_member_offset(c_member,c_class): 131 """计算ctype类型的成员相对类的偏移 132 Args 133 c_member: 成员名字符串 134 c_class: ctype类 135 fd: 输出目标 136 return 137 int:偏移 138 """ 139 list=c_member.split('.') 140 obj=c_class.from_buffer(_g_basic_ctrl.temp_memory) 141 temp_obj=obj 142 for member in list: 143 x=getattr(temp_obj,member) 144 temp_obj=x 145 return addressof(x)-addressof(obj) 146 147class _ParseBinItem: 148 def __init__(self): 149 file_name=None 150 start_addr=None 151 size = None 152 data=None 153 154class _ParseMemoryManager: 155 def __init__(self): 156 self.momory_list=[] 157 158 def register_memory(self,file_name,start_addr,size): 159 with open(file_name,'rb') as fp: 160 item = _ParseBinItem() 161 data = fp.read() 162 item.file_name=file_name 163 item.start_addr = start_addr 164 item.data=bytearray(data) 165 item.size=size 166 self.momory_list.append(item) 167 def register_bin(bin,start_addr,size): 168 item = _ParseBinItem() 169 item.file_name=None 170 item.start_addr = start_addr 171 item.data=bytearray(bin) 172 item.size=size 173 self.momory_list.append(item) 174 175 def memory_get(self,addr,size): 176 match_item=None 177 for item in self.momory_list: 178 if addr >= item.start_addr and addr+size < item.start_addr+item.size: 179 match_item=item 180 break 181 if match_item==None: 182 return None 183 addr=addr-match_item.start_addr 184 return match_item.data[addr:addr+size] 185 186class _HookFunctions: 187 def __init__(self): 188 self.get_symbol_info = None 189 self.get_u32_symbol_val = None 190 self.get_symbol_addr = None 191 self.addr_2_function_name = None 192 self.addr_in_2_function_name = None 193 194def parse_memory_get(addr,size): 195 """获取一段空间 196 Args 197 addr: 起始地址 198 size:大小 199 return 200 binary:成功返回一段空间 201 None:这段空间不存在 202 """ 203 return _g_parse_memory_manager.memory_get(addr,size) 204 205def parse_memory_2_class(addr,class_type,class_size): 206 """将一段空间转换成一个ctype obj 207 Args 208 addr: 起始地址 209 class_type: class 类型 210 class_size: class size 211 return 212 obj:返回一个ctype obj 213 None:这段空间不存在 214 """ 215 bin = parse_memory_get(addr,class_size) 216 if bin==None: 217 return None 218 return class_type.from_buffer(bin) 219 220def parse_memory_2_string(addr,max_len): 221 obj=parse_memory_2_class(addr,(c_char*max_len),sizeof((c_char*max_len))) 222 if obj==None: 223 return None 224 else: 225 return obj.value.decode('utf-8') 226 227def parse_memory_register(file_name,start_addr,size): 228 """注册一段内存 229 Args 230 file_name: 内存来自文件,文件全路径 231 start_addr: 内存起始地址 232 size: 内存大小 233 return 234 """ 235 _g_parse_memory_manager.register_memory(file_name,start_addr,size) 236 237def parse_memory_register_bin(bin,start_addr,size): 238 """注册一段内存 239 Args 240 bin: 内存一段binary 241 start_addr: 内存起始地址 242 size: 内存大小 243 return 244 """ 245 _g_parse_memory_manager.register_bin(bin,start_addr,size) 246 247def parse_get_symbol_info(name): 248 """获取symbolinfo 249 Args 250 name: 符号名 251 return 252 obj:成功,Sysmbol类型的obj 253 None:获取失败 254 """ 255 if _g_hook_functions.get_symbol_info==None: 256 assert(False) 257 return None 258 return _g_hook_functions.get_symbol_info(name) 259 260def parse_get_u32_symbol_val(name): 261 """获取值 262 Args 263 name: 符号名 264 return 265 int:成功,获取到的值 266 None:获取失败 267 """ 268 if _g_hook_functions.get_u32_symbol_val==None: 269 assert(False) 270 return None 271 return _g_hook_functions.get_u32_symbol_val(name) 272 273def parse_get_symbol_addr(name): 274 """获取符号地址 275 Args 276 name: 符号名 277 return 278 int:成功,获取到的值 279 None:获取失败 280 """ 281 if _g_hook_functions.get_symbol_addr==None: 282 assert(False) 283 return None 284 return _g_hook_functions.get_symbol_addr(name) 285 286def parse_addr_2_function_name(addr): 287 if _g_hook_functions.addr_2_function_name==None: 288 assert(False) 289 return None 290 return _g_hook_functions.addr_2_function_name(addr) 291 292def parse_addr_in_2_function_name(addr): 293 if _g_hook_functions.addr_in_2_function_name==None: 294 assert(False) 295 return None 296 return _g_hook_functions.addr_in_2_function_name(addr) 297 298def uapi_register_function(name,function): 299 if name=="get_symbol_info": 300 _g_hook_functions.get_symbol_info = function 301 elif name=="get_u32_symbol_val": 302 _g_hook_functions.get_u32_symbol_val = function 303 elif name=="get_symbol_addr": 304 _g_hook_functions.get_symbol_addr=function 305 elif name=="addr_2_function_name": 306 _g_hook_functions.addr_2_function_name = function 307 elif name=="addr_in_2_function_name": 308 _g_hook_functions.addr_in_2_function_name = function 309 else: 310 assert(False) 311 312_g_parse_memory_manager = _ParseMemoryManager() 313_g_basic_ctrl=_BasicCtrl() 314_g_hook_functions =_HookFunctions()