start signal.h
This commit is contained in:
parent
42911ccf67
commit
408e9b0e81
4 changed files with 96 additions and 2 deletions
|
@ -5,7 +5,7 @@
|
|||
; read-only data 4MB addresses 0x800000-0xbfffff
|
||||
; read-write data 4MB addresses 0xc00000-0xffffff
|
||||
; note that file offsets and runtime addresses are the same.
|
||||
; you should be able to change these constants (in a way that's consistent) without breaking anything:
|
||||
; if you want to change these constants, make sure you update signal.h's _SIGNAL_HANDLERS!
|
||||
#define ENTRY_ADDR 0x200000
|
||||
#define FUNCTIONS_ADDR 0x400000
|
||||
#define FUNCTIONS_END 0x800000
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
#define _STDLIB_DEBUG
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
void test_signal_handler(int x) {
|
||||
printf("interompu\n");
|
||||
_Exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
printf("%.16g\n", cosh(10));
|
||||
signal(SIGINT, test_signal_handler);
|
||||
while (1){}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
2
05/setjmp.h
Normal file
2
05/setjmp.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
// @NONSTANDARD
|
||||
#error "longjmp is not supported."
|
85
05/signal.h
Normal file
85
05/signal.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#ifndef _SIGNAL_H
|
||||
#define _SIGNAL_H
|
||||
|
||||
|
||||
#include <stdc_common.h>
|
||||
|
||||
typedef long sig_atomic_t; // there are no "asynchronous interrupts"
|
||||
|
||||
#define SIG_DFL 0
|
||||
#define SIG_IGN _sig_ign
|
||||
#define SIG_ERR (-1)
|
||||
|
||||
typedef void (*_Sighandler)(int);
|
||||
|
||||
struct sigaction {
|
||||
void (*handler)(int);
|
||||
unsigned long flags;
|
||||
void (*restorer)(void);
|
||||
unsigned long mask;
|
||||
};
|
||||
|
||||
unsigned char _signal_restorer[] = {
|
||||
0x48,0xb8,15,0,0,0,0,0,0,0, // mov rax, 15 (sigreturn)
|
||||
0x0f,0x05 // syscall
|
||||
};
|
||||
|
||||
#define _SIGNAL_HANDLERS 0xfff000
|
||||
#define _LE64(x) (x)&0xff, ((x)>> 8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff, \
|
||||
((x)>>32)&0xff, ((x)>>40)&0xff, ((x)>>48)&0xff, (x)>>56
|
||||
|
||||
// we need to do this weird indirection because linux has a different
|
||||
// calling convention from us.
|
||||
unsigned char _signal_handler[] = {
|
||||
// signal # passed in rdi
|
||||
0x48,0x89,0xf8, // mov rax, rdi (signal #)
|
||||
0x50, // push rax
|
||||
0x50, // push rax (allocate space for return value)
|
||||
0x48,0xb8,_LE64(_SIGNAL_HANDLERS), // mov rax, _SIGNAL_HANDLERS
|
||||
0x48,0x89,0xc3, // mov rbx, rax
|
||||
0x48,0x89,0xf8, // mov rax, rdi (signal #)
|
||||
0x48,0xc1,0xe0,0x03, // shl rax, 3
|
||||
0x48,0x01,0xd8, // add rax, rbx
|
||||
0x48,0x89,0xc3, // mov rbx, rax
|
||||
0x48,0x8b,0x03, // mov rax, [rbx]
|
||||
0xff,0xd0, // call rax
|
||||
0x48,0x81,0xc4,16,0,0,0, // add rsp, 16
|
||||
0xc3 // ret
|
||||
};
|
||||
|
||||
#define _SA_RESTORER 0x04000000
|
||||
|
||||
int __sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) {
|
||||
return __syscall(13, signum, act, oldact, 8, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void _sig_ign(int signal) {
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned long _sig_mask = 0;
|
||||
|
||||
_Sighandler signal(int sig, _Sighandler func) {
|
||||
if (func == SIG_DFL) {
|
||||
// @TODO
|
||||
return 0;
|
||||
}
|
||||
if (func == SIG_IGN) {
|
||||
func = _sig_ign;
|
||||
}
|
||||
|
||||
void **handlers = _SIGNAL_HANDLERS;
|
||||
handlers[sig] = func;
|
||||
|
||||
_sig_mask |= 1ul << (sig-1);
|
||||
struct sigaction act = {0};
|
||||
act.handler = _signal_handler;
|
||||
act.mask = _sig_mask;
|
||||
act.flags = _SA_RESTORER;
|
||||
act.restorer = _signal_restorer;
|
||||
__sigaction(sig, &act, NULL);
|
||||
return 0;//@TODO
|
||||
}
|
||||
|
||||
#endif // _SIGNAL_H
|
Loading…
Add table
Add a link
Reference in a new issue