def mlist_source_file_func(self, filename=None, line=0, offset=0): """ params: line = 0 and offset = 0 allowed line = 0 and offset != 0 allowed line != 0 and offset = 0 allowed line != 0 and offset != 0 NOT allowed """ if line != 0 and offset != 0: return frame_change_count = m_datastore.mlldb_rdata.read_frame_change_counter( ) # stack selected frame changed by other cmds or breakpoints if self.frame_change_count < frame_change_count: frame = m_frame.get_selected_frame() if not frame: return ds = m_datastore.get_stack_frame_data(frame) if not ds: return self.frame_data = ds self.frame_change_count = frame_change_count if filename: self.frame_data['frame_func_src_info'][ 'short_src_file_name'] = filename if line != 0: self.frame_data['frame_func_src_info'][ 'short_src_file_line'] = line if offset != 0: new_line = self.prev_src_file_line + offset self.frame_data['frame_func_src_info'][ 'short_src_file_line'] = new_line if new_line > 1 else 1 file_full_path = None for source_path in maple_source_path_list: file_full_path = find_one_file( self.frame_data['frame_func_src_info']['short_src_file_name'], source_path) if not file_full_path: continue else: break if not file_full_path: if self.frame_data['frame_func_src_info']['short_src_file_name']: mdb_print("Warning: Source code file " + self.frame_data['frame_func_src_info'] ['short_src_file_name'] + " not found in any path") else: mdb_print( "Warning: Source code file not found. try 'mlist -asm' instead" ) return self.display_src_lines( file_full_path, self.frame_data['frame_func_src_info']['short_src_file_line'])
def display_src_file_lines(filename, line_num): exist = m_datastore.mlldb_rdata.in_src_lines(filename) if exist: total = m_datastore.mlldb_rdata.get_src_lines(filename) else: with open(filename) as fp: total = len(fp.readlines()) m_datastore.mlldb_rdata.add_src_lines(filename, total) try: count = int(m_set.msettings["linecount"]) if count < 5: count = default_src_display_line_count if count != 0 else total << 1 except: count = default_src_display_line_count line_num = line_num if line_num < total else total half = (count - 1) >> 1 s_line = line_num - half if line_num > half + 1 else 1 half = count - half - 1 e_line = line_num + half if line_num + half <= total else total mdb_print("src file: %s%s%s line: %d" % (MColors.BT_SRC, filename, MColors.ENDC, line_num)) if m_util.Highlighted: buf =m_util.shell_cmd('highlight -O xterm256 --force -s %s %s | sed -n %d,%dp |' ' nl -ba -s" " -w8 -v%d | sed "s/^ \\( *%d \\)/=>\\1/"' \ % (m_util.HighlightStyle, filename, s_line, e_line, s_line, line_num)) else: buf = m_util.shell_cmd('sed -n %d,%dp %s | nl -ba -s" " -w8 -v%d | sed "s/^ \\( *%d \\)/=>\\1/"' \ % (s_line, e_line, filename, s_line, line_num)) m_util.mdb_write(buf) new_line_num = line_num + count if line_num + count <= total else total return new_line_num
def create_asm_mirbin_label_cache(asm_path, popen_only=False, proc_saved={}): """ Create a dictionary for a given asm file When it is called the first time with a given asm file, it starts a subprocess to handle the asm file and returns None; When called subsequently using the same asm file, it will wait for the first subprocess to finish and return a dictionary created from its output. """ if m_debug.Debug: m_util.mdb_print("ASM Begin gen:" + asm_path) if not asm_path: for p in proc_saved.values(): m_util.proc_communicate(p) return None #TODO: This code prints to stdout on lldb which is a mess if m_debug.Debug: m_debug.dbg_print("asm_path=", asm_path) #if not path.exists(asm_path): if asm_path not in proc_saved: cmd="bash -c \"paste <(grep -bn _mirbin_info: '" + asm_path \ + "') <(grep -Fb .cfi_endproc '" + asm_path \ + "')\" | awk -F: -v a='\"' -v b='\":(' -v c=',' -v d='),' " \ "'BEGIN { print \"import pickle\\nimport sys\\nd={\" } " \ "{ print a$3b$1c$2c$4d } END { print \"}\\no=pickle.dumps(d,3)\\n" \ "sys.stdout.write(o.decode(\\\"latin1\\\"))\" }' | python3" proc_saved[asm_path] = m_util.proc_popen(cmd) if popen_only: return None d = m_util.proc_communicate(proc_saved.pop(asm_path)) if m_debug.Debug: m_util.mdb_print("ASM End/Load gen:" + str(d)) return pickle.loads(d)
def get_next_older_frame(frame): """ get a gdb.Frame object representing the next older frame on stack """ #if not frame or not frame.is_valid(): if not frame or not frame.IsValid(): mdb_print("Trouble accessing older LLDB Frame") return None else: return frame.get_parent_frame()
def add_path(self, path): # we add path into the top of the list global maple_source_path_list if path in maple_source_path_list: maple_source_path_list.remove(path) if not os.path.exists(os.path.expandvars(os.path.expanduser(path))): buffer = "%s specified but not found, please verify: " % (path) mdb_print(buffer) else: maple_source_path_list = [ os.path.expandvars(os.path.expanduser(path)) ] + maple_source_path_list return
def get_initialized_maple_func_addrs(): """ get an initialized Maple frame func header address returns: func header address in string format of xxxxxx:yyyyyy: format where xxxxxx means (header - lib_base_addr), yyyyyy means (pc - header - header_size) """ #print("Here the mess starts") header = get_initialized_maple_func_attr('func.header') pc = get_initialized_maple_func_attr('func.pc') if m_debug.Debug: m_debug.dbg_print("header=", header, "pc=", pc) if not header or not pc: return None try: header = int(header, 16) except: return None try: pc = int(pc, 16) except: return None lib_addr = get_lib_addr_from_proc_mapping(header) if m_debug.Debug: m_debug.dbg_print("header=", header, "lib_addr=",lib_addr, "pc=", pc) if not lib_addr: return None try: buf = m_util.mdb_exec_to_str('x/1xw ' + str(header)) except: return None if not buf: return None header_size = int(buf.split(':')[1],16) if (header < lib_addr): mdb_print ("Warning: The header address is lower than lib_addr.") return None if (pc < header): mdb_print ("Warning: The pc address is lower than the header address.") return None xxxxxx = header - lib_addr yyyyyy = pc - header - header_size return hex(xxxxxx) + ":" + "{:04x}".format(yyyyyy)+":"
def get_selected_frame(): """ get a gdb.Frame object representing the selected frame in current stack if it is valid """ try: #frame = lldb.frame() frame = lldb.debugger.GetTargetAtIndex( 0).GetProcess().GetSelectedThread().GetSelectedFrame() process = lldb.debugger.GetTargetAtIndex(0).GetProcess() for t in process: #print("Thread= ", t.GetThreadID(), t.GetIndexID(), t.GetName(), t.GetStopReason()) if (t.GetStopReason() == 3): # Get the stopped Thread frame = t.GetSelectedFrame() #frame = lldb.debugger.GetTargetAtIndex(0).GetProcess().GetThreadByID(0).GetSelectedFrame() except: mdb_print("-" * 60) mdb_print("Trouble accessing selected LLDB Frame:") traceback.print_stack(file=sys.stdout) mdb_print("-" * 60) traceback.print_exc(file=sys.stdout) mdb_print("-" * 60) return None #if not frame or not frame.is_valid(): if not frame or not frame.IsValid(): return None return frame
def print_mdb_frame(frame, index): """ print one mdb native backtrace frame """ hpc = hex(frame.GetPC()).strip() hpc = MColors.italic(MColors.yellow(hpc).strip()).strip() funct = str(frame.GetFunctionName()).strip() module = str(frame.GetModule()).strip().replace("(x86_64) ", "") buf = str(frame.GetLineEntry()) if (buf == ':4294967295'): #if the file is not available buf = "" funct = (MColors.lblue("in") + funct + MColors.lblue(" from")).strip() else: module = "" funct = (MColors.lblue("in") + funct + MColors.lgreen(" at")).strip() #print("#"+str(index),hex(frame.GetPC()), "in", frame.GetFunctionName(), "from", frame.GetModule(),buf) mdb_print(('#%2i%s %s%s %s' % (index, hpc, funct, module, buf)))
def do_list(self, ml_file, ml_path, ml_format, ml_line): line_offset = 1 src_file_name = ml_file src_line_num = ml_line mdb_print("Listing") MColors.init_maple_colors() mlist_mode = ml_format if mlist_mode == MLIST_MODE_ASM: self.mlist_asm_file_func(line_offset) elif mlist_mode == MLIST_MODE_SRC: self.mlist_source_file_func(filename=src_file_name, line=src_line_num, offset=line_offset) else: self.mlist_mir_file_func(line_offset)
def get_next_newer_frame(frame): """ get a lldb.Frame object representing the next newer frame on stack """ if not frame or not frame.is_valid(): mdb_print("Trouble accessing newer LLDB Frame") return None else: #return frame.newer() mark = 0 target = lldb.debugger.GetSelectedTarget() process = target.GetProcess() thread = process.GetSelectedThread() for sframe in thread: if mark == 1: return sframe if frame == sframe: mark = 1
def get_newest_frame(): """ get a gdb.Frame object representing the innermost frame on stack """ try: #frame = lldb.newest_frame() #target = lldb.GetSelectedTarget() target = lldb.debugger.GetTargetAtIndex(0) process = target.GetProcess() thread = process.GetSelectedThread() frame = thread.GetFrameAtIndex(0) except: mdb_print("Trouble accessing newest LLDB Frame") return None #if not frame or not frame.is_valid(): if not frame or not frame.IsValid(): return None #print("MFrame: ",frame) return frame
def show_path(self): mdb_print("Maple source path list: --") if len(maple_source_path_list) is 0: mdb_print("none") return for path in maple_source_path_list: mdb_print(path) if m_debug.Debug: m_datastore.mlldb_rdata.show_file_cache()
def get_newest_maple_frame_func_lib_info(): """ starting from currently selected frame, find out the newest Maple frame, and then call get_maple_frame_func_lib_info() to return func header offset, library .so path, library's coresponding assembly file path, func_header address, and the Maple frame itself returns: 1, func_header_offset: in string. 2, so_path: string. so library file full path. 3, asm_path: string. asm file full path. 4, func_header: int. address of function header. 5, mirmpl_path: string. .mpl.mir.mpl file full path or all None if no valid Maple frame found """ frame = get_selected_frame() if not frame: mdb_print('Selected Maple frame is invalid') return None, None, None, None, None mdb_print('Maple frame located: ') index = 0 info_buffer = None frame_symbol = None frame_sal = None while frame: #print('Maple frame: ', frame) if not is_maple_frame(frame): frame = get_next_older_frame(frame) print('Getting older frame: ', frame) index += 1 continue info_buffer, frame_symbol, frame_sal = get_frame_info(frame) if not frame_sal or not frame_symbol: mdb_print('Unable to locate Maple frame data') return None, None, None, None, None return get_maple_frame_func_lib_info(frame) return None, None, None, None, None
def do_backtrace(self, full, mbt_format): selected_frame = m_frame.get_selected_frame() newest_frame = m_frame.get_newest_frame() if not selected_frame or not newest_frame: mdb_print('Unable to locate Maple frame') return # walk through from innermost frame to selected frame index = 0 frame = newest_frame while frame != selected_frame and frame: print("Frame is:", frame) frame = m_frame.get_next_older_frame(frame) index += 1 if not frame: mdb_print('No valid frames found') return start_level = index mdb_print('Maple Traceback (most recent call first):') while frame: if m_frame.is_maple_frame(frame): print_maple_frame(frame, index, mbt_format) elif full: print_mdb_frame(frame, index) #else: # print("not maple frame") index += 1 frame = m_frame.get_next_older_frame(frame) #if m_debug.Debug: m_debug.dbg_print("frame=", frame, " index=", index) if frame: m_util.mdb_exec_to_null('up') #m_util.mdb_exec_to_null('frame select'+str(index)) # move frame back to the original stack level #m_util.mdb_exec_to_null('down-silently ' + str(index - start_level - 1)) m_util.mdb_exec_to_null('down ' + str(index - start_level - 1))
def update_mdb_runtime_data(self): if m_debug.Debug: print("update mdb rt data ...") addr_offset, so_path, asm_path, func_header, mirmpl_path = m_frame.get_newest_maple_frame_func_lib_info( ) targ = lldb.debugger.GetSelectedTarget() module_cnt = targ.GetNumModules() #for x in range(0, module_cnt): # mod = targ.GetModuleAtIndex(x) # print("Module:",mod) if m_debug.Debug: m_debug.dbg_print("addr_offset=", addr_offset) m_debug.dbg_print("so_path=", so_path) m_debug.dbg_print("asm_path=", asm_path) m_debug.dbg_print("func_header=", func_header) m_debug.dbg_print("mirmpl_path=", mirmpl_path) if not addr_offset or not so_path or not asm_path or not func_header or not mirmpl_path: return if not self.mirmpl_info_cache_has_key(mirmpl_path): if m_debug.Debug: mdb_print("create Maple mir.mpl cache using file: " + mirmpl_path) self.create_mirmpl_info_cache(mirmpl_path) if not self.mirbin_info_cache_has_key(asm_path): if m_debug.Debug: mdb_print("create Maple symbol cache using file: " + asm_path) self.create_mirbin_info_cache(asm_path) def_file_path = asm_path[: -1] + 'macros.def' if 'VtableImpl' in asm_path else asm_path[: -1] + 'VtableImpl.macros.def' if not def_file_path in self.class_def.def_paths: if m_debug.Debug: mdb_print("create def cache using file: " + def_file_path) self.create_class_def(def_file_path)
def show_mir_block_lines(self): mdb_print("mlldb_rdata.mir_block_lines cache ==== ") mdb_print(str(self.mir_block_lines))
def print_maple_frame(frame, index, mbt_format): """ prints one Maple backtrace frame. params: frame: a gdb.Frame object index: a index number of the frame. mbt_format: print Maple backtrace in specified format, MBT_FORMAT_SRC or MBT_FORMAT_ASM or MBT_FORMAT_MIR """ data = m_datastore.get_stack_frame_data(frame) if not data: #mdb_print('#%i no info' % (index)) data = frame.register["rdi"].value #data = frame.register["rdi"].Dereference().GetValue() if m_debug.Debug: m_debug.dbg_print("RDI: ", data) ivar = frame.FindVariable("mir_header") if m_debug.Debug: m_debug.dbg_print("Variable: ", ivar) #for ivar in lldb.frame.variables: #print("Variable: ", ivar) mdb_print(('#%i %s' % (index, data)).replace("\n * frame", "")) return so_path = data['frame_func_header_info']['so_path'] asm_path = data['frame_func_header_info']['asm_path'] mirmpl_path = data['frame_func_header_info']['mirmpl_path'] func_addr_offset = data['frame_func_header_info']['func_addr_offset'] func_name = data['frame_func_header_info']['func_name'] src_file_short_name = data['frame_func_src_info']['short_src_file_name'] asm_line_num = data['frame_func_src_info']['asm_line'] mirmpl_line_num = data['frame_func_src_info']['mirmpl_line'] src_file_line = data['frame_func_src_info']['short_src_file_line'] func_argus_locals = data['func_argus_locals'] if src_file_short_name: file_full_path = None for source_path in m_list.maple_source_path_list: file_full_path = m_list.find_one_file(src_file_short_name, source_path) if not file_full_path: continue else: break if not file_full_path: file_full_path = "unknown" else: file_full_path = 'unknown' # buffer format # index func_offset func_symbol (type argu=value, ...) at source-file-full-path:line_num args_buffer = "" arg_num = len(func_argus_locals['formals_name']) MColors.init_maple_colors() for i in range(arg_num): arg_value = m_info.get_maple_caller_argument_value( i, arg_num, func_argus_locals['formals_type'][i]) if m_debug.Debug: m_debug.dbg_print("arg_num=", arg_num, " arg_value=", arg_value) if arg_value: if func_argus_locals['formals_type'][i] == 'a64': mtype = m_info.get_maple_a64_pointer_type(arg_value) if not mtype: mtype = "" else: mtype = "" else: arg_value = '...' mtype = "" args_buffer += func_argus_locals['formals_type'][i] args_buffer += '<' + mtype + '>' args_buffer += ' ' args_buffer += MColors.BT_ARGNAME + func_argus_locals['formals_name'][ i] + MColors.ENDC #args_buffer += func_argus_locals['formals_name'][i] args_buffer += '=' args_buffer += arg_value args_buffer += ', ' if arg_num > 0: args_buffer = args_buffer[:-2] if m_debug.Debug: m_debug.dbg_print("arg_num=", arg_num, " args_buffer=", args_buffer) if mbt_format == MBT_FORMAT_ASM: buffer = '#%2i %s:%s %s(%s) at %s:%s' % \ (index, MColors.bt_addr( so_path.split('/')[-1]), MColors.bt_addr(func_addr_offset),\ m_util.color_symbol(MColors.BT_FNNAME, func_name), args_buffer, MColors.bt_src(asm_path.strip()), asm_line_num) elif mbt_format == MBT_FORMAT_SRC: buffer = '#%2i %s:%s %s(%s) at %s:%s' % \ (index, MColors.bt_addr(so_path.split('/')[-1]), MColors.bt_addr(func_addr_offset),\ m_util.color_symbol(MColors.BT_FNNAME, func_name), args_buffer, MColors.bt_src(file_full_path.strip()), src_file_line) else: buffer = '#%2i %s:%s %s(%s) at %s:%s' % \ (index, MColors.bt_addr(so_path.split('/')[-1]),MColors.bt_addr(func_addr_offset),\ m_util.color_symbol(MColors.BT_FNNAME, func_name), args_buffer, MColors.bt_src(mirmpl_path.strip()), mirmpl_line_num) #mdb_print(buffer) mdb_print(buffer.replace("\n frame", ""))
def show_src_file_lines(self): mdb_print("mlldb_rdata.src_file_lines cache ==== ") mdb_print(str(self.src_file_lines))
def display_mir_file_lines(self, filename, line_num, mir_tuple): """ params: filename: string. asm file full path line_num: int. line number of this asm file mir_tuple: (maple_symbol_block_start_line, block_start_offset, block_end_offset) in mir.mpl file """ exist = m_datastore.mlldb_rdata.in_mirblock_lines( filename, mir_tuple[0]) if exist: total = m_datastore.mlldb_rdata.get_mirblock_lines( filename, mir_tuple[0]) else: with open(filename) as fp: offset = mir_tuple[1] fp.seek(offset) total = 0 while offset < mir_tuple[2]: line = fp.readline() offset += len(line) total += 1 m_datastore.mlldb_rdata.add_mirblock_lines(filename, mir_tuple[0], total) try: count = int(m_set.msettings["linecount"]) if count < 9: count = default_mir_display_line_count if count != 0 else total << 1 except: count = default_mir_display_line_count if line_num < mir_tuple[0]: line_num = mir_tuple[0] if line_num > mir_tuple[0] + total: line_num = mir_tuple[0] + total - 1 curr_num = line_num - mir_tuple[0] + 1 half = (count - 1) >> 1 s_line = curr_num - half if curr_num > half + 1 else 1 half = count - half - 1 e_line = curr_num + half if curr_num + half <= total else total mdb_print("mir file: %s%s%s line: %d" % (MColors.BT_SRC, filename, MColors.ENDC, line_num)) ss_line = mir_tuple[0] + s_line - 1 if m_util.Highlighted: buf =m_util.shell_cmd('dd skip=%d bs=1 count=%d if=%s 2> /dev/null |' ' highlight -O xterm256 --config-file=%s -s %s | sed -n %d,%dp |' ' nl -ba -s" " -w12 -v%d | sed "s/^ \\( *%d \\)/=>\\1/"' \ % (mir_tuple[1], mir_tuple[2] - mir_tuple[1], filename, mpl_lang, \ m_util.HighlightStyle, s_line, e_line, ss_line, line_num)) else: buf =m_util.shell_cmd('dd skip=%d bs=1 count=%d if=%s 2> /dev/null |' ' sed -n %d,%dp | nl -ba -s" " -w12 -v%d | sed "s/^ \\( *%d \\)/=>\\1/"' \ % (mir_tuple[1], mir_tuple[2] - mir_tuple[1], filename, \ s_line, e_line, ss_line, line_num)) buf = re.sub(r"\#(\w+.*)", MColors.lblue('#\\1').strip(), buf, flags=re.MULTILINE) buf = re.sub(r'\$(\w+)', MColors.lyellow('$\\1').strip(), buf, flags=re.MULTILINE) buf = re.sub(r'\&(\w+\s)', MColors.lmagenta('&\\1').strip(), buf, flags=re.MULTILINE) m_util.mdb_write(buf) self.prev_mir_file_line = line_num self.frame_data['frame_func_src_info'][ 'mirmpl_line'] = line_num + count if line_num + count < mir_tuple[ 0] + total else mir_tuple[0] + total - 1
def display_asm_file_lines(self, filename, line_num, asm_tuple): """ params: filename: string. asm file full path line_num: int. line number of this asm file asm_tuple: (maple_symbol_block_start_line, block_start_offset, block_end_offset) """ exist = m_datastore.mlldb_rdata.in_asmblock_lines( filename, asm_tuple[0]) if exist: total = m_datastore.mlldb_rdata.get_asmblock_lines( filename, asm_tuple[0]) else: with open(filename) as fp: offset = asm_tuple[1] fp.seek(offset) total = 0 while offset < asm_tuple[2]: line = fp.readline() offset += len(line) total += 1 m_datastore.mlldb_rdata.add_asmblock_lines(filename, asm_tuple[0], total) try: count = int(m_set.msettings["linecount"]) if count < 9: count = default_asm_display_line_count if count != 0 else total << 1 except: count = default_asm_display_line_count if line_num < asm_tuple[0]: line_num = asm_tuple[0] if line_num > asm_tuple[0] + total: line_num = asm_tuple[0] + total - 1 curr_num = line_num - asm_tuple[0] + 1 half = (count - 1) >> 1 s_line = curr_num - half if curr_num > half + 1 else 1 half = count - half - 1 e_line = curr_num + half if curr_num + half <= total else total mdb_print("asm file: %s%s%s line: %d" % (MColors.BT_SRC, filename, MColors.ENDC, line_num)) ss_line = asm_tuple[0] + s_line - 1 if m_util.Highlighted: buf =m_util.shell_cmd('dd skip=%d bs=1 count=%d if=%s 2> /dev/null |' ' highlight -O xterm256 --config-file=%s -s %s | sed -n %d,%dp |' ' nl -ba -s" " -w12 -v%d | sed "s/^ \\( *%d \\)/=>\\1/"' \ % (asm_tuple[1], asm_tuple[2] - asm_tuple[1], filename, asm_lang, \ m_util.HighlightStyle, s_line, e_line, ss_line, line_num)) else: buf =m_util.shell_cmd('dd skip=%d bs=1 count=%d if=%s 2> /dev/null |' ' sed -n %d,%dp | nl -ba -s" " -w12 -v%d | sed "s/^ \\( *%d \\)/=>\\1/"' \ % (asm_tuple[1], asm_tuple[2] - asm_tuple[1], filename, \ s_line, e_line, ss_line, line_num)) #buf = buf.replace(".long",MColors.magenta(".long")) #buf = buf.replace(".byte",MColors.magenta(".byte")) #buf = buf.replace(".word",MColors.magenta(".word")) #buf = re.sub(r"\/\/", MColors.cyan("//"), buf,flags=re.MULTILINE) buf = re.sub(r'\/\/\ ((%|\w+).*)', MColors.cyan('// \\1').strip(), buf, flags=re.MULTILINE) buf = re.sub(r'\.(\w+)', MColors.magenta('.\\1').strip(), buf, flags=re.MULTILINE) m_util.mdb_write(buf) self.prev_asm_file_line = line_num self.frame_data['frame_func_src_info'][ 'asm_line'] = line_num + count if line_num + count < asm_tuple[ 0] + total else asm_tuple[0] + total - 1
def show_general_fullpath(self): mdb_print("mlldb_rdata.general_fullpath cache ==== ") mdb_print(str(self.general_fullpath))
def show_asm_block_lines(self): mdb_print("mdb_rdata.asm_block_lines cache ==== ") mdb_print(str(self.asm_block_lines))