In x86 long mode, is there a better way to skip the instruction after IRET than parsing the bytes at the stored IP and working out how much to add to it?
Modifying the bytes at IP isn't an option because I don't want the change to be "permanent".
Skipping the instruction after IRET
-
- Member
- Posts: 5578
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Skipping the instruction after IRET
No.
Why do you want to skip the instruction?
Why do you want to skip the instruction?
Re: Skipping the instruction after IRET
Because it's a non-fatal condition and I don't want the failing instruction to be retried.
To vastly simplify, what's going on is GC trickery; If a page contains candidates for garbage collection, I tag it oldspace and make it read-only. If something later tries to write to the page, it will page fault, allowing me to trap the write. The kernel will do the right thing for the object that was touched, but not the entire page. Since the kernel has completed the write, having the program try it again will loop.
Later I can GC the objects in the page that didn't get written to and keep just what's being actively used.
To vastly simplify, what's going on is GC trickery; If a page contains candidates for garbage collection, I tag it oldspace and make it read-only. If something later tries to write to the page, it will page fault, allowing me to trap the write. The kernel will do the right thing for the object that was touched, but not the entire page. Since the kernel has completed the write, having the program try it again will loop.
Later I can GC the objects in the page that didn't get written to and keep just what's being actively used.
Re: Skipping the instruction after IRET
No, you would need to parse the assembly pointed to by the IP and figure out the length of that instruction and add it to the IP. There is no easy way to solve that.
Re: Skipping the instruction after IRET
Hi Suzuran,
If you're using long mode (64 bit), you could try my disassembler: https://gitlab.com/bztsrc/osz/blob/mast ... 4/disasm.h. It has one function only:Where "virt_t" is a virtual address, uint64_t. This function receives an address, and returns the address of the next instruction. You obviously won't need the disassembled string, so just pass NULL as the second argument.
For protected mode (32 bit), you might want to take a look at OpenBSD's version: https://github.com/openbsd/src/blob/mas ... b_disasm.c. It has a very similar interface:
but it is not that trivial to reuse this code as it is a bit tied up with other parts of the BSD kernel (but not particularly hard either, just provide you own db_access implementation), and you'll have to manually remove the disassembled string writes from the code (all those db_print* calls). But at the end, it will do the job.
Cheers,
bzt
If you're using long mode (64 bit), you could try my disassembler: https://gitlab.com/bztsrc/osz/blob/mast ... 4/disasm.h. It has one function only:
Code: Select all
virt_t disasm(virt_t addr, char *str)
Code: Select all
nextinst = disasm(exceptioninst, NULL);
Code: Select all
vaddr_t db_disasm(vaddr_t loc, int altfmt);
Cheers,
bzt