def get_symbol_address(symbol): """ for a given Maple symbol, returns its address in hex string via gdb p command, or None if not found """ cmd = 'p ' + symbol try: result = m_util.gdb_exec_to_str(cmd) except: return None match_pattern = '<' + symbol + '>' if result.find(match_pattern) is -1: return None else: x = result.split() pattern_index = x.index(match_pattern) return x[pattern_index - 1]
def __init__(self): gdb.Command.__init__(self, "msrcpath", gdb.COMMAND_FILES, gdb.COMPLETE_NONE) global maple_source_path_list # add current working directory at the top line = m_util.gdb_exec_to_str('pwd') if line: s = line.split() line = s[2][:-1] if len(s) is 3 else None if line: maple_source_path_list.append( os.path.expandvars(os.path.expanduser(line))) ''' if len(maple_source_path_list) == 1: gdb_print("Maple application source code search path only has one path as following:") gdb_print(" ", maple_source_path_list[0]) gdb_print("Please add more search paths using msrcpath -add <path> command") ''' m_util.gdb_exec('alias msp = msrcpath')
def get_symbol_name_by_current_func_args(): """ get the 'func' symbol name and its address in currect frame stack """ cmd = 'p func' try: result = m_util.gdb_exec_to_str(cmd) except: return None, None if m_debug.Debug: m_debug.dbg_print("result=", result) if 'header = ' in result and '_mirbin_info>' in result: s = result.split('header = ') address = s[1].split()[0] name = s[1].split()[1].split('>')[0][1:] caller = result.split('caller = ')[1].split(',')[0] if m_debug.Debug: m_debug.dbg_print("address=", address, "name=", name, "caller=", caller) return address, name else: return None, None
def print_array_class_values(self, addr): """ display 10 items if length is less than 10, or first 7 and last three if length is over 11 """ item_num = self.get_array_length(addr) if item_num > 10: item_list = [ 0, 1, 2, 3, 4, 5, 6, item_num - 3, item_num - 2, item_num - 1 ] else: item_list = [i for i in range(item_num)] steps = 0 show_snip = True for i in item_list: obj_addr = addr + 4 + 8 * i # class reference is a pointer, 8 bytes cmd = 'x/1gx ' + hex(obj_addr) if m_debug.Debug: m_debug.dbg_print("cmd=", cmd) try: buffer = m_util.gdb_exec_to_str(cmd) except: buf = ' [{}] {}'.format(i, 'no-data') gdb_print(buf) steps += 1 continue steps += 1 v = buffer.split(':')[1].strip() v = hex(int(v, 16)) #remove leading 0s. e.g. 0x000123 to 0x123 buf = ' [{}] {}'.format(i, v) gdb_print(buf) if item_num > 10 and steps > 6 and show_snip == True: gdb_print(" ...") show_snip = False return
def stop(self): """ provide stop control logic here. note, user will add one or more Maple symbol into mbp_table, only those qualified ones in mbp_table will be admitted to make breakpoint stop return True: to stop False: to bypass """ # if the Maple breakpoint was created before .so is loaded, when the breakpoint is hit, # plt will be not disable. So we disable it buf = m_util.gdb_exec_to_str("info b") if not is_maple_invoke_bp_plt_disabled(buf): disable_maple_invoke_bp_plt(buf) return False # if the Maple breakpoint was created before .so is loaded, bp_addr, bp_info (location) # if not available. But once hit, address and loc start to be available. if not self.bp_info or not self.bp_addr: self.bp_addr, self.bp_info = get_maple_invoke_bp_stop_addr(buf) # determine whether need to look up pending symbol's address. If the number of loaded libraries # is not eaual to the one saved, then libs might have been loaded or unloaded, so we try to update if len(gdb.objfiles()) != self.load_objfiles: self.load_objfiles = len(gdb.objfiles()) pending_addr_symbol_list = self.get_pending_addr_symbol_list() if len(pending_addr_symbol_list) > 0: for sym in pending_addr_symbol_list: self.update_pending_addr_symbol(sym) # NOTE!!! here we are getting the current stack's mir_header's address args_addr = m_symbol.get_symbol_addr_by_current_frame_args() if not args_addr or not args_addr in self.mbp_addr_sym_table: return False # mir_header address matches one breakpoint address list table_args_addr = self.mbp_addr_sym_table[args_addr] args_symbol = table_args_addr['mir_symbol'] match_pattern = table_args_addr['symbol'] # it is possible that match pattern is in mbp_addr_sym_table for address check, # but the self.mbp_addr_sym_table[args_addr]['symbol'] could have been cleared # in self.mbp_table by user's mb -clear command if not match_pattern in self.mbp_table: return False # Maple symbol for the breakpoint is disabled table_match_pattern = self.mbp_table[match_pattern] if table_match_pattern['disabled'] is True: return False if table_match_pattern['ignore_count'] > 0: table_match_pattern['ignore_count'] -= 1 return False table_match_pattern['hit_count'] += 1 # update the Maple gdb runtime metadata store. m_datastore.mgdb_rdata.update_gdb_runtime_data() # update the Maple frame change count m_datastore.mgdb_rdata.update_frame_change_counter() return True
def get_value_from_memory(self, addr, offset, length): """ params: addr: int offset: int length: int returns: value in string """ if m_debug.Debug: m_debug.dbg_print("addr=", addr, " offset=", offset, " length=", length) hex_string = None doulbe_string = None long_string = None int_string = None float_string = None word_string = None short_string = None byte_string = None ret = None if length == 8: # 8 byte, could be a long, a 8 byte address ptr, or a double cmd = 'x/1gx ' + hex(addr + offset) # cmd to get 8 byte address try: hex_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None hex_string = hex_string.split(':')[1] hex_string = hex(int(hex_string, 16)) cmd = 'x/1gf ' + hex( addr + offset) # cmd to get 8 byte double value try: double_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None double_string = double_string.split()[1] cmd = 'x/1dg ' + hex(addr + offset) # cmd to get 8 byte long value try: long_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None long_string = long_string.split()[1] ret = 'hex:' + hex_string + ',long:' + long_string + ',double:' + double_string if m_debug.Debug: m_debug.dbg_print("ret=", ret) return ret elif length == 4: # 4 byte,could be int, float, hex cmd = 'x/1xw ' + hex( addr + offset) # cmd to get 4 byte hex address try: hex_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None hex_string = hex_string.split()[1] cmd = 'x/1dw ' + hex(addr + offset) # cmd to get 4 byte int try: int_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None int_string = int_string.split()[1] cmd = 'x/1fw ' + hex(addr + offset) # cmd to get 4 byte float try: float_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None float_string = float_string.split()[1] ret = 'hex:' + hex_string + ',int:' + int_string + ',float:' + float_string if m_debug.Debug: m_debug.dbg_print("ret=", ret) return ret elif length == 2: # 2 byte, could be short, hex, 2 character cmd = 'x/1xh ' + hex( addr + offset) # cmd to get 2 byte hex address try: hex_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None hex_string = hex_string.split()[1] cmd = 'x/1dh ' + hex(addr + offset) # cmd to get 2 byte short int try: short_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None short_string = short_string.split()[1] cmd = 'x/2b ' + hex(addr + offset) # cmd to get 2 byte characters try: byte_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None byte_string = byte_string.split(':')[1].strip() ret = 'hex:' + hex_string + ',short:' + short_string + ',byte:' + byte_string if m_debug.Debug: m_debug.dbg_print("ret=", ret) return ret elif length == 1: # 1 byte. could be hex, c cmd = 'x/1xb ' + hex(addr + offset) # cmd to get 1 byte hex try: hex_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None hex_string = hex_string.split()[1] cmd = 'x/1cb ' + hex(addr + offset) # cmd to get 1 byte characters try: byte_string = m_util.gdb_exec_to_str(cmd) except: if m_debug.Debug: m_debug.dbg_print() return None byte_string = byte_string.split(':')[1].strip() ret = 'hex:' + hex_string + ',byte:' + byte_string if m_debug.Debug: m_debug.dbg_print("ret=", ret) return ret else: if m_debug.Debug: m_debug.dbg_print() return None
def get_maple_caller_argument_value(arg_idx, arg_num, mtype): """ for a given Maple caller's arg_idx, arg_num and type, get its value from caller's operand_stack params: arg_idx: the argument index in a Maple method. e.g. method1(int a, long b, string c), for argument "a", its arg index is 0, c is 2. arg_num: number of argument a method has mtype : a string. definition in m_asm.py for "a", it could be 'i32', 'i64' returns: the argument value in string. """ if m_debug.Debug: m_debug.dbg_print("pass in arg_idx=", arg_idx, "arg_num=", arg_num, "mtype=", mtype) # get the caller.sp first try: buffer = m_util.gdb_exec_to_str('p caller.sp') except: return None if 'No symbol "caller" in current context.' in buffer: return None if ' = ' in buffer: sp = int(buffer.split(' = ')[-1]) else: return None if arg_idx > sp: #sp must be >= num of args return None if m_debug.Debug: m_debug.dbg_print("sp=", sp) # get the caller.operand_stack length try: buffer = m_util.gdb_exec_to_str('p caller.operand_stack.size()') except: return None if buffer[0] != '$': return None if ' = ' in buffer: try: length = int(buffer.split(' = ')[1]) except: return None else: return None if m_debug.Debug: m_debug.dbg_print("length=", length) if length < arg_idx: return None # get the caller.operand_stack[arg_idx] idx = sp - arg_num + arg_idx + 1 try: buffer = m_util.gdb_exec_to_str('p caller.operand_stack[' + str(idx) + ']') except: return None vline = buffer.split('x = ')[1][1:].split('}')[0] v = vline.split(mtype+' = ')[1].split(',')[0] if mtype in vline else None return v