ghidra icon indicating copy to clipboard operation
ghidra copied to clipboard

Emulator discards changed PC register value when stepping

Open zb3 opened this issue 1 year ago • 3 comments

Describe the bug I'd like to skip to a specific address, so I edit the PC register (aarch64). After this, the dynamic listing changes its location, and the new PC register value is visible in the threads panel. However, after I press "Step the integrated emulator a single instruction", it steps to the next instruction that'd be executed if I didn't change the PC register - IOW, it ignores my PC register change.

Maybe changing the PC register is not the correct way to make a given thread "jump" to arbitrary location, but then I couldn't find out how to do it..

To Reproduce Steps to reproduce the behavior:

  1. Open any aarch64 program in the emulator
  2. Right click any instruction, press "Emulate program in new trace"
  3. Populate memory, for instance via "load emulator from programs"
  4. Step a single instruction, observe PC now being X
  5. Change the PC register to point to a different location Y
  6. Step a single instruction, observing that instruction at X was executed, not at Y

Expected behavior In the step 6, the instruction at Y should be executed.

Environment (please complete the following information):

  • OS: Linux x64
  • Java Version: 21.0.4
  • Ghidra Version: 11.1.2
  • Ghidra Origin: github release

zb3 avatar Aug 29 '24 16:08 zb3

Note invalidating emulator cache does not help

zb3 avatar Aug 29 '24 16:08 zb3

Okay. I believe it's because the emulator keeps a copy of the counter, rather than reading it from the state every loop. It seems I need to treat patches affecting it as a special case. I think this will be an easy fix. In the meantime, a possible workaround is to use the Go To Time action. (Yes, I agree, that is not intuitive, but hey, it's a workaround....) After Step 5 in your process above, access the action by pressing Ctrl-G or in the menus: Debugger → Go To Time. At the very end of the expression, you should see something like {pc=Y}. Change that to {goto Y}.

Furthermore, if this is a section of code you want to skip every time, consider placing an injection breakpoint. Use K to place a SW_EXECUTE breakpoint at X. Right-click it and choose Set Injection (Emulator). Clear the default and enter goto Y; (mind the semicolon) and press OK. You'll need to invalidate the emulator cache for that to take effect.

nsadeveloper789 avatar Aug 29 '24 19:08 nsadeveloper789

@nsadeveloper789 thanks for your help and fast reply :)

I eventually figured out a more invasive way - patching the dynamic listing so that there's an unconditional branch, but I see these injection breakpoints are interesting, I didn't even know they exist.

zb3 avatar Aug 30 '24 00:08 zb3