88import cmd
99
1010from qiling import Qiling
11- from qiling .const import QL_ARCH , QL_VERBOSE
11+ from qiling .const import QL_OS , QL_ARCH , QL_VERBOSE
1212from qiling .debugger import QlDebugger
1313
14- from .utils import setup_context_render , setup_branch_predictor , SnapshotManager , run_qdb_script
14+ from .utils import setup_context_render , setup_branch_predictor , setup_address_marker , SnapshotManager , run_qdb_script
1515from .memory import setup_memory_Manager
16- from .misc import parse_int , Breakpoint , TempBreakpoint
16+ from .misc import parse_int , Breakpoint , TempBreakpoint , try_read_int
1717from .const import color
1818
1919from .utils import QDB_MSG , qdb_print
@@ -34,6 +34,7 @@ def __init__(self, ql: Qiling, init_hook: str = "", rr: bool = False, script: st
3434 self ._saved_reg_dump = None
3535 self ._script = script
3636 self .bp_list = {}
37+ self .marker = setup_address_marker ()
3738
3839 self .rr = SnapshotManager (ql ) if rr else None
3940 self .mm = setup_memory_Manager (ql )
@@ -72,7 +73,10 @@ def bp_handler(ql, address, size, bp_list):
7273
7374 self .ql .hook_code (bp_handler , self .bp_list )
7475
75- if init_hook and self .ql .loader .entry_point != init_hook :
76+ if self .ql .os .type == QL_OS .BLOB :
77+ self .ql .loader .entry_point = self .ql .loader .load_address
78+
79+ elif init_hook and self .ql .loader .entry_point != init_hook :
7680 self .do_breakpoint (init_hook )
7781
7882 self .cur_addr = self .ql .loader .entry_point
@@ -319,6 +323,7 @@ def do_disassemble(self, address: Optional[int] = None) -> None:
319323 qdb_print (QDB_MSG .ERROR )
320324
321325 def do_examine (self , line : str ) -> None :
326+
322327 """
323328 Examine memory: x/FMT ADDRESS.
324329 format letter: o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char), s(string) and z(hex, zero padded on the left)
@@ -328,6 +333,29 @@ def do_examine(self, line: str) -> None:
328333
329334 if type (err_msg := self .mm .parse (line )) is str :
330335 qdb_print (QDB_MSG .ERROR , err_msg )
336+
337+
338+ def do_set (self , line : str ) -> None :
339+ """
340+ set register value of current context
341+ """
342+ # set $a = b
343+
344+ reg , val = line .split ("=" )
345+ reg_name = reg .strip ().strip ("$" )
346+ reg_val = try_read_int (val .strip ())
347+
348+ if reg_name in self .ql .arch .regs .save ().keys ():
349+ if reg_val :
350+ setattr (self .ql .arch .regs , reg_name , reg_val )
351+ self .do_context ()
352+ qdb_print (QDB_MSG .INFO , f"set register { reg_name } to 0x{ (reg_val & 0xfffffff ):08x} " )
353+
354+ else :
355+ qdb_print (QDB_MSG .ERROR , f"error parsing input: { reg_val } as integer value" )
356+
357+ else :
358+ qdb_print (QDB_MSG .ERROR , f"invalid register: { reg_name } " )
331359
332360 def do_start (self , * args ) -> None :
333361 """
@@ -348,6 +376,61 @@ def do_context(self, *args) -> None:
348376 self .render .context_stack ()
349377 self .render .context_asm ()
350378
379+ def do_jump (self , loc : str , * args ) -> None :
380+ """
381+ seek to where ever valid location you want
382+ """
383+
384+ sym = self .marker .get_symbol (loc )
385+ addr = sym if sym is not None else try_read_int (loc )
386+
387+ # check validation of the address to be seeked
388+ if self .ql .mem .is_mapped (addr , 4 ):
389+ if sym :
390+ qdb_print (QDB_MSG .INFO , f"seek to { loc } @ 0x{ addr :08x} ..." )
391+ else :
392+ qdb_print (QDB_MSG .INFO , f"seek to 0x{ addr :08x} ..." )
393+
394+ self .cur_addr = addr
395+ self .do_context ()
396+
397+ else :
398+ qdb_print (QDB_MSG .ERROR , f"the address to be seeked isn't mapped" )
399+
400+ def do_mark (self , args = "" ):
401+ """
402+ mark a user specified address as a symbol
403+ """
404+
405+ args = args .split ()
406+ if len (args ) == 0 :
407+ loc = self .cur_addr
408+ sym_name = self .marker .mark_only_loc (loc )
409+
410+ elif len (args ) == 1 :
411+ if (loc := try_read_int (args [0 ])):
412+ sym_name = self .marker .mark_only_loc (loc )
413+
414+ else :
415+ loc = self .cur_addr
416+ sym_name = args [0 ]
417+ if (err := self .marker .mark (sym_name , loc )):
418+ qdb_print (QDB_MSG .ERROR , err )
419+ return
420+
421+ elif len (args ) == 2 :
422+ sym_name , addr = args
423+ if (loc := try_read_int (addr )):
424+ self .marker .mark (sym_name , loc )
425+ else :
426+ qdb_print (QDB_MSG .ERROR , f"unable to mark symbol at address: '{ addr } '" )
427+ return
428+ else :
429+ qdb_print (QDB_MSG .ERROR , "symbol should not be empty ..." )
430+ return
431+
432+ qdb_print (QDB_MSG .INFO , f"mark symbol '{ sym_name } ' at address: 0x{ loc :08x} ..." )
433+
351434 def do_show (self , * args ) -> None :
352435 """
353436 show some runtime information
@@ -357,6 +440,7 @@ def do_show(self, *args) -> None:
357440 self .ql .log .info (info_line )
358441
359442 qdb_print (QDB_MSG .INFO , f"Breakpoints: { [hex (addr ) for addr in self .bp_list .keys ()]} " )
443+ qdb_print (QDB_MSG .INFO , f"Marked symbol: { [{key :hex (val )} for key ,val in self .marker .mark_list ]} " )
360444 if self .rr :
361445 qdb_print (QDB_MSG .INFO , f"Snapshots: { len ([st for st in self .rr .layers if isinstance (st , self .rr .DiffedState )])} " )
362446
@@ -403,6 +487,8 @@ def do_EOF(self, *args) -> None:
403487 do_r = do_run
404488 do_s = do_step_in
405489 do_n = do_step_over
490+ do_j = do_jump
491+ do_m = do_mark
406492 do_q = do_quit
407493 do_x = do_examine
408494 do_p = do_backward
0 commit comments