mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[ld.so] Properly handle stack alignment in ld.so args
Now when loading a process, init will push all the loader args, align the stack so that the next pointer will have correct alignment, then push a pointer to the loader args. Also: * _ldso_start will pop all loader args off of the stack before jumping to the loaded program's entrypoint, as if it had never run. * The sentinel arg structures have a size instead of being all zeros, so that they can be popped off properly when done.
This commit is contained in:
@@ -43,7 +43,6 @@ struct j6_arg_loader
|
||||
uintptr_t *got;
|
||||
uintptr_t entrypoint;
|
||||
uintptr_t start_addr;
|
||||
uintptr_t other;
|
||||
};
|
||||
|
||||
struct j6_arg_driver
|
||||
|
||||
@@ -17,10 +17,12 @@ _ldso_start:
|
||||
; Call ldso_init with the loader-provided stack data and
|
||||
; also the address of the GOT, since clang refuses to take
|
||||
; the address of it, only dereference it.
|
||||
mov rdi, rbp
|
||||
mov rdi, [rbp]
|
||||
lea rsi, [rel _GLOBAL_OFFSET_TABLE_]
|
||||
call ldso_init
|
||||
; The real program's entrypoint is now in rax
|
||||
|
||||
; The real program's entrypoint is now in rax, save it to r11
|
||||
mov r11, rax
|
||||
|
||||
; Put the function call params back
|
||||
pop r9
|
||||
@@ -30,7 +32,19 @@ _ldso_start:
|
||||
pop rsi
|
||||
pop rdi
|
||||
|
||||
jmp rax
|
||||
; Pop all the loader args
|
||||
pop rsp ; Point the stack at the first arg
|
||||
mov rax, 0
|
||||
mov rbx, 0
|
||||
.poploop:
|
||||
mov eax, [dword rsp] ; size
|
||||
mov ebx, [dword rsp+4] ; type
|
||||
add rsp, rax
|
||||
cmp ebx, 0
|
||||
jne .poploop
|
||||
|
||||
mov rbp, rsp
|
||||
jmp r11
|
||||
.end:
|
||||
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ stack_push_sentinel(uint8_t *&stack)
|
||||
memset(stack, 0, size);
|
||||
j6_arg_header *header = reinterpret_cast<j6_arg_header*>(stack);
|
||||
header->type = j6_arg_type_none;
|
||||
header->size = 0;
|
||||
header->size = size;
|
||||
}
|
||||
|
||||
template <typename T> T *
|
||||
@@ -222,6 +222,7 @@ load_program(
|
||||
uintptr_t entrypoint = program_elf.entrypoint() + program_image_base;
|
||||
|
||||
if (dyn) {
|
||||
stack_push_sentinel(stack);
|
||||
j6_arg_loader *loader_arg = stack_push<j6_arg_loader>(stack, 0);
|
||||
const elf::file_header *h = program_elf.header();
|
||||
loader_arg->image_base = program_image_base;
|
||||
@@ -240,6 +241,15 @@ load_program(
|
||||
handles_arg->handles[1].handle = vfs;
|
||||
handles_arg->handles[1].proto = j6::proto::vfs::id;
|
||||
|
||||
// Align the stack to be one word short of 16-byte aligned, so
|
||||
// that the arg address will be aligned when pushed
|
||||
while ((reinterpret_cast<uintptr_t>(stack) & 0xf) != 0x8) --stack;
|
||||
|
||||
// Push the args list address itself
|
||||
stack -= sizeof(uintptr_t);
|
||||
uintptr_t *args_addr = reinterpret_cast<uintptr_t*>(stack);
|
||||
*args_addr = stack_top - (stack_orig - reinterpret_cast<uint8_t*>(handles_arg));
|
||||
|
||||
uintptr_t ldso_image_base = (eop & ~(MiB-1)) + MiB;
|
||||
|
||||
for (auto seg : program_elf.segments()) {
|
||||
|
||||
Reference in New Issue
Block a user