* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "x86_signals.h"
#include <string.h>
#include <KernelExport.h>
#include <commpage.h>
#include <cpu.h>
#include <elf.h>
#include <smp.h>
#include "syscall_numbers.h"
extern "C" void x86_signal_frame_function_beos(signal_frame_data* frameData);
extern "C" void
x86_signal_frame_function(signal_frame_data* frameData)
{
if (frameData->siginfo_handler) {
void (*handler)(int, siginfo_t*, void*, void*)
= (void (*)(int, siginfo_t*, void*, void*))frameData->handler;
handler(frameData->info.si_signo, &frameData->info,
&frameData->context, frameData->user_data);
} else {
void (*handler)(int, void*, vregs*)
= (void (*)(int, void*, vregs*))frameData->handler;
handler(frameData->info.si_signo, frameData->user_data,
&frameData->context.uc_mcontext);
}
#define TO_STRING_LITERAL_HELPER(number) #number
#define TO_STRING_LITERAL(number) TO_STRING_LITERAL_HELPER(number)
asm volatile(
"pushl %0;"
"pushl $0;"
"movl $" TO_STRING_LITERAL(SYSCALL_RESTORE_SIGNAL_FRAME) ", %%eax;"
"int $99;"
:: "r"(frameData)
);
#undef TO_STRING_LITERAL_HELPER
#undef TO_STRING_LITERAL
}
static void
register_signal_handler_function(const char* functionName, int32 commpageIndex,
const char* commpageSymbolName, addr_t expectedAddress)
{
elf_symbol_info symbolInfo;
if (elf_lookup_kernel_symbol(functionName, &symbolInfo)
!= B_OK) {
panic("x86_initialize_commpage_signal_handler(): Failed to find "
"signal frame function \"%s\"!", functionName);
}
ASSERT(expectedAddress == symbolInfo.address);
addr_t position = fill_commpage_entry(commpageIndex,
(void*)symbolInfo.address, symbolInfo.size);
image_id image = get_commpage_image();
elf_add_memory_image_symbol(image, commpageSymbolName, position,
symbolInfo.size, B_SYMBOL_TYPE_TEXT);
}
void
x86_initialize_commpage_signal_handler()
{
register_signal_handler_function("x86_signal_frame_function",
COMMPAGE_ENTRY_X86_SIGNAL_HANDLER, "commpage_signal_handler",
(addr_t)&x86_signal_frame_function);
register_signal_handler_function("x86_signal_frame_function_beos",
COMMPAGE_ENTRY_X86_SIGNAL_HANDLER_BEOS, "commpage_signal_handler_beos",
(addr_t)&x86_signal_frame_function_beos);
}
addr_t
x86_get_user_signal_handler_wrapper(bool beosHandler, void* commPageAdddress)
{
int32 index = beosHandler
? COMMPAGE_ENTRY_X86_SIGNAL_HANDLER_BEOS
: COMMPAGE_ENTRY_X86_SIGNAL_HANDLER;
return ((addr_t*)commPageAdddress)[index] + (addr_t)commPageAdddress;
}