Kernel: Add support for SA_SIGINFO

This commit is contained in:
Bananymous 2025-11-13 04:19:06 +02:00
parent a44c45ff9e
commit dd636ffcb2
13 changed files with 260 additions and 96 deletions

View File

@ -2,15 +2,41 @@
// stack contains // stack contains
// return address // return address
// return stack
// return rflags
// siginfo_t
// signal number // signal number
// signal handler // signal handler
.global signal_trampoline .global signal_trampoline
signal_trampoline: signal_trampoline:
pusha pushl %esi // gregs
pushl %edi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
pushl %ebp
movl 40(%esp), %edi movl 76(%esp), %eax // return sp
movl 36(%esp), %eax addl $4, %eax // return address
movl 80(%esp), %ebx // return ip
pushl %eax;
pushl %ebx
// FIXME: populate these
xorl %eax, %eax
pushl %eax // stack
pushl %eax
pushl %eax
pushl %eax // sigset
pushl %eax
pushl %eax // link
movl %esp, %edx // ucontext
leal 68(%esp), %esi // siginfo
movl 64(%esp), %edi // signal number
movl 60(%esp), %eax // handlers
// align stack to 16 bytes // align stack to 16 bytes
movl %esp, %ebp movl %esp, %ebp
@ -19,7 +45,9 @@ signal_trampoline:
subl $512, %esp subl $512, %esp
fxsave (%esp) fxsave (%esp)
subl $12, %esp subl $4, %esp
pushl %edx
pushl %esi
pushl %edi pushl %edi
call *%eax call *%eax
addl $16, %esp addl $16, %esp
@ -29,9 +57,21 @@ signal_trampoline:
// restore stack // restore stack
movl %ebp, %esp movl %ebp, %esp
popa addl $32, %esp
addl $8, %esp // restore registers
popl %ebp
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %edi
popl %esi
// skip handler, number, siginfo_t
addl $44, %esp
// restore flags
popf popf
movl (%esp), %esp movl (%esp), %esp

View File

@ -2,29 +2,48 @@
// stack contains // stack contains
// return address // return address
// return stack
// return rflags
// siginfo_t
// signal number // signal number
// signal handler // signal handler
.global signal_trampoline .global signal_trampoline
signal_trampoline: signal_trampoline:
pushq %rax pushq %r15 // gregs
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rbp
pushq %rdi
pushq %rsi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r14 pushq %r14
pushq %r15 pushq %r13
pushq %r12
pushq %r11
pushq %r10
pushq %r9
pushq %r8
pushq %rsi
pushq %rdi
pushq %rdx
pushq %rcx
pushq %rbx
pushq %rax
pushq %rbp
movq 128(%rsp), %rdi movq 200(%rsp), %rax // return sp
movq 120(%rsp), %rax addq $(128 + 8), %rax // red-zone and return address
movq 208(%rsp), %rbx // return ip
pushq %rax;
pushq %rbx
// FIXME: populate these
xorq %rax, %rax
pushq %rax // stack
pushq %rax
pushq %rax
pushq %rax // sigset
pushq %rax // link
movq %rsp, %rdx // ucontext
leaq 192(%rsp), %rsi // siginfo
movq 184(%rsp), %rdi // signal number
movq 176(%rsp), %rax // handler
// align stack to 16 bytes // align stack to 16 bytes
movq %rsp, %rbp movq %rsp, %rbp
@ -40,26 +59,32 @@ signal_trampoline:
// restore stack // restore stack
movq %rbp, %rsp movq %rbp, %rsp
popq %r15 addq $56, %rsp
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rsi
popq %rdi
popq %rbp
popq %rdx
popq %rcx
popq %rbx
popq %rax
addq $16, %rsp // restore registers
popq %rbp
popq %rax
popq %rbx
popq %rcx
popq %rdx
popq %rdi
popq %rsi
popq %r8
popq %r9
popq %r10
popq %r11
popq %r12
popq %r13
popq %r14
popq %r15
// skip handler, number, siginfo_t
addq $72, %rsp
// restore flags
popfq popfq
movq (%rsp), %rsp movq (%rsp), %rsp
// return over red-zone // return over red-zone and siginfo_t
ret $128 ret $128

View File

@ -192,7 +192,7 @@ namespace Kernel
void set_stopped(bool stopped, int signal); void set_stopped(bool stopped, int signal);
void wait_while_stopped(); void wait_while_stopped();
static BAN::ErrorOr<void> kill(pid_t pid, int signal); static BAN::ErrorOr<void> kill(pid_t pid, int signal, const siginfo_t& = {});
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal); BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact); BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
BAN::ErrorOr<long> sys_sigpending(sigset_t* set); BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
@ -290,7 +290,7 @@ namespace Kernel
return m_signal_pending_mask; return m_signal_pending_mask;
} }
void add_pending_signal(uint8_t signal) void add_pending_signal(uint8_t signal, const siginfo_t& info)
{ {
ASSERT(signal >= _SIGMIN); ASSERT(signal >= _SIGMIN);
ASSERT(signal <= _SIGMAX); ASSERT(signal <= _SIGMAX);
@ -302,6 +302,7 @@ namespace Kernel
if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG)) if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
return; return;
m_signal_pending_mask |= 1ull << signal; m_signal_pending_mask |= 1ull << signal;
m_signal_infos[signal] = info;
} }
void remove_pending_signal(uint8_t signal) void remove_pending_signal(uint8_t signal)
@ -354,6 +355,7 @@ namespace Kernel
uint64_t m_alarm_wake_time_ns { 0 }; uint64_t m_alarm_wake_time_ns { 0 };
mutable SpinLock m_signal_lock; mutable SpinLock m_signal_lock;
siginfo_t m_signal_infos[_SIGMAX + 1] { };
struct sigaction m_signal_handlers[_SIGMAX + 1] { }; struct sigaction m_signal_handlers[_SIGMAX + 1] { };
uint64_t m_signal_pending_mask { 0 }; uint64_t m_signal_pending_mask { 0 };

View File

@ -59,8 +59,8 @@ namespace Kernel
bool can_add_signal_to_execute() const; bool can_add_signal_to_execute() const;
bool will_execute_signal() const; bool will_execute_signal() const;
// Returns true if handled signal had SA_RESTART // Returns true if handled signal had SA_RESTART
bool handle_signal(int signal = 0); bool handle_signal(int signal = 0, const siginfo_t& signal_info = {});
void add_signal(int signal); void add_signal(int signal, const siginfo_t& info);
void set_suspend_signal_mask(uint64_t sigmask); void set_suspend_signal_mask(uint64_t sigmask);
static bool is_stopping_signal(int signal); static bool is_stopping_signal(int signal);
@ -174,6 +174,7 @@ namespace Kernel
InterruptStack m_interrupt_stack { }; InterruptStack m_interrupt_stack { };
InterruptRegisters m_interrupt_registers { }; InterruptRegisters m_interrupt_registers { };
siginfo_t m_signal_infos[_SIGMAX + 1] { };
uint64_t m_signal_pending_mask { 0 }; uint64_t m_signal_pending_mask { 0 };
uint64_t m_signal_block_mask { 0 }; uint64_t m_signal_block_mask { 0 };
BAN::Optional<uint64_t> m_signal_suspend_mask; BAN::Optional<uint64_t> m_signal_suspend_mask;

View File

@ -56,7 +56,7 @@ namespace Kernel::ACPI
EmbeddedController::~EmbeddedController() EmbeddedController::~EmbeddedController()
{ {
if (m_thread) if (m_thread)
m_thread->add_signal(SIGKILL); m_thread->add_signal(SIGKILL, {});
m_thread = nullptr; m_thread = nullptr;
} }

View File

@ -106,7 +106,7 @@ namespace Kernel
{ {
if (m_reading_count == 0) if (m_reading_count == 0)
{ {
Thread::current().add_signal(SIGPIPE); Thread::current().add_signal(SIGPIPE, {});
return BAN::Error::from_errno(EPIPE); return BAN::Error::from_errno(EPIPE);
} }
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex)); TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));

View File

@ -203,7 +203,7 @@ namespace Kernel
if (result.is_error()) if (result.is_error())
{ {
dwarnln("Demand paging: {}", result.error()); dwarnln("Demand paging: {}", result.error());
Thread::current().handle_signal(SIGKILL); Thread::current().handle_signal(SIGKILL, {});
goto done; goto done;
} }
} }
@ -273,30 +273,48 @@ namespace Kernel
{ {
// TODO: Confirm and fix the exception to signal mappings // TODO: Confirm and fix the exception to signal mappings
int signal = 0; siginfo_t signal_info {};
switch (isr) switch (isr)
{ {
case ISR::DivisionError: case ISR::DivisionError:
signal_info.si_signo = SIGFPE;
signal_info.si_code = FPE_INTDIV;
break;
case ISR::SIMDFloatingPointException: case ISR::SIMDFloatingPointException:
case ISR::x87FloatingPointException: case ISR::x87FloatingPointException:
signal = SIGFPE; // FIXME: this is probably not correct?
signal_info.si_signo = SIGFPE;
signal_info.si_code = FPE_FLTDIV;
break; break;
case ISR::AlignmentCheck: case ISR::AlignmentCheck:
signal = SIGBUS; signal_info.si_signo = SIGBUS;
signal_info.si_code = BUS_ADRALN;
break;
case ISR::GeneralProtectionFault:
// TODO: this assumes unaligned operand but GP can be also caused by
// a privileged instruction or uncanonical address in which case
// the generated signal should be different
signal_info.si_signo = SIGBUS;
signal_info.si_code = BUS_ADRALN;
break; break;
case ISR::InvalidOpcode: case ISR::InvalidOpcode:
signal = SIGILL; signal_info.si_signo = SIGILL;
signal_info.si_code = ILL_ILLOPC;
break; break;
case ISR::PageFault: case ISR::PageFault:
signal = SIGSEGV; signal_info.si_signo = SIGSEGV;
if (PageTable::current().get_page_flags(regs->cr2 & PAGE_ADDR_MASK) & PageTable::Flags::Present)
signal_info.si_code = SEGV_ACCERR;
else
signal_info.si_code = SEGV_MAPERR;
break; break;
default: default:
dwarnln("Unhandled exception"); dwarnln("Unhandled exception");
signal = SIGABRT; signal_info.si_signo = SIGABRT;
break; break;
} }
Thread::current().handle_signal(signal); Thread::current().handle_signal(signal_info.si_signo, signal_info);
} }
else else
{ {

View File

@ -36,7 +36,7 @@ namespace Kernel
ARPTable::~ARPTable() ARPTable::~ARPTable()
{ {
if (m_thread) if (m_thread)
m_thread->add_signal(SIGKILL); m_thread->add_signal(SIGKILL, {});
m_thread = nullptr; m_thread = nullptr;
} }

View File

@ -47,7 +47,7 @@ namespace Kernel
IPv4Layer::~IPv4Layer() IPv4Layer::~IPv4Layer()
{ {
if (m_thread) if (m_thread)
m_thread->add_signal(SIGKILL); m_thread->add_signal(SIGKILL, {});
m_thread = nullptr; m_thread = nullptr;
} }

View File

@ -502,7 +502,7 @@ namespace Kernel
LockGuard _(inode->m_mutex); LockGuard _(inode->m_mutex);
if (inode->has_error()) if (inode->has_error())
{ {
Thread::current().add_signal(SIGPIPE); Thread::current().add_signal(SIGPIPE, {});
return BAN::Error::from_errno(EPIPE); return BAN::Error::from_errno(EPIPE);
} }
if (is_nonblock && !inode->can_write()) if (is_nonblock && !inode->can_write())
@ -588,7 +588,7 @@ namespace Kernel
LockGuard _(inode->m_mutex); LockGuard _(inode->m_mutex);
if (inode->has_hungup()) if (inode->has_hungup())
{ {
Thread::current().add_signal(SIGPIPE); Thread::current().add_signal(SIGPIPE, {});
return BAN::Error::from_errno(EPIPE); return BAN::Error::from_errno(EPIPE);
} }
if (is_nonblock && !inode->can_write()) if (is_nonblock && !inode->can_write())

View File

@ -313,7 +313,17 @@ namespace Kernel
child.status = __WGENEXITCODE(status, signal); child.status = __WGENEXITCODE(status, signal);
parent_process->add_pending_signal(SIGCHLD); parent_process->add_pending_signal(SIGCHLD, {
.si_signo = SIGCHLD,
.si_code = signal ? CLD_KILLED : CLD_EXITED,
.si_errno = 0,
.si_pid = pid(),
.si_uid = m_credentials.ruid(),
.si_addr = nullptr,
.si_status = __WGENEXITCODE(status, signal),
.si_band = 0,
.si_value = {},
});
if (!parent_process->m_threads.empty()) if (!parent_process->m_threads.empty())
Processor::scheduler().unblock_thread(parent_process->m_threads.front()); Processor::scheduler().unblock_thread(parent_process->m_threads.front());
@ -328,7 +338,7 @@ namespace Kernel
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
for (auto* thread : m_threads) for (auto* thread : m_threads)
if (thread != &Thread::current()) if (thread != &Thread::current())
thread->add_signal(SIGKILL); thread->add_signal(SIGKILL, {});
} }
while (m_threads.size() > 1) while (m_threads.size() > 1)
@ -1054,7 +1064,17 @@ namespace Kernel
if (current_ns < process->m_alarm_wake_time_ns) if (current_ns < process->m_alarm_wake_time_ns)
break; break;
process->add_pending_signal(SIGALRM); process->add_pending_signal(SIGALRM, {
.si_signo = SIGALRM,
.si_code = SI_TIMER,
.si_errno = 0,
.si_pid = 0,
.si_uid = 0,
.si_addr = nullptr,
.si_status = 0,
.si_band = 0,
.si_value = {},
});
ASSERT(!process->m_threads.empty()); ASSERT(!process->m_threads.empty());
Processor::scheduler().unblock_thread(process->m_threads.front()); Processor::scheduler().unblock_thread(process->m_threads.front());
@ -2765,7 +2785,18 @@ namespace Kernel
if (!(m_signal_handlers[SIGCHLD].sa_flags & SA_NOCLDSTOP)) if (!(m_signal_handlers[SIGCHLD].sa_flags & SA_NOCLDSTOP))
{ {
parent->add_pending_signal(SIGCHLD); parent->add_pending_signal(SIGCHLD, {
.si_signo = SIGCHLD,
.si_code = stopped ? CLD_STOPPED : CLD_CONTINUED,
.si_errno = 0,
.si_pid = pid(),
.si_uid = m_credentials.ruid(),
.si_addr = nullptr,
.si_status = __WGENEXITCODE(0, signal),
.si_band = 0,
.si_value = { .sival_int = 0 },
});
if (!parent->m_threads.empty()) if (!parent->m_threads.empty())
Processor::scheduler().unblock_thread(parent->m_threads.front()); Processor::scheduler().unblock_thread(parent->m_threads.front());
} }
@ -2791,7 +2822,7 @@ namespace Kernel
} }
} }
BAN::ErrorOr<void> Process::kill(pid_t pid, int signal) BAN::ErrorOr<void> Process::kill(pid_t pid, int signal, const siginfo_t& signal_info)
{ {
if (pid == 0 || pid == -1) if (pid == 0 || pid == -1)
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
@ -2815,7 +2846,7 @@ namespace Kernel
process.set_stopped(false, signal); process.set_stopped(false, signal);
else else
{ {
process.add_pending_signal(signal); process.add_pending_signal(signal, signal_info);
if (!process.m_threads.empty()) if (!process.m_threads.empty())
Processor::scheduler().unblock_thread(process.m_threads.front()); Processor::scheduler().unblock_thread(process.m_threads.front());
process.m_stop_blocker.unblock(); process.m_stop_blocker.unblock();
@ -2837,6 +2868,18 @@ namespace Kernel
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX)) if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
const siginfo_t signal_info {
.si_signo = signal,
.si_code = SI_USER,
.si_errno = 0,
.si_pid = this->pid(),
.si_uid = m_credentials.ruid(),
.si_addr = nullptr,
.si_status = 0,
.si_band = 0,
.si_value = {},
};
if (pid == m_pid) if (pid == m_pid)
{ {
if (signal == 0) if (signal == 0)
@ -2847,13 +2890,13 @@ namespace Kernel
set_stopped(false, signal); set_stopped(false, signal);
else else
{ {
add_pending_signal(signal); add_pending_signal(signal, signal_info);
m_stop_blocker.unblock(); m_stop_blocker.unblock();
} }
return 0; return 0;
} }
TRY(kill(pid, signal)); TRY(kill(pid, signal, signal_info));
return 0; return 0;
} }
@ -3196,8 +3239,19 @@ namespace Kernel
{ {
if (thread->tid() != tid) if (thread->tid() != tid)
continue; continue;
if (signal != 0) if (signal == 0)
thread->add_signal(signal); return 0;
thread->add_signal(signal, {
.si_signo = signal,
.si_code = SI_USER,
.si_errno = 0,
.si_pid = pid(),
.si_uid = m_credentials.ruid(),
.si_addr = nullptr,
.si_status = 0,
.si_band = 0,
.si_value = {},
});
return 0; return 0;
} }

View File

@ -550,12 +550,14 @@ namespace Kernel
vaddr_t signal_handler; vaddr_t signal_handler;
{ {
SpinLockGuard _(m_process->m_signal_lock); SpinLockGuard _(m_process->m_signal_lock);
ASSERT(!(m_process->m_signal_handlers[i].sa_flags & SA_SIGINFO)); const auto& handler = m_process->m_signal_handlers[i];
signal_handler = (vaddr_t)m_process->m_signal_handlers[i].sa_handler; signal_handler = (handler.sa_flags & SA_SIGINFO)
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
: reinterpret_cast<vaddr_t>(handler.sa_handler);
} }
if (signal_handler == (vaddr_t)SIG_IGN) if (signal_handler == reinterpret_cast<vaddr_t>(SIG_IGN))
continue; continue;
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(i)) if (signal_handler == reinterpret_cast<vaddr_t>(SIG_DFL) && is_default_ignored_signal(i))
continue; continue;
return true; return true;
} }
@ -586,7 +588,7 @@ namespace Kernel
return false; return false;
} }
bool Thread::handle_signal(int signal) bool Thread::handle_signal(int signal, const siginfo_t& _signal_info)
{ {
ASSERT(&Thread::current() == this); ASSERT(&Thread::current() == this);
ASSERT(is_userspace()); ASSERT(is_userspace());
@ -596,16 +598,23 @@ namespace Kernel
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack)); auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack));
ASSERT(GDT::is_user_segment(interrupt_stack.cs)); ASSERT(GDT::is_user_segment(interrupt_stack.cs));
auto signal_info = _signal_info;
if (signal == 0) if (signal == 0)
{ {
uint64_t full_pending_mask = m_signal_pending_mask | process().signal_pending_mask(); const uint64_t process_signal_pending_mask = process().signal_pending_mask();
const uint64_t full_pending_mask = m_signal_pending_mask | process_signal_pending_mask;
for (signal = _SIGMIN; signal <= _SIGMAX; signal++) for (signal = _SIGMIN; signal <= _SIGMAX; signal++)
{ {
uint64_t mask = 1ull << signal; const uint64_t mask = 1ull << signal;
if ((full_pending_mask & mask) && !(m_signal_block_mask & mask)) if ((full_pending_mask & mask) && !(m_signal_block_mask & mask))
break; break;
} }
ASSERT(signal <= _SIGMAX); ASSERT(signal <= _SIGMAX);
if (process_signal_pending_mask & (1ull << signal))
signal_info = process().m_signal_infos[signal];
else
signal_info = m_signal_infos[signal];
} }
else else
{ {
@ -616,19 +625,20 @@ namespace Kernel
vaddr_t signal_handler; vaddr_t signal_handler;
bool has_sa_restart; bool has_sa_restart;
vaddr_t signal_stack_top = 0; vaddr_t signal_stack_top = 0;
{ {
SpinLockGuard _(m_process->m_signal_lock); SpinLockGuard _(m_process->m_signal_lock);
auto& handler = m_process->m_signal_handlers[signal]; auto& handler = m_process->m_signal_handlers[signal];
ASSERT(!(handler.sa_flags & SA_SIGINFO)); signal_handler = (handler.sa_flags & SA_SIGINFO)
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
signal_handler = reinterpret_cast<vaddr_t>(handler.sa_handler); : reinterpret_cast<vaddr_t>(handler.sa_handler);
if (handler.sa_flags & SA_RESETHAND)
handler.sa_handler = SIG_DFL;
has_sa_restart = !!(handler.sa_flags & SA_RESTART); has_sa_restart = !!(handler.sa_flags & SA_RESTART);
if (handler.sa_flags & SA_RESETHAND)
handler = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
const auto& alt_stack = m_signal_alt_stack; const auto& alt_stack = m_signal_alt_stack;
if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack()) if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack())
signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size; signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size;
@ -662,15 +672,15 @@ namespace Kernel
if (signal_stack_top == 0) if (signal_stack_top == 0)
{ {
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK; pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t)) & PAGE_ADDR_MASK; pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t) - sizeof(siginfo_t)) & PAGE_ADDR_MASK;
page_count = 2; page_count = 2;
} }
else else
{ {
pages[0] = (interrupt_stack.sp - sizeof(uintptr_t)) & PAGE_ADDR_MASK; pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t)) & PAGE_ADDR_MASK; pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK; pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t) - sizeof(siginfo_t)) & PAGE_ADDR_MASK;
page_count = 3; page_count = 3;
} }
@ -691,6 +701,16 @@ namespace Kernel
interrupt_stack.sp = signal_stack_top; interrupt_stack.sp = signal_stack_top;
write_to_stack(interrupt_stack.sp, old_stack); write_to_stack(interrupt_stack.sp, old_stack);
write_to_stack(interrupt_stack.sp, interrupt_stack.flags); write_to_stack(interrupt_stack.sp, interrupt_stack.flags);
{
signal_info.si_signo = signal;
signal_info.si_addr = reinterpret_cast<void*>(interrupt_stack.ip);
interrupt_stack.sp -= sizeof(siginfo_t);
*reinterpret_cast<siginfo_t*>(interrupt_stack.sp) = signal_info;
static_assert(sizeof(siginfo_t) % sizeof(uintptr_t) == 0);
}
write_to_stack(interrupt_stack.sp, signal); write_to_stack(interrupt_stack.sp, signal);
write_to_stack(interrupt_stack.sp, signal_handler); write_to_stack(interrupt_stack.sp, signal_handler);
interrupt_stack.ip = (uintptr_t)signal_trampoline; interrupt_stack.ip = (uintptr_t)signal_trampoline;
@ -728,25 +748,29 @@ namespace Kernel
return has_sa_restart; return has_sa_restart;
} }
void Thread::add_signal(int signal) void Thread::add_signal(int signal, const siginfo_t& info)
{ {
SpinLockGuard _(m_signal_lock); SpinLockGuard _(m_signal_lock);
if (m_process) if (m_process)
{ {
vaddr_t signal_handler; vaddr_t signal_handler;
{ {
SpinLockGuard _(m_process->m_signal_lock); SpinLockGuard _(m_process->m_signal_lock);
ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO)); const auto& handler = m_process->m_signal_handlers[signal];
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler; signal_handler = (handler.sa_flags & SA_SIGINFO)
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
: reinterpret_cast<vaddr_t>(handler.sa_handler);
} }
if (signal_handler == (vaddr_t)SIG_IGN) if (signal_handler == reinterpret_cast<vaddr_t>(SIG_IGN))
return; return;
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(signal)) if (signal_handler == reinterpret_cast<vaddr_t>(SIG_DFL) && is_default_ignored_signal(signal))
return; return;
} }
const uint64_t mask = 1ull << signal; const uint64_t mask = 1ull << signal;
m_signal_pending_mask |= mask; m_signal_pending_mask |= mask;
m_signal_infos[signal] = info;
if (this != &Thread::current()) if (this != &Thread::current())
Processor::scheduler().unblock_thread(this); Processor::scheduler().unblock_thread(this);

View File

@ -152,15 +152,15 @@ typedef struct
enum enum
{ {
#if defined(__x86_64__) #if defined(__x86_64__)
REG_RIP,
REG_RSP,
REG_RBP,
REG_RAX, REG_RAX,
REG_RBX, REG_RBX,
REG_RCX, REG_RCX,
REG_RDX, REG_RDX,
REG_RDI, REG_RDI,
REG_RSI, REG_RSI,
REG_RSP,
REG_RBP,
REG_RIP,
REG_R8, REG_R8,
REG_R9, REG_R9,
REG_R10, REG_R10,
@ -170,15 +170,15 @@ enum
REG_R14, REG_R14,
REG_R15, REG_R15,
#elif defined(__i686__) #elif defined(__i686__)
REG_EIP,
REG_ESP,
REG_EBP,
REG_EAX, REG_EAX,
REG_EBX, REG_EBX,
REG_ECX, REG_ECX,
REG_EDX, REG_EDX,
REG_EDI, REG_EDI,
REG_ESI, REG_ESI,
REG_ESP,
REG_EBP,
REG_EIP,
#else #else
#error #error
#endif #endif