Kernel/LibC/DynamicLoader: Update process start ABI

We now use SysV abi for process startup
This commit is contained in:
2025-04-15 23:04:20 +03:00
parent e6026cb0b8
commit 36baf7b0af
12 changed files with 314 additions and 280 deletions

View File

@@ -2,18 +2,22 @@
.global _start
_start:
pushl $0
# get argc, argv, envp
movl (%esp), %edi
leal 4(%esp), %esi
leal 4(%esi, %edi, 4), %edx
# align stack
andl $-16, %esp
xorl %ebp, %ebp
# save argc, argv, envp
subl $4, %esp
pushl %edx
pushl %esi
pushl %edi
# STACK LAYOUT
# null
# argc
# argv
# envp
xorl %ebp, %ebp
subl $4, %esp
pushl $__fini_array_end
pushl $__fini_array_start

View File

@@ -2,21 +2,22 @@
.global _start
_start:
pushq $0
# get argc, argv, envp
movq (%rsp), %rdi
leaq 8(%rsp), %rsi
leaq 8(%rsi, %rdi, 8), %rdx
# align stack
andq $-16, %rsp
xorq %rbp, %rbp
# save argc, argv, envp
subq $8, %rsp
pushq %rdi
pushq %rsi
pushq %rdx
# STACK LAYOUT
# null
# argc
# argv
# envp
xorq %rbp, %rbp
# init libc
movq 0(%rsp), %rdi
movq %rdx, %rdi # environ
pushq $__fini_array_end
pushq $__fini_array_start
@@ -31,9 +32,10 @@ _start:
addq $(6 * 8), %rsp
# call main
movq 16(%rsp), %rdi
movq 8(%rsp), %rsi
movq 0(%rsp), %rdx
popq %rdx
popq %rsi
popq %rdi
addq $8, %rsp
call main
# call exit

View File

@@ -2,6 +2,8 @@
#include <BAN/Atomic.h>
#include <BAN/PlacementNew.h>
#include <kernel/Arch.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
@@ -16,15 +18,30 @@ struct pthread_trampoline_info_t
};
// stack is 16 byte aligned on entry, this `call` is used to align it
extern "C" void pthread_trampoline(void*);
asm("pthread_trampoline: call pthread_trampoline_cpp");
extern "C" void _pthread_trampoline(void*);
asm(
#if ARCH(x86_64)
"_pthread_trampoline:"
"popq %rdi;"
"andq $-16, %rsp;"
"xorq %rbp, %rbp;"
"call _pthread_trampoline_cpp"
#elif ARCH(i686)
"_pthread_trampoline:"
"ud2;"
"popl %edi;"
"andl $-16, %esp;"
"xorl %ebp, %ebp;"
"subl $12, %esp;"
"pushl %edi;"
"call _pthread_trampoline_cpp"
#endif
);
extern "C" void pthread_trampoline_cpp(void* arg)
extern "C" void _pthread_trampoline_cpp(void* arg)
{
pthread_trampoline_info_t info;
memcpy(&info, arg, sizeof(pthread_trampoline_info_t));
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
free(arg);
pthread_exit(info.start_routine(info.arg));
ASSERT_NOT_REACHED();
}
@@ -63,24 +80,30 @@ void pthread_cleanup_push(void (*routine)(void*), void* arg)
s_cleanup_stack = cleanup;
}
int pthread_create(pthread_t* __restrict thread, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
{
auto* info = static_cast<pthread_trampoline_info_t*>(malloc(sizeof(pthread_trampoline_info_t)));
if (info == nullptr)
return -1;
info->start_routine = start_routine;
info->arg = arg;
return errno;
*info = {
.start_routine = start_routine,
.arg = arg,
};
const auto ret = syscall(SYS_PTHREAD_CREATE, attr, pthread_trampoline, info);
if (ret == -1)
{
free(info);
return -1;
}
goto pthread_create_error;
if (thread)
*thread = ret;
if (thread_id)
*thread_id = ret;
return 0;
pthread_create_error:
const int return_code = errno;
free(info);
return return_code;
}
void pthread_exit(void* value_ptr)

View File

@@ -1,5 +1,6 @@
#include "utils.h"
#include <LibELF/AuxiliaryVector.h>
#include <LibELF/Types.h>
#include <LibELF/Values.h>
@@ -15,42 +16,44 @@ void _start()
{
#if defined(__x86_64__)
asm volatile(
"xorq %rbp, %rbp;"
"movq (%rsp), %rdi;"
"leaq 8(%rsp), %rsi;"
"leaq 8(%rsi, %rdi, 8), %rdx;"
"movq %rsp, %rbp;"
"andq $-16, %rsp;"
"call _entry;"
"movq %rbp, %rsp;"
"xorq %rbp, %rbp;"
"jmp *%rax;"
"ud2;"
);
#elif defined(__i686__)
asm volatile(
"xorl %ebp, %ebp;"
"pushl %ecx;"
"movl (%esp), %edi;"
"leal 4(%esp), %esi;"
"leal 4(%esi, %edi, 4), %edx;"
"movl %esp, %ebp;"
"andl $-16, %esp;"
"subl $4, %esp;"
"pushl %edx;"
"pushl %esi;"
"pushl %edi;"
"call _entry;"
"ud2;"
);
#else
#error "unsupported architecture"
#endif
}
__attribute__((naked, noreturn))
static void call_entry_point(int, char**, char**, uintptr_t)
{
#if defined(__x86_64__)
asm volatile(
"andq $-16, %rsp;"
"jmp *%rcx;"
);
#elif defined(__i686__)
asm volatile(
"addl $4, %esp;"
"popl %edi;"
"popl %esi;"
"popl %edx;"
"popl %ecx;"
"andl $-16, %esp;"
"jmp *%ecx;"
"call _entry;"
"movl %ebp, %esp;"
"xorl %ebp, %ebp;"
"jmp *%eax;"
"ud2;"
);
#else
#error "unsupported architecture"
@@ -901,16 +904,33 @@ static void call_init_funcs(LoadedElf& elf, bool is_main_elf)
reinterpret_cast<init_t>(elf.init)();
for (size_t i = 0; i < elf.init_arraysz / sizeof(init_t); i++)
reinterpret_cast<init_t*>(elf.init_array)[i]();
}
static LibELF::AuxiliaryVector* find_auxv(char** envp)
{
if (envp == nullptr)
return nullptr;
char** null_env = envp;
while (*null_env)
null_env++;
return reinterpret_cast<LibELF::AuxiliaryVector*>(null_env + 1);
}
extern "C"
__attribute__((used, noreturn))
int _entry(int argc, char** argv, char** envp, int fd)
__attribute__((used))
uintptr_t _entry(int argc, char* argv[], char* envp[])
{
const bool invoked_directly = (fd < 0);
if (invoked_directly)
int execfd = -1;
if (auto* auxv = find_auxv(envp))
for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++)
if (aux->a_type == LibELF::AT_EXECFD) {
execfd = aux->a_un.a_val;
aux->a_type = LibELF::AT_IGNORE;
}
if (execfd == -1)
{
if (argc < 2)
print_error_and_exit("missing program name", 0);
@@ -918,18 +938,19 @@ int _entry(int argc, char** argv, char** envp, int fd)
argc--;
argv++;
fd = syscall(SYS_OPENAT, AT_FDCWD, argv[0], O_RDONLY);
if (fd < 0)
print_error_and_exit("could not open program", fd);
execfd = syscall(SYS_OPENAT, AT_FDCWD, argv[0], O_RDONLY);
if (execfd < 0)
print_error_and_exit("could not open program", execfd);
}
init_random();
auto& elf = load_elf(argv[0], fd);
auto& elf = load_elf(argv[0], execfd);
syscall(SYS_CLOSE, fd);
fini_random();
relocate_elf(elf, true);
initialize_environ(envp);
call_init_funcs(elf, true);
call_entry_point(argc, argv, envp, elf.base + elf.file_header.e_entry);
return elf.base + elf.file_header.e_entry;
}