diff --git a/qiling/debugger/qdb/frontend.py b/qiling/debugger/qdb/frontend.py index 3e34abc3..cf4a1d08 100644 --- a/qiling/debugger/qdb/frontend.py +++ b/qiling/debugger/qdb/frontend.py @@ -252,7 +252,7 @@ class CtxManager(object): past_list.append(line) # print four insns before current location - for line in past_list[:-1][:4]: + for line in past_list[:-1]: self.print_asm(line) # assembly for current location diff --git a/qiling/debugger/qdb/qdb.py b/qiling/debugger/qdb/qdb.py index 4bb5c64d..d6366254 100644 --- a/qiling/debugger/qdb/qdb.py +++ b/qiling/debugger/qdb/qdb.py @@ -44,15 +44,26 @@ class QlQdb(cmd.Cmd, QlDebugger): # self.ql.loader.elf_entry # .text of binary def bp_handler(ql, address, size, bp_list): - if address in bp_list: - ql.emu_stop() - _ = bp_list.pop(address) + + if (bp := self.bp_list.get(address, None)): + + if isinstance(bp, TempBreakpoint): + # remove TempBreakpoint once hitted + self.del_breakpoint(bp) + + else: + if bp.hitted: + return + + print(f"{color.CYAN}[+] hit breakpoint at 0x{self.cur_addr:08x}{color.END}") + bp.hitted = True + + ql.stop() self.do_context() self.ql.hook_code(bp_handler, self.bp_list) if init_hook and self.ql.loader.entry_point != init_hook: - breakpoint() self.do_breakpoint(init_hook) self.cur_addr = self.ql.loader.entry_point @@ -82,27 +93,6 @@ class QlQdb(cmd.Cmd, QlDebugger): self.ql.reg.arch_pc = address - def _bp_handler(self: QlQdb, *args) -> None: - """ - internal function for handling once breakpoint hitted - """ - - if (bp := self.bp_list.get(self.cur_addr, None)): - - if isinstance(bp, TempBreakpoint): - # remove TempBreakpoint once hitted - self.del_breakpoint(bp) - - else: - if bp.hitted: - return - - print(f"{color.CYAN}[+] hit breakpoint at 0x{self.cur_addr:08x}{color.END}") - bp.hitted = True - - self.ql.stop() - self.do_context() - def _save(self: QlQdb, *args) -> None: """ internal function for saving state of qiling instance @@ -220,6 +210,12 @@ class QlQdb(cmd.Cmd, QlDebugger): self._restore() self.do_context() + def update_reg_dump(self: QlQdb) -> None: + """ + internal function for updating registers dump + """ + self._saved_reg_dump = dict(filter(lambda d: isinstance(d[0], str), self.ql.reg.save().items())) + def do_step_in(self: QlQdb, *args) -> Optional[bool]: """ execute one instruction at a time, will enter subroutine @@ -229,8 +225,7 @@ class QlQdb(cmd.Cmd, QlDebugger): print(f"{color.RED}[!] The program is not being run.{color.END}") else: - # save reg dump for data highlighting changes - self._saved_reg_dump = dict(filter(lambda d: isinstance(d[0], str), self.ql.reg.save().items())) + self.update_reg_dump() if self.rr: self._save() @@ -241,10 +236,9 @@ class QlQdb(cmd.Cmd, QlDebugger): return True if self.ql.archtype == QL_ARCH.CORTEX_M: - self.ql.count -= 1 - self.set_breakpoint(self.cur_addr, is_temp=True) - - self._run(count=1) + self.ql.arch.step() + else: + self._run(count=1) self.do_context() @@ -259,6 +253,7 @@ class QlQdb(cmd.Cmd, QlDebugger): else: prophecy = self.predictor.predict() + self.update_reg_dump() if prophecy.going: cur_insn = disasm(self.ql, self.cur_addr) @@ -267,7 +262,7 @@ class QlQdb(cmd.Cmd, QlDebugger): else: self.set_breakpoint(prophecy.where, is_temp=True) - self._run(self.cur_addr) + self._run() def set_breakpoint(self: QlQdb, address: int, is_temp: bool = False) -> None: """ @@ -276,19 +271,14 @@ class QlQdb(cmd.Cmd, QlDebugger): bp = TempBreakpoint(address) if is_temp else Breakpoint(address) - # if self.ql.archtype != QL_ARCH.CORTEX_M: - # skip hook_address for cortex_m - # bp.hook = self.ql.hook_address(self._bp_handler, address) - self.bp_list.update({address: bp}) def del_breakpoint(self: QlQdb, bp: Union[Breakpoint, TempBreakpoint]) -> None: """ - internal function for removing breakpoints + internal function for removing breakpoint """ - if self.bp_list.pop(bp.addr, None): - bp.hook.remove() + self.bp_list.pop(bp.addr, None) def do_start(self: QlQdb, *args) -> None: """ diff --git a/qiling/debugger/qdb/utils.py b/qiling/debugger/qdb/utils.py index dd9f5f8d..9178a262 100644 --- a/qiling/debugger/qdb/utils.py +++ b/qiling/debugger/qdb/utils.py @@ -240,9 +240,9 @@ class BranchPredictor_ARM(BranchPredictor): if "#" in line.op_str: prophecy.where = read_int(line.op_str.split("#")[-1]) else: - prophecy.where = read_reg_val(line.op_str) + prophecy.where = self.read_reg(line.op_str) - if regdst_eq_pc(line.op_str): + if self.regdst_eq_pc(line.op_str): next_addr = cur_addr + line.size n2_addr = next_addr + len(read_inst(next_addr)) prophecy.where += len(read_inst(n2_addr)) + len(read_inst(next_addr)) @@ -285,11 +285,11 @@ class BranchPredictor_ARM(BranchPredictor): r, _, imm = rn_offset.strip("[]!").partition(", #") if "]" in rn_offset.split(", ")[1]: # pre-indexed immediate - prophecy.where = ql.unpack32(ql.mem.read(read_int(imm) + read_reg_val(r), self.INST_SIZE)) + prophecy.where = ql.unpack32(ql.mem.read(read_int(imm) + self.read_reg(r), self.INST_SIZE)) else: # post-indexed immediate # FIXME: weired behavior, immediate here does not apply - prophecy.where = ql.unpack32(ql.mem.read(read_reg_val(r), self.INST_SIZE)) + prophecy.where = ql.unpack32(ql.mem.read(self.read_reg(r), self.INST_SIZE)) elif line.mnemonic in ("addls", "addne", "add") and self.regdst_eq_pc(line.op_str): V, C, Z, N = get_cpsr(ql.reg.cpsr) @@ -305,10 +305,10 @@ class BranchPredictor_ARM(BranchPredictor): n = read_int(expr[-1].strip("#")) * 2 if line.mnemonic == "addls" and (C == 0 or Z == 1): - prophecy.where = extra + read_reg_val(r1) + read_reg_val(r2) * n + prophecy.where = extra + self.read_reg(r1) + self.read_reg(r2) * n elif line.mnemonic == "add" or (line.mnemonic == "addne" and Z == 0): - prophecy.where = extra + read_reg_val(r1) + (read_reg_val(r2) * n if imm else read_reg_val(r2)) + prophecy.where = extra + self.read_reg(r1) + (self.read_reg(r2) * n if imm else self.read_reg(r2)) elif line.mnemonic in ("tbh", "tbb"): @@ -322,11 +322,11 @@ class BranchPredictor_ARM(BranchPredictor): if line.mnemonic == "tbh": - r1 = read_reg_val(r1) * n + r1 = self.read_reg(r1) * n elif line.mnemonic == "tbb": - r1 = read_reg_val(r1) + r1 = self.read_reg(r1) to_add = int.from_bytes(ql.mem.read(cur_addr+r1, 2 if line.mnemonic == "tbh" else 1), byteorder="little") * n prophecy.where = cur_addr + to_add @@ -348,11 +348,11 @@ class BranchPredictor_ARM(BranchPredictor): elif line.mnemonic == "sub" and self.regdst_eq_pc(line.op_str): _, r, imm = line.op_str.split(", ") - prophecy.where = read_reg_val(r) - read_int(imm.strip("#")) + prophecy.where = self.read_reg(r) - read_int(imm.strip("#")) elif line.mnemonic == "mov" and self.regdst_eq_pc(line.op_str): _, r = line.op_str.split(", ") - prophecy.where = read_reg_val(r) + prophecy.where = self.read_reg(r) if prophecy.where & 1: prophecy.where -= 1 @@ -544,17 +544,16 @@ class Breakpoint(object): """ dummy class for breakpoint """ - def __init__(self, address: int): - self.addr = address + def __init__(self, addr): + self.addr = addr self.hitted = False - self.hook = None class TempBreakpoint(Breakpoint): """ dummy class for temporay breakpoint """ - def __init__(self, address): - super().__init__(address) + def __init__(self, addr): + super().__init__(addr) class ParseError(Exception): pass