mirror of https://github.com/flysand7/ciabatta.git
switch stacks
This commit is contained in:
parent
653342a30a
commit
d8dc35c083
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
bits 64
|
||||||
|
|
||||||
|
section .text
|
||||||
|
global ld_stack_trampoline
|
||||||
|
|
||||||
|
; DESCRIPTION:
|
||||||
|
; This function copies the current stack down from RSP to the top of the stack
|
||||||
|
; into a memory region provided in parameter
|
||||||
|
; After the stack has been copied, we jump into ld_stage3_entry
|
||||||
|
; PARAMS:
|
||||||
|
; RDI (u64) - dst stack base
|
||||||
|
; RSI (u64) - src stack base
|
||||||
|
; RDX (u64) - dst stack size
|
||||||
|
; RCX (u64) - src stack size
|
||||||
|
; R8 (u64) - function to call
|
||||||
|
; R9 (u64) - param to pass to function
|
||||||
|
; RETURNS:
|
||||||
|
; guess what, it doesn't
|
||||||
|
ld_stack_trampoline:
|
||||||
|
; Calculate the amount of memory we need to move to the new stack
|
||||||
|
add rcx, rsi
|
||||||
|
sub rcx, rsp
|
||||||
|
; Calculate the base of the source memory
|
||||||
|
mov rsi, rsp
|
||||||
|
; Check to see if the amount we're about to move is less than dst stack size
|
||||||
|
cmp rcx, rdx
|
||||||
|
jl .continue
|
||||||
|
xor rdi, rdi
|
||||||
|
mov rsi, r9
|
||||||
|
mov rax, r8
|
||||||
|
call rax
|
||||||
|
.continue:
|
||||||
|
; Save rsi, rdi, rcx on stack
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rcx
|
||||||
|
; copy stack
|
||||||
|
shr rcx, 3
|
||||||
|
rep movsq
|
||||||
|
; get back our regs
|
||||||
|
pop rcx
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
; We copied the stack at this point, lets switch
|
||||||
|
add rsp, rdi
|
||||||
|
sub rsp, rsi
|
||||||
|
add rsp, rdx
|
||||||
|
sub rsp, rcx
|
||||||
|
; We should have the new stack now, which is an exact copy of the old stack
|
||||||
|
and rsp, -16
|
||||||
|
mov rdi, 1
|
||||||
|
mov rsi, r9
|
||||||
|
mov rax, r8
|
||||||
|
call rax
|
3
build.py
3
build.py
|
@ -144,7 +144,8 @@ if loader_debugging_enabled:
|
||||||
cc_defines.append('_CIA_LD_DEBUG')
|
cc_defines.append('_CIA_LD_DEBUG')
|
||||||
print_step("Building lib/ld-cia.so\n")
|
print_step("Building lib/ld-cia.so\n")
|
||||||
assemble_obj('bin/loader-entry.o', [f'arch/{target_abi}_{target_arch}/loader-entry.asm'], ['-f "elf64"'])
|
assemble_obj('bin/loader-entry.o', [f'arch/{target_abi}_{target_arch}/loader-entry.asm'], ['-f "elf64"'])
|
||||||
compile_shared('lib/ld-cia.so', ['bin/loader-entry.o','loader/loader-self-reloc.c','loader/loader.c'])
|
assemble_obj('bin/loader-trampoline.o', [f'arch/{target_abi}_{target_arch}/loader-trampoline.asm'], ['-f "elf64"'])
|
||||||
|
compile_shared('lib/ld-cia.so', ['bin/loader-entry.o','loader/loader-self-reloc.c','loader/loader.c','bin/loader-trampoline.o'])
|
||||||
cc_defines_pop()
|
cc_defines_pop()
|
||||||
cc_flags_pop()
|
cc_flags_pop()
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,27 @@
|
||||||
// are fine with gcc and clang (I think))
|
// are fine with gcc and clang (I think))
|
||||||
|
|
||||||
#include <cia/def.h>
|
#include <cia/def.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <bin/elf.h>
|
#include <bin/elf.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <stdarg.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
|
|
||||||
extern void loader_entry(Loader_Info *ld_info);
|
extern void ld_stage2_entry(Loader_Info *ld_info);
|
||||||
|
|
||||||
void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) {
|
void ld_stage1_entry(u64 *sp, Elf64_Dyn *dynv) {
|
||||||
_dbg_print_string("Entered dynamic loader\n");
|
_dbg_print_string("Entered dynamic loader\n");
|
||||||
// Find argc, argv in stack
|
// Find argc, argv in stack
|
||||||
int argc = *sp;
|
int argc = *sp;
|
||||||
char **argv = (void *)(sp+1);
|
char **argv = (void *)(sp+1);
|
||||||
|
_dbg_printf("ARGV:\n");
|
||||||
|
for(int i = 0; i < argc; ++i) {
|
||||||
|
_dbg_printf("[%d]: %s\n", (i64)i, argv[i]);
|
||||||
|
}
|
||||||
// Skip over environment
|
// Skip over environment
|
||||||
char **envp = argv+argc+1;
|
char **envp = argv+argc+1;
|
||||||
int envc = 0;
|
int envc = 0;
|
||||||
|
@ -173,7 +182,6 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) {
|
||||||
}
|
}
|
||||||
rela_offs += rela_ent;
|
rela_offs += rela_ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
_mfence();
|
_mfence();
|
||||||
Loader_Info ld_info;
|
Loader_Info ld_info;
|
||||||
|
@ -182,7 +190,7 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) {
|
||||||
ld_info.dyn = dyn;
|
ld_info.dyn = dyn;
|
||||||
ld_info.aux = aux;
|
ld_info.aux = aux;
|
||||||
_dbg_printf("Self-relocation finished. Entering the loader\n");
|
_dbg_printf("Self-relocation finished. Entering the loader\n");
|
||||||
loader_entry(&ld_info);
|
ld_stage2_entry(&ld_info);
|
||||||
sys_exit(0);
|
sys_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ struct Elf_Image {
|
||||||
#define elf_addr(elf, off) (void *)((elf)->base + (u64)off)
|
#define elf_addr(elf, off) (void *)((elf)->base + (u64)off)
|
||||||
|
|
||||||
static Cia_Pool image_pool;
|
static Cia_Pool image_pool;
|
||||||
|
static Cia_Arena tmp_arena;
|
||||||
|
|
||||||
static u32 elf_sym_gnu_hash(char *name) {
|
static u32 elf_sym_gnu_hash(char *name) {
|
||||||
unsigned char *s = (void *)name;
|
unsigned char *s = (void *)name;
|
||||||
|
@ -91,7 +92,24 @@ static Elf64_Sym *elf_symbol_by_name(Elf_Image *image, char *name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loader_entry(Loader_Info *ld_info) {
|
struct Stage3_Info_Struct typedef Stage3_Info_Struct;
|
||||||
|
struct Stage3_Info_Struct {
|
||||||
|
Elf_Image *app;
|
||||||
|
Elf_Image *ldso;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ld_stage3_entry(u64 has_new_stack, void *ctx);
|
||||||
|
|
||||||
|
void ld_stack_trampoline(
|
||||||
|
void *stack_base
|
||||||
|
, void *old_stack_base
|
||||||
|
, u64 stack_size
|
||||||
|
, u64 old_stack_size
|
||||||
|
, void (*fn)(u64 has_new_stack, void *ctx)
|
||||||
|
, void *ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
void ld_stage2_entry(Loader_Info *ld_info) {
|
||||||
_dbg_printf("Loader entry point reached!\n");
|
_dbg_printf("Loader entry point reached!\n");
|
||||||
// Get our loader data back
|
// Get our loader data back
|
||||||
u64 *sp = ld_info->sp;
|
u64 *sp = ld_info->sp;
|
||||||
|
@ -101,7 +119,11 @@ void loader_entry(Loader_Info *ld_info) {
|
||||||
cia_pool_create(&image_pool, cia_allocator_pages(), 1*KB, sizeof(Elf_Image), 0x10);
|
cia_pool_create(&image_pool, cia_allocator_pages(), 1*KB, sizeof(Elf_Image), 0x10);
|
||||||
Elf_Image *ldso = cia_pool_alloc(&image_pool);
|
Elf_Image *ldso = cia_pool_alloc(&image_pool);
|
||||||
Elf_Image *app = cia_pool_alloc(&image_pool);
|
Elf_Image *app = cia_pool_alloc(&image_pool);
|
||||||
cia_arena_create(&app->arena, cia_allocator_pages(), 1*MB);
|
// Save some stuff for stage3 to eat
|
||||||
|
cia_arena_create(&tmp_arena, cia_allocator_pages(), 1*MB);
|
||||||
|
Stage3_Info_Struct *stage3 = cia_arena_alloc(&tmp_arena, sizeof(Stage3_Info_Struct));
|
||||||
|
stage3->app = app;
|
||||||
|
stage3->ldso = ldso;
|
||||||
ldso->base = ldso_base;
|
ldso->base = ldso_base;
|
||||||
ldso->dyn = dyn;
|
ldso->dyn = dyn;
|
||||||
// Read ldso elf header
|
// Read ldso elf header
|
||||||
|
@ -150,14 +172,6 @@ void loader_entry(Loader_Info *ld_info) {
|
||||||
if(fd != 0) {
|
if(fd != 0) {
|
||||||
sys_close(fd);
|
sys_close(fd);
|
||||||
}
|
}
|
||||||
// Get the information about the main thread stack
|
|
||||||
if(linux_read_stack_info()) {
|
|
||||||
printf("ERROR: failed to read /proc/self/maps to get the stack info\n");
|
|
||||||
sys_exit(1);
|
|
||||||
}
|
|
||||||
_dbg_printf("Received stack: %x-%x\n", stack_info.start_addr, stack_info.end_addr);
|
|
||||||
u64 *ptr = (void *)stack_info.start_addr;
|
|
||||||
// *ptr = 1245;
|
|
||||||
// Find .dynamic section
|
// Find .dynamic section
|
||||||
{
|
{
|
||||||
u8 *phdr = (void *)aux[AT_PHDR];
|
u8 *phdr = (void *)aux[AT_PHDR];
|
||||||
|
@ -281,9 +295,32 @@ void loader_entry(Loader_Info *ld_info) {
|
||||||
// Get the app main
|
// Get the app main
|
||||||
// Elf64_Sym *app_main = elf_symbol_by_name(app, "main");
|
// Elf64_Sym *app_main = elf_symbol_by_name(app, "main");
|
||||||
// _dbg_printf("app main: %x\n", app_main);
|
// _dbg_printf("app main: %x\n", app_main);
|
||||||
void (*crt_entry)() = elf_addr(app, eh->e_entry);
|
// Get the information about the main thread stack
|
||||||
_dbg_printf("Exiting the dynamic loader, trying to enter the main app\n");
|
if(linux_read_stack_info()) {
|
||||||
crt_entry();
|
printf("ERROR: failed to read /proc/self/maps to get the stack info\n");
|
||||||
|
sys_exit(1);
|
||||||
|
}
|
||||||
|
_dbg_printf("Found default stack at: %x-%x\n", stack_info.start_addr, stack_info.end_addr);
|
||||||
|
void *old_stack_base = (void *)stack_info.start_addr;
|
||||||
|
u64 old_stack_size = (u64)stack_info.end_addr - (u64)stack_info.start_addr;
|
||||||
|
u64 stack_size = 0x10000;
|
||||||
|
void *stack_base = sys_mmap(0, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0);
|
||||||
|
_dbg_printf("stage3 info struct: %x\n", stage3);
|
||||||
|
// Will jump to ld_stage3_entry
|
||||||
|
ld_stack_trampoline(stack_base, old_stack_base, stack_size, old_stack_size, &ld_stage3_entry, stage3);
|
||||||
}
|
}
|
||||||
sys_exit(0);
|
sys_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ld_stage3_entry(u64 has_new_stack, void *ctx) {
|
||||||
|
if(!has_new_stack) {
|
||||||
|
printf("ERROR: failed to switch the stack\n");
|
||||||
|
sys_exit(1);
|
||||||
|
}
|
||||||
|
Stage3_Info_Struct *info = ctx;
|
||||||
|
_dbg_printf("Entered loader stage 3. Try entering main executable\n");
|
||||||
|
_dbg_printf("stage3 info struct: %x\n", info);
|
||||||
|
void (*crt_entry)() = elf_addr(info->app, ((Elf64_Ehdr *)info->app->base)->e_entry);
|
||||||
|
_dbg_printf("Entry at: %x\n", crt_entry);
|
||||||
|
crt_entry();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue