@@ -2308,18 +2308,16 @@ def infer_context(self): # type: () -> Emulator
23082308 """Emulate the code before this function call, and return the state.
23092309
23102310 The goal of this function is to recover the state of the CPU
2311- before the function call, as well as possible. This will work well in case
2312- the assembly looks like , for example:
2311+ before the function call, as well as possible. This will work well when
2312+ parameters are constants written just before the call , for example:
23132313
23142314 mov eax, 30
23152315 mov ebx, DAT_encrypted_string
23162316 call decrypt_string
23172317
2318- Then recovering eax them is as simple as call.infer_context()["eax"]."""
2318+ Then recovering eax is as simple as call.infer_context()["eax"]."""
23192319 basicblock = BasicBlock (self ._address )
2320- emu = Emulator ()
2321- emu .emulate (basicblock .start_address , self ._address )
2322- return emu
2320+ return Emulator .new (basicblock .start_address , self ._address )
23232321
23242322 @property
23252323 def high_pcodeop (self ): # type: () -> PcodeOp|None
@@ -3593,7 +3591,7 @@ def single_step(self): # type: () -> bool
35933591 return False
35943592
35953593 @staticmethod
3596- def emulate_new (
3594+ def new (
35973595 start ,
35983596 ends = [],
35993597 callback = lambda emu : None ,
@@ -3602,8 +3600,20 @@ def emulate_new(
36023600 ): # type: (Addr, Addr|list[Addr], Callable[[Emulator], str|None], Callable[[Emulator], bool], int) -> Emulator
36033601 """Emulate from start to end address, with callback for each executed address.
36043602
3605- This function creates a new emulator, runs emulate on it, and returns it.
3606- See emulate documentation for information about the parameters."""
3603+ >>> Emulator.new("main", maxsteps=100)["EAX"]
3604+ 128
3605+
3606+ This function is a convenience wrapper around emulate and can be always
3607+ replaced by three lines of code. The above is equivalent to:
3608+
3609+ >>> emu = Emulator()
3610+ >>> emu.emulate("main", maxsteps=100)
3611+ >>> emu["EAX"]
3612+ 128
3613+
3614+ This function may be used for quickly doing one-off emulations.
3615+
3616+ See `emulate` documentation for info about this method parameters."""
36073617 emu = Emulator ()
36083618 emu .emulate (start , ends , callback , stop_when , maxsteps )
36093619 return emu
@@ -3621,7 +3631,7 @@ def emulate(
36213631 >>> emu = Emulator()
36223632 >>> def callback(emu):
36233633 >>> print("executing {:x}'.format(emu.pc))
3624- >>> emu.trace (Function("main").entrypoint, callback=callback, maxsteps=3)
3634+ >>> emu.emulate (Function("main").entrypoint, callback=callback, maxsteps=3)
36253635 SUB ESP,0x2d4
36263636 PUSH EBX
36273637 PUSH EBP
@@ -3678,6 +3688,17 @@ def is_at_breakpoint(self): # type: () -> bool
36783688 """Check if the emulator is at a breakpoint"""
36793689 return self .raw .getEmulator ().isAtBreakpoint ()
36803690
3691+ # Basic unicorn compatibility, because why not
3692+ # You may prefer these aliases if you already know Unicorn API.
3693+ reg_write = write_register
3694+ reg_read = read_register
3695+ mem_write = write_bytes
3696+ mem_read = read_bytes
3697+ mem_map = (
3698+ lambda _1 , _2 , _3 : None
3699+ ) # This is a noop - all memory is already available.
3700+ emu_start = lambda self , begin , until : self .emulate (begin , until )
3701+
36813702
36823703class MemoryBlock (GhidraWrapper , BodyTrait ):
36833704 """A Ghidra wrapper for a Ghidra MemoryBlock"""
0 commit comments