3

Is there a SPARC equivalent to x86's single step mode? What I want is to stop execution after every instruction and move control flow to a trap handler or something similar.

I thought of using the ta instruction in the delayed execution slot but this would not work when the previous instruction is a branching instruction with the annul bit set.

  • I think you're supposed substitute Tcc instructions and handle delay slots by decoding instructions and looking at the saved NPC register value. – Ross Ridge Sep 16 '18 at 20:40

1 Answers1

1

Sparc lacks a single step bit in PSR, so it's harder to single step. But I've used a trick to help get closer. Set TPC to the address of the instruction you want to single step, and set TNPC to an address someplace else where you've placed a trap instruction. When you execute the retry instruction to get back to the process context, it will single step the one instruction you want, then it will next execute the trap instruction which will bring you right back to the kernel, where you can do whatever you want. (n.b this is for sparc64, not sure about sparc32). This is a nice trick because you don't have modify existing instructions in the user's address space. This was important to me since I was single stepping instructions in the kernel.

Another idea I had, but never tried, was to simply set TNPC to an illegal address. Then after the instruction at TPC was executed, you'd get an automatic trap back into the kernel. And since the trap handling code knows that the process is being single stepped, there would be no confusion over a "real" illegal address trap.

Rob Gardner
  • 201
  • 1
  • 4
  • ... unless the first instruction was a jump to an illegal address (in a buggy program). Maybe you can choose your illegal address so that can't happen, at least not with a relative jump, but presumably a register-indirect jump could take you anywhere. (I don't know SPARC details enough to know if this is a real concern, or if the trap handler would have enough info to sort that out.) – Peter Cordes Sep 17 '18 at 01:04
  • I can think of a couple of ways to deal with that. First, you could read the instruction you're about to single step and see if it's a register indirect jump, and decode it to find the source register and any offsets, then compute the target of the jump and save that for comparison with the TPC value after the illegal address trap. Two, just treat the illegal address we put in TNPC as meta data; fill it with a pseudo random number, and then confirm that the illegal address that faulted is the same. If it's not, then the illegal address was caused by the stepped instruction, not by our address. – Rob Gardner Sep 17 '18 at 02:37
  • Both of those sound cumbersome. Relying on chance that you didn't happen to generate the same address that the target code will jump to is probably safe (especially with 64-bit addresses), but it would be nice to do something that's guaranteed safe. Does pointing TNPC at a trap instruction avoid all of that? That seems like the obvious way to go. – Peter Cordes Sep 17 '18 at 02:46
  • 1
    Yes, of course the safe thing to do is point TNPC at a trap instruction. All this other talk is just for fun, and I've never tried it. Just thought of an easy way to detect the difference between a user generated illegal address and one we generate: in the trap handler after the illegal address, look at TNPC. If it's the same as it was before the trap, then it means that the stepped instruction faulted. – Rob Gardner Sep 17 '18 at 03:18
  • Neat, maybe edit that into your answer. And BTW, I mostly only know x86, but some about how other ISAs are designed. ISA support for debugging on other machines, especially with branch-delay slots, is interesting. – Peter Cordes Sep 17 '18 at 03:25