0

I'm writing a Forth programming system using nasm assembly language. I have a quite good error recovery system that catches more or less all compile errors - the action it takes is to restore the entire system to the state that prevailed before I started typing the line containing the error. There's a command history, so that puts me in a position to just "up arrow" back to the offending line of input, correct my goof, and hit Enter to try again.

Forth does not offer any significant protection against addressing errors or arithmetic errors like divide by zero. These are common errors in a Forth environment. Currently they segfault my system and send me back to bash. I'd like to catch these errors and respond by running through the error handling process described above. I'm trying, but for the life of me I can't figure out how to catch the addressing fault signal that ends in a segfault. Furthermore, I'm finding that existing information online about this stuff is 1) highly C-centric and 2) often conflicting across sources.

So, in general I'm asking for "excellent references" on this kind of work, particularly in assembly language. Specifically, though, I can add that in these situations I do not want to ultimately return to the precise point I was at when the fault occurred. I want to abandon that ongoing work and re-enter my command interpreter after restoring my state. I've been telling myself this means I want to "diddle" the processor context the system saves on the stack and uses to return to my code - if I can alter the value of a couple of registers (the instruction pointer and my "Forth level instruction pointer," which is just another register), then it should do precisely what I want.

The references I've seen say that the third parameter sent to my signal handler should be a pointer to that context structure, and it seems that parameter three should be in DX. If that's correct, then the task is pretty simple and only would take a few lines of assembly code, but I haven't been able to get it to work yet. I've tried to use gdb on this, but I'm not sure it's meant to work with signal handlers - when execution stops at the breakpoint I set in the handler, the instruction pointer doesn't have the expected value and rdx contains 1, which is clearly not a pointer to anything.

So, that's my story - hope someone can offer some good advice.

PS: I use no C libraries of any kind in this system, and I don't need to do any system calls from the handler or anything like that.

Right now I've tried this:

               mov     rax, [rdx+0x38]         ; machine return: next
               mov     [rdx+0x80], rax
               add     rax, err_p-o            ; Forth return is err
               mov     [rdx+0x28], rax
               mov     rax, 8                  ; error 8 to stack
               mov     [rdx+0x70], rax
               xor     rax, rax
               ret

The first two lines are meant to point the instruction pointer to the code I want to run, which is always addressed by r15 in my system, the next two are meant to aim the "Forth instruction pointer" at an error word, the next two place a parameter for that error word into rcx, and the xor ax, ax was to provide a success return, which I don't know is required. I'm referring here with these register names to the location of that register's value in the context structure, of course. My Forth caches the top stack element in rcx.

  • *My Forth caches the top stack element in rcx.* Note that the `syscall` instruction itself clobbers RCX (and R11). You might want to choose a different one, or syscalls should be rare enough that you can just reload it after since it's just a cache anyway. – Peter Cordes Mar 23 '22 at 22:44
  • This is not a [mcve]. You did not show how you set the signal up for example. Did you specify `SA_SIGINFO`? – Jester Mar 23 '22 at 22:49
  • [Signal handling in asm: Why am I receiving SIGSEGV when invoking the sys\_pause syscall?](https://stackoverflow.com/q/46479421) shows NASM code for catching signals. And see comments and duplicate list on [How do you catch segmentation faults in assembly?](https://stackoverflow.com/q/69179326) – Peter Cordes Mar 23 '22 at 22:50
  • Peter: syscalls are quite rare. I do want to use this on Linux, since that's my typical OS, but the long term goal for it is to serve as a stand-alone OS for "gadgets" that I build. I use syscalls for keyboard, screen, and disk i/o, and I use some at startup and shutdown to diddle my termios. But that's it - otherwise it runs entirely "within itself." – Kip Ingram Mar 24 '22 at 04:14
  • @KipIngram: If you want people to see your replies, make sure you `@user` them. (You get notified because we're commenting under your post.) So long-term you want to replace POSIX signal handling with x86-64 `#PF` page-fault and `#DE` divide-exception handling? That's potentially easier, since x86 exceptions are designed and documented at the asm level, and you don't have to "return" from an exception; unlike Linux signals, the CPU doesn't know that you're "inside an exception" that you haven't returned from yet. You can iret or not. But for signals you do need a `sigreturn` syscall. – Peter Cordes Mar 24 '22 at 05:18
  • @PeterCordes Thanks - a bit new to SO here. And thanks for the earlier refs - they were helpful and in fact I was able to get things working. I think part of the dearth of info is that I'm swimming around in machine dependent waters here that people generally like to stay out of. I'm not fully informed on SO procedure yet, but if you want to copy that comment into an answer I'll be glad to "choose it" or whatever it is I need to do. :-) Thanks again, man, and take care. – Kip Ingram Mar 24 '22 at 16:36
  • Welcome to SO! So your question was basically a duplicate, if the info and example there of signal-handling in asm was enough? Instead of posting an answer with just a link to another question, on SO we can just mark questions as duplicates. (That's fine, unlike other close reasons, it doesn't necessarily mean the question was bad.) – Peter Cordes Mar 24 '22 at 17:47

0 Answers0