Skip to content

Commit 3dae873

Browse files
authored
Merge pull request #1086 from ucgJhe/qdb
Qdb improvements
2 parents cf541bf + afca5bb commit 3dae873

File tree

3 files changed

+120
-31
lines changed

3 files changed

+120
-31
lines changed

qiling/debugger/qdb/frontend.py

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import unicorn
1515

16-
from .utils import dump_regs, get_arm_flags, disasm, _parse_int, handle_bnj
16+
from .utils import dump_regs, get_x86_eflags, get_arm_flags, disasm, _parse_int, handle_bnj
1717
from .const import *
1818

1919

@@ -192,8 +192,34 @@ def context_reg(ql: Qiling, saved_states: Optional[Mapping[str, int]] = None, /,
192192

193193
print(lines.format(*_cur_regs.values()))
194194

195-
elif ql.archtype in (QL_ARCH.ARM, QL_ARCH.ARM_THUMB, QL_ARCH.CORTEX_M):
195+
elif ql.archtype == QL_ARCH.X86:
196+
197+
if saved_states is not None:
198+
_saved_states = copy.deepcopy(saved_states)
199+
_diff = [k for k in _cur_regs if _cur_regs[k] != _saved_states[k]]
200+
201+
else:
202+
_diff = None
203+
204+
lines = ""
205+
for idx, r in enumerate(_cur_regs, 1):
206+
if len(r) == 2:
207+
line = "{}{}: 0x{{:08x}} {}\t\t".format(_colors[(idx-1) // 4], r, color.END)
208+
else:
209+
line = "{}{}: 0x{{:08x}} {}\t".format(_colors[(idx-1) // 4], r, color.END)
210+
211+
if _diff and r in _diff:
212+
line = f"{color.UNDERLINE}{color.BOLD}{line}"
213+
214+
if idx % 4 == 0 and idx != 32:
215+
line += "\n"
216+
217+
lines += line
196218

219+
print(lines.format(*_cur_regs.values()))
220+
print(color.GREEN, "EFLAGS: [CF: {flags[CF]}, PF: {flags[PF]}, AF: {flags[AF]}, ZF: {flags[ZF]}, SF: {flags[SF]}, OF: {flags[OF]}]".format(flags=get_x86_eflags(ql.reg.ef)), color.END, sep="")
221+
222+
elif ql.archtype in (QL_ARCH.ARM, QL_ARCH.ARM_THUMB, QL_ARCH.CORTEX_M):
197223

198224
_cur_regs.update({"sl": _cur_regs.pop("r10")})
199225
_cur_regs.update({"ip": _cur_regs.pop("r12")})
@@ -265,7 +291,10 @@ def context_reg(ql: Qiling, saved_states: Optional[Mapping[str, int]] = None, /,
265291
def print_asm(ql: Qiling, insn: CsInsn, to_jump: Optional[bool] = None, address: int = None) -> None:
266292

267293
opcode = "".join(f"{b:02x}" for b in insn.bytes)
268-
trace_line = f"0x{insn.address:08x}{opcode:10s} {insn.mnemonic:10} {insn.op_str:35s}"
294+
if ql.archtype in (QL_ARCH.X86, QL_ARCH.X8664):
295+
trace_line = f"0x{insn.address:08x}{opcode:20s} {insn.mnemonic:10} {insn.op_str:35s}"
296+
else:
297+
trace_line = f"0x{insn.address:08x}{opcode:10s} {insn.mnemonic:10} {insn.op_str:35s}"
269298

270299
cursor = " "
271300
if ql.reg.arch_pc == insn.address:
@@ -282,39 +311,59 @@ def context_asm(ql: Qiling, address: int) -> None:
282311

283312
with context_printer(ql, field_name="[ DISASM ]"):
284313

285-
# assembly before current location
314+
if ql.archtype in (QL_ARCH.X86, QL_ARCH.X8664):
315+
past_list = []
316+
317+
# assembly before current location
318+
319+
line = disasm(ql, address)
320+
acc_size = line.size
321+
322+
while line and len(past_list) != 10:
323+
past_list.append(line)
324+
next_start = address + acc_size
325+
line = disasm(ql, next_start)
326+
acc_size += line.size
327+
328+
# print four insns before current location
329+
for line in past_list[:-1]:
330+
print_asm(ql, line)
331+
332+
else:
333+
334+
# assembly before current location
286335

287-
past_list = []
336+
past_list = []
288337

289-
line = disasm(ql, address-0x10)
338+
line = disasm(ql, address-0x10)
290339

291-
while line:
292-
if line.address == address:
293-
break
340+
while line:
341+
if line.address == address:
342+
break
294343

295-
addr = line.address + line.size
296-
line = disasm(ql, addr)
344+
addr = line.address + line.size
345+
line = disasm(ql, addr)
297346

298-
if not line:
299-
break
347+
if not line:
348+
break
300349

301-
past_list.append(line)
350+
past_list.append(line)
302351

303-
# print four insns before current location
304-
for line in past_list[:-1][:4]:
305-
print_asm(ql, line)
352+
# print four insns before current location
353+
for line in past_list[:-1][:4]:
354+
print_asm(ql, line)
306355

307-
# assembly for current location
356+
# assembly for current location
308357

309-
cur_ins = disasm(ql, address)
310-
to_jump, next_stop = handle_bnj(ql, address)
311-
print_asm(ql, cur_ins, to_jump=to_jump)
358+
cur_ins = disasm(ql, address)
359+
to_jump, next_stop = handle_bnj(ql, address)
360+
print_asm(ql, cur_ins, to_jump=to_jump)
312361

313-
# assembly after current location
362+
# assembly after current location
314363

315-
forward_insn_size = cur_ins.size
316-
for _ in range(5):
317-
forward_insn = disasm(ql, address+forward_insn_size)
318-
if forward_insn:
319-
print_asm(ql, forward_insn)
320-
forward_insn_size += forward_insn.size
364+
forward_insn_size = cur_ins.size
365+
for _ in range(5):
366+
forward_insn = disasm(ql, address+forward_insn_size)
367+
if forward_insn:
368+
print_asm(ql, forward_insn)
369+
forward_insn_size += forward_insn.size

qiling/debugger/qdb/qdb.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,11 @@ def do_step(self: QlQdb, *args) -> Optional[bool]:
232232
self.ql.count -= 1
233233

234234
else:
235-
count = 1 if next_stop == self.cur_addr + 4 else 2
235+
if self.ql.archtype in (QL_ARCH.X86, QL_ARCH.X8664):
236+
count = 1
237+
else:
238+
count = 1 if next_stop == self.cur_addr + 4 else 2
239+
236240
self._run(count=count)
237241

238242
self.do_context()
@@ -323,7 +327,7 @@ def do_disassemble(self: QlQdb, address: Optional[int] = 0, *args) -> None:
323327
"""
324328

325329
try:
326-
context_asm(self.ql, _parse_int(address), self.ql.pointersize)
330+
context_asm(self.ql, address)
327331
except:
328332
print(f"{color.RED}[!] something went wrong ...{color.END}")
329333

qiling/debugger/qdb/utils.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ def dump_regs(ql: Qiling) -> Mapping[str, int]:
3636
"r12", "sp", "lr", "pc",
3737
)
3838

39+
elif ql.archtype == QL_ARCH.X86:
40+
41+
_reg_order = (
42+
"eax", "ebx", "ecx", "edx",
43+
"esp", "ebp", "esi", "edi",
44+
"eip", "ss", "cs", "ds", "es",
45+
"fs", "gs", "ef",
46+
)
47+
3948
elif ql.archtype == QL_ARCH.CORTEX_M:
4049

4150
_reg_order = (
@@ -83,7 +92,7 @@ def _parse_int(s: str) -> int:
8392

8493
# function dectorator for parse argument as integer
8594
def parse_int(func: Callable) -> Callable:
86-
def wrap(qdb, s: str) -> int:
95+
def wrap(qdb, s: str = "") -> int:
8796
assert type(s) is str
8897
try:
8998
ret = _parse_int(s)
@@ -109,6 +118,7 @@ def handle_bnj(ql: Qiling, cur_addr: str) -> Callable[[Qiling, str], int]:
109118
QL_ARCH.ARM : handle_bnj_arm,
110119
QL_ARCH.ARM_THUMB: handle_bnj_arm,
111120
QL_ARCH.CORTEX_M : handle_bnj_arm,
121+
QL_ARCH.X86 : handle_bnj_x86,
112122
}.get(ql.archtype)(ql, cur_addr)
113123

114124

@@ -121,6 +131,17 @@ def get_cpsr(bits: int) -> (bool, bool, bool, bool):
121131
)
122132

123133

134+
def get_x86_eflags(bits: int) -> Dict[str, bool]:
135+
return {
136+
"CF" : bits & 0x0001 != 0, # CF, carry flag
137+
"PF" : bits & 0x0004 != 0, # PF, parity flag
138+
"AF" : bits & 0x0010 != 0, # AF, adjust flag
139+
"ZF" : bits & 0x0040 != 0, # ZF, zero flag
140+
"SF" : bits & 0x0080 != 0, # SF, sign flag
141+
"OF" : bits & 0x0800 != 0, # OF, overflow flag
142+
}
143+
144+
124145
def is_thumb(bits: int) -> bool:
125146
return bits & 0x00000020 != 0
126147

@@ -158,8 +179,23 @@ def _read_inst(ql: Qiling, addr: int) -> int:
158179
latter_two = ql.unpack16(ql.mem.read(addr+2, 2))
159180
result += ql.pack16(latter_two)
160181

182+
elif ql.archtype in (QL_ARCH.X86, QL_ARCH.X8664):
183+
# due to the variadic lengh of x86 instructions ( 1~15 )
184+
# always assume the maxium size for disassembler to tell
185+
# what is it exactly.
186+
result = ql.mem.read(addr, 15)
187+
161188
return result
162189

190+
def handle_bnj_x86(ql: Qilng, cur_addr: str) -> int:
191+
192+
# FIXME: NO HANDLE BRANCH AND JUMP FOR X86 FOR NOW
193+
194+
to_jump = False
195+
ret_addr = None
196+
197+
return (to_jump, ret_addr)
198+
163199

164200
def handle_bnj_arm(ql: Qiling, cur_addr: str) -> int:
165201

0 commit comments

Comments
 (0)