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:
committed by
Adrien Destugues
parent
34cdda1dd5
commit
13daa9299e
@@ -101,12 +101,16 @@ arch_randomize_stack_pointer(addr_t value)
|
|||||||
static_assert(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1,
|
static_assert(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1,
|
||||||
"randomization range is too big");
|
"randomization range is too big");
|
||||||
value -= random_value() & (B_PAGE_SIZE - 1);
|
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*
|
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.
|
// Use the alternate signal stack if we should and can.
|
||||||
if (thread->signal_stack_enabled
|
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
|
|| frame->user_sp >= thread->signal_stack_base
|
||||||
+ thread->signal_stack_size)) {
|
+ thread->signal_stack_size)) {
|
||||||
addr_t stackTop = 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
|
// 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
|
// 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 functions to store temporary data and guaranteed not to be modified
|
||||||
// by signal handlers).
|
// 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)
|
void* args2)
|
||||||
{
|
{
|
||||||
addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
|
addr_t stackTop = thread->user_stack_base + thread->user_stack_size;
|
||||||
|
addr_t codeAddr;
|
||||||
|
|
||||||
TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
|
TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
|
||||||
"stackTop %#lx\n", entry, args1, args2, stackTop);
|
"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
|
// 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
|
// entry function returns to the top of the stack to act as the return
|
||||||
// address. The stub is inside commpage.
|
// address. The stub is inside commpage.
|
||||||
addr_t commPageAddress = (addr_t)thread->team->commpage_address;
|
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;
|
+ commPageAddress;
|
||||||
stackTop -= sizeof(codeAddr);
|
|
||||||
if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
|
if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
|
||||||
!= B_OK)
|
!= B_OK)
|
||||||
return B_BAD_ADDRESS;
|
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;
|
signalFrameData->syscall_restart_return_value = frame->orig_rax;
|
||||||
|
|
||||||
// Get the stack to use and copy the frame data to it.
|
// 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* userSignalFrameData = (signal_frame_data*)userStack;
|
= (signal_frame_data*)(userStack + sizeof(frame->ip));
|
||||||
|
|
||||||
if (user_memcpy(userSignalFrameData, signalFrameData,
|
if (user_memcpy(userSignalFrameData, signalFrameData,
|
||||||
sizeof(*signalFrameData)) != B_OK) {
|
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.
|
// 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)
|
if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user