mirror of
https://review.haiku-os.org/haiku
synced 2025-01-31 18:56:49 +01:00
Fix initial stack alignment on 64-bit systems.
gcc does re-align the stack in the main() function prologue, however, we still need to set the right alignment for other cases: thread entry, .init and .fini code that is executed before main() is called or after it has returned, and signal handlers which may use a separate stack. Part of #10509
This commit is contained in:
parent
34cdda1dd5
commit
13daa9299e
@ -101,12 +101,16 @@ arch_randomize_stack_pointer(addr_t value)
|
||||
static_assert(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1,
|
||||
"randomization range is too big");
|
||||
value -= random_value() & (B_PAGE_SIZE - 1);
|
||||
return value & ~addr_t(0xf);
|
||||
return (value & ~addr_t(0xf)) - 8;
|
||||
// This means, result % 16 == 8, which is what rsp should adhere to
|
||||
// when a function is entered for the stack to be considered aligned to
|
||||
// 16 byte.
|
||||
}
|
||||
|
||||
|
||||
static uint8*
|
||||
get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action)
|
||||
get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action,
|
||||
size_t spaceNeeded)
|
||||
{
|
||||
// Use the alternate signal stack if we should and can.
|
||||
if (thread->signal_stack_enabled
|
||||
@ -115,14 +119,15 @@ get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action)
|
||||
|| frame->user_sp >= thread->signal_stack_base
|
||||
+ thread->signal_stack_size)) {
|
||||
addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size;
|
||||
return (uint8*)arch_randomize_stack_pointer(stackTop);
|
||||
return (uint8*)arch_randomize_stack_pointer(stackTop - spaceNeeded);
|
||||
}
|
||||
|
||||
// We are going to use the stack that we are already on. We must not touch
|
||||
// the red zone (128 byte area below the stack pointer, reserved for use
|
||||
// by functions to store temporary data and guaranteed not to be modified
|
||||
// by signal handlers).
|
||||
return (uint8*)(frame->user_sp - 128);
|
||||
return (uint8*)((frame->user_sp - 128 - spaceNeeded) & ~addr_t(0xf)) - 8;
|
||||
// align stack pointer (cf. arch_randomize_stack_pointer())
|
||||
}
|
||||
|
||||
|
||||
@ -207,19 +212,19 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
|
||||
void* args2)
|
||||
{
|
||||
addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
|
||||
addr_t codeAddr;
|
||||
|
||||
TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
|
||||
"stackTop %#lx\n", entry, args1, args2, stackTop);
|
||||
|
||||
stackTop = arch_randomize_stack_pointer(stackTop);
|
||||
stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr));
|
||||
|
||||
// Copy the address of the stub that calls exit_thread() when the thread
|
||||
// entry function returns to the top of the stack to act as the return
|
||||
// address. The stub is inside commpage.
|
||||
addr_t commPageAddress = (addr_t)thread->team->commpage_address;
|
||||
addr_t codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
|
||||
codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
|
||||
+ commPageAddress;
|
||||
stackTop -= sizeof(codeAddr);
|
||||
if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
|
||||
!= B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
@ -315,10 +320,11 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action,
|
||||
signalFrameData->syscall_restart_return_value = frame->orig_rax;
|
||||
|
||||
// Get the stack to use and copy the frame data to it.
|
||||
uint8* userStack = get_signal_stack(thread, frame, action);
|
||||
uint8* userStack = get_signal_stack(thread, frame, action,
|
||||
sizeof(*signalFrameData) + sizeof(frame->ip));
|
||||
|
||||
userStack -= sizeof(*signalFrameData);
|
||||
signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack;
|
||||
signal_frame_data* userSignalFrameData
|
||||
= (signal_frame_data*)(userStack + sizeof(frame->ip));
|
||||
|
||||
if (user_memcpy(userSignalFrameData, signalFrameData,
|
||||
sizeof(*signalFrameData)) != B_OK) {
|
||||
@ -326,7 +332,6 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action,
|
||||
}
|
||||
|
||||
// Copy a return address to the stack so that backtraces will be correct.
|
||||
userStack -= sizeof(frame->ip);
|
||||
if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user