Skip to content

Commit 93bb984

Browse files
committed
fix breakpoint strategy in mcu and add parse_int function decorator
1 parent 0bf2c17 commit 93bb984

File tree

3 files changed

+45
-41
lines changed

3 files changed

+45
-41
lines changed

qiling/debugger/qdb/frontend.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from qiling.const import QL_ARCH
1313

14-
from .utils import dump_regs, get_arm_flags, disasm, parse_int, handle_bnj
14+
from .utils import dump_regs, get_arm_flags, disasm, _parse_int, handle_bnj
1515
from .const import *
1616

1717

@@ -59,7 +59,7 @@ def extract_count(t):
5959
elif ql.archtype == QL_ARCH.MIPS:
6060
addr = addr.replace("fp", "s8")
6161

62-
addr = getattr(ql.reg, addr) if addr in ql.reg.register_mapping.keys() else parse_int(addr)
62+
addr = getattr(ql.reg, addr) if addr in ql.reg.register_mapping.keys() else _parse_int(addr)
6363

6464
def unpack(bs, sz):
6565
return {

qiling/debugger/qdb/qdb.py

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from qiling.debugger import QlDebugger
1414

1515
from .frontend import context_reg, context_asm, examine_mem
16-
from .utils import parse_int, handle_bnj, is_thumb, CODE_END
16+
from .utils import _parse_int, handle_bnj, is_thumb, CODE_END, parse_int
1717
from .utils import Breakpoint, TempBreakpoint
1818
from .const import *
1919

@@ -42,7 +42,7 @@ def dbg_hook(self: QlQdb, init_hook: str):
4242
if self.ql.archtype != QL_ARCH.CORTEX_M:
4343

4444
if init_hook:
45-
init_hook = parse_int(init_hook)
45+
init_hook = _parse_int(init_hook)
4646

4747
self.set_breakpoint(init_hook, is_temp=True)
4848

@@ -112,16 +112,22 @@ def _run(self: Qldbg, address: int = 0, end: int = 0, count: int = 0) -> None:
112112
address = self.cur_addr
113113

114114
if self.ql.archtype == QL_ARCH.CORTEX_M and self.ql.count != 0:
115-
count = self.ql.count
115+
116+
while self.ql.count:
117+
self.ql.arch.step()
118+
self.ql.count -= 1
119+
if self.cur_addr in self.bp_list.keys():
120+
print(f"{color.CYAN}[+] hit breakpoint at 0x{self.cur_addr:08x}{color.END}")
121+
break
122+
123+
self.do_context()
124+
return
116125

117126
if self.ql.archtype in (QL_ARCH.ARM, QL_ARCH.ARM_THUMB, QL_ARCH.CORTEX_M) and is_thumb(self.ql.reg.cpsr):
118127
address |= 1
119128

120129
self.ql.emu_start(begin=address, end=end, count=count)
121130

122-
if self.ql.count:
123-
self.ql.count -= count
124-
125131
def parseline(self: QlQdb, line: str) -> Tuple[Optional[str], Optional[str], str]:
126132
"""
127133
Parse the line into a command name and a string containing
@@ -203,7 +209,7 @@ def do_step(self: QlQdb, *args) -> Optional[bool]:
203209
print(f"{color.RED}[!] The program is not being run.{color.END}")
204210

205211
else:
206-
# save reg dump for data highliting changes
212+
# save reg dump for data highlighting changes
207213
self._saved_reg_dump = dict(filter(lambda d: isinstance(d[0], str), self.ql.reg.save().items()))
208214

209215
if self.rr:
@@ -244,7 +250,7 @@ def del_breakpoint(self: QlQdb, bp: Union[Breakpoint, TempBreakpoint]) -> None:
244250
if self.bp_list.pop(bp.addr, None):
245251
bp.hook.remove()
246252

247-
def do_start(self: QlQdb, address: str = "", *args) -> None:
253+
def do_start(self: QlQdb, *args) -> None:
248254
"""
249255
restore qiling instance context to initial state
250256
"""
@@ -253,43 +259,29 @@ def do_start(self: QlQdb, address: str = "", *args) -> None:
253259

254260
self.do_context()
255261

256-
def do_breakpoint(self: QlQdb, address: str = "") -> None:
262+
@parse_int
263+
def do_breakpoint(self: QlQdb, address: Optional[int] = 0) -> None:
257264
"""
258265
set breakpoint on specific address
259266
"""
260267

261-
address = parse_int(address) if address else self.cur_addr
268+
if address is None:
269+
address = self.cur_addr
262270

263271
self.set_breakpoint(address)
264272

265273
print(f"{color.CYAN}[+] Breakpoint at 0x{address:08x}{color.END}")
266274

267-
def do_continue(self: QlQdb, address: str = "") -> None:
275+
@parse_int
276+
def do_continue(self: QlQdb, address: Optional[int] = 0) -> None:
268277
"""
269-
continue execution from current address if no specified
278+
continue execution from current address if not specified
270279
"""
271280

272-
if address:
273-
address = parse_int(address)
274-
275-
print(f"{color.CYAN}continued from 0x{self.cur_addr:08x}{color.END}")
276-
277-
if self.ql.archtype == QL_ARCH.CORTEX_M:
278-
end = 0
279-
280-
if len(self.bp_list) > 0:
281-
end = next(filter(lambda x: x > self.cur_addr, sorted(self.bp_list.keys())))
282-
283-
self._run(address, end=end)
284-
285-
if end != 0:
286-
print(f"{color.CYAN}[+] hit breakpoint at 0x{self.cur_addr:08x}{color.END}")
287-
288-
if self.ql.count:
289-
# print context if still running
290-
self.do_context()
281+
if address is None:
282+
address = self.cur_addr
291283

292-
return
284+
print(f"{color.CYAN}continued from 0x{address:08x}{color.END}")
293285

294286
self._run(address)
295287

@@ -315,13 +307,14 @@ def do_show(self: QlQdb, *args) -> None:
315307
self.ql.mem.show_mapinfo()
316308
print(f"Breakpoints: {[hex(addr) for addr in self.bp_list.keys()]}")
317309

318-
def do_disassemble(self: QlQdb, address: str, /, *args, **kwargs) -> None:
310+
@parse_int
311+
def do_disassemble(self: QlQdb, address: Optional[int] = 0, *args) -> None:
319312
"""
320313
disassemble instructions from address specified
321314
"""
322315

323316
try:
324-
context_asm(self.ql, parse_int(address), 4)
317+
context_asm(self.ql, _parse_int(address), self.ql.pointersize)
325318
except:
326319
print(f"{color.RED}[!] something went wrong ...{color.END}")
327320

qiling/debugger/qdb/utils.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,21 @@ def _get_mode(bits):
7777

7878

7979
# parse unsigned integer from string
80-
def parse_int(s: str) -> int:
80+
def _parse_int(s: str) -> int:
8181
return int(s, 0)
8282

8383

84+
# function dectorator for parse argument as integer
85+
def parse_int(func: Callable) -> Callable:
86+
def wrap(qdb, s: str) -> int:
87+
assert type(s) is str
88+
try:
89+
ret = _parse_int(s)
90+
except:
91+
ret = None
92+
return func(qdb, ret)
93+
return wrap
94+
8495
# check wether negative value or not
8596
def is_negative(i: int) -> int:
8697
return i & (1 << 31)
@@ -250,7 +261,7 @@ def regdst_eq_pc(op_str):
250261

251262
if to_jump:
252263
if '#' in line.op_str:
253-
ret_addr = parse_int(line.op_str.split('#')[-1])
264+
ret_addr = _parse_int(line.op_str.split('#')[-1])
254265
else:
255266
ret_addr = read_reg_val(line.op_str)
256267

@@ -298,7 +309,7 @@ def regdst_eq_pc(op_str):
298309

299310
if "]" in rn_offset.split(", ")[1]: # pre-indexed immediate
300311
_, r, imm = line.op_str.replace("[", "").replace("]", "").replace("!", "").replace("#", "").split(", ")
301-
ret_addr = ql.unpack32(ql.mem.read(parse_int(imm) + read_reg_val(r), 4))
312+
ret_addr = ql.unpack32(ql.mem.read(_parse_int(imm) + read_reg_val(r), 4))
302313

303314
else: # post-indexed immediate
304315
# FIXME: weired behavior, immediate here does not apply
@@ -353,7 +364,7 @@ def regdst_eq_pc(op_str):
353364

354365
elif line.mnemonic == "sub" and regdst_eq_pc(line.op_str):
355366
_, r, imm = line.op_str.split(", ")
356-
ret_addr = read_reg_val(r) - parse_int(imm.strip("#"))
367+
ret_addr = read_reg_val(r) - _parse_int(imm.strip("#"))
357368

358369
elif line.mnemonic == "mov" and regdst_eq_pc(line.op_str):
359370
_, r = line.op_str.split(", ")
@@ -390,7 +401,7 @@ def _read_reg(regs, _reg):
390401
# get registers or memory address from op_str
391402
targets = [
392403
read_reg_val(each)
393-
if '$' in each else parse_int(each)
404+
if '$' in each else _parse_int(each)
394405
for each in line.op_str.split(", ")
395406
]
396407

0 commit comments

Comments
 (0)