diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-05-26 19:41:59 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-05-28 03:22:11 -0700 |
| commit | d9a82e9f3c87aa318fb05819249656b43fde15e3 (patch) | |
| tree | 136ac947f2cac5fb6ba2599ce4e0540f46cb5dcf /linux.e | |
| parent | 33fb92edc2a9958234b1bc2431a17fa4edbd83ea (diff) | |
add the ability to bind signal handlers
and a useful example one ;) this also involved fixing the failure cases in input.e to handle EINTR correctly. it required a lot of tracing, but now the expected state of the stack is much better commented for next time. many thanks to @cks@mastodon.social who found code in the Go compiler which had the details of what's required in regard to the restorer, which made the whole thing work, and to @snowfox@tech.lgbt who did some experimental testing around the exact requirements. both those contributions are reflected in the documentation added with this CL. additional thanks to everyone who chimed in on the fedi thread, your comments kept us going! Force-Push: yes Change-Id: I97fd89426bf807df5565e011d3665f7e904fa138
Diffstat (limited to 'linux.e')
| -rw-r--r-- | linux.e | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/linux.e b/linux.e index bf5a3e1..fb386f9 100644 --- a/linux.e +++ b/linux.e @@ -11,6 +11,22 @@ ~ that, since rsp is preserved, or we can use one of the other registers. We ~ don't ourselves save other registers because our caller should do that, if ~ it cares. +~ +~ In the kernel source, you may find the following files useful to +~ reference: +~ +~ * arch/x86/entry/syscalls/syscall_64.tbl +~ * include/linux/syscalls.h +~ * include/linux/compat.h +~ +~ Don't be confused by tools/scripts/syscall.tbl, it's not for x86. +~ +~ This file loads early, before dynamic.e. So, although it superficially +~ appears to be able to do allocation and high-level flow control, those come +~ from the transforms, which means they're shallow implementations. The stuff +~ here can't be moved later, because input.e relies on it, and the dynamic +~ stuff relies on that. So, there's additional Linux functionality in another +~ file that loads later, linux-dynamic.e. ~ (call number -- return value) @@ -21,91 +37,93 @@ :rax push-reg64 ~ return value here ! ] ;asm -~ (call number, first param -- return value) +~ (first param, call number -- return value) : syscall-1 [ here @ - :rdi pop-reg64 ~ first param :rax pop-reg64 ~ syscall number + :rdi pop-reg64 ~ first param syscall :rax push-reg64 ~ return value here ! ] ;asm -~ (call number, first param, second param -- return value) +~ (first param, second param, call number -- return value) : syscall-2 [ here @ :rsi :rbx mov-reg64-reg64 ~ save rsi + :rax pop-reg64 ~ syscall number :rsi pop-reg64 ~ second param :rdi pop-reg64 ~ first param - :rax pop-reg64 ~ syscall number syscall :rbx :rsi mov-reg64-reg64 ~ restore rsi :rax push-reg64 ~ return value here ! ] ;asm -~ (call number, first param, second param, third param -- return value) +~ (first param, second param, third param, call number -- return value) : syscall-3 [ here @ :rsi :rbx mov-reg64-reg64 ~ save rsi + :rax pop-reg64 ~ syscall number :rdx pop-reg64 ~ third param :rsi pop-reg64 ~ second param :rdi pop-reg64 ~ first param - :rax pop-reg64 ~ syscall number syscall :rbx :rsi mov-reg64-reg64 ~ restore rsi :rax push-reg64 ~ return value here ! ] ;asm -~ (call number, first param, second param, third param, fourth param +~ (first param, second param, third param, fourth param, call number ~ -- return value) : syscall-4 [ here @ :rsi :rbx mov-reg64-reg64 ~ save rsi + :rax pop-reg64 ~ syscall number :r10 pop-extrareg64 ~ fourth param :rdx pop-reg64 ~ third param :rsi pop-reg64 ~ second param :rdi pop-reg64 ~ first param - :rax pop-reg64 ~ syscall number syscall :rbx :rsi mov-reg64-reg64 ~ restore rsi :rax push-reg64 ~ return value here ! ] ;asm -~ (call number, first param, second param, third param, fourth param, -~ fifth param -- return value) +~ (first param, second param, third param, fourth param, fifth param, +~ call number -- return value) : syscall-5 [ here @ :rsi :rbx mov-reg64-reg64 ~ save rsi + :rax pop-reg64 ~ syscall number :r8 pop-extrareg64 ~ fifth param :r10 pop-extrareg64 ~ fourth param :rdx pop-reg64 ~ third param :rsi pop-reg64 ~ second param :rdi pop-reg64 ~ first param - :rax pop-reg64 ~ syscall number syscall :rbx :rsi mov-reg64-reg64 ~ restore rsi :rax push-reg64 ~ return value here ! ] ;asm -~ (call number, first param, second param, third param, fourth param, -~ fifth param, sixth param -- return value) +~ (first param, second param, third param, fourth param, fifth param, +~ sixth param, call number -- return value) : syscall-6 [ here @ :rsi :rbx mov-reg64-reg64 ~ save rsi + :rax pop-reg64 ~ syscall number :r9 pop-extrareg64 ~ sixth param :r8 pop-extrareg64 ~ fifth param :r10 pop-extrareg64 ~ fourth param :rdx pop-reg64 ~ third param :rsi pop-reg64 ~ second param :rdi pop-reg64 ~ first param - :rax pop-reg64 ~ syscall number syscall :rbx :rsi mov-reg64-reg64 ~ restore rsi :rax push-reg64 ~ return value here ! ] ;asm +~ Raw system calls +~ ~~~~~~~~~~~~~~~~ ~ This does the Linux exit() system call, passing it an exit code taken ~ from the stack. It does not return. @@ -148,7 +166,7 @@ here ! ] ;asm -~ (length to read, base address -- *) +~ (length to read, base address -- result code) : sys-read [ here @ :rcx pop-reg64 ~ address from stack |