Crude argument passing, added hex dump as demo program
This commit is contained in:
@@ -21,6 +21,9 @@ struct thread {
|
||||
__plat_thread data;
|
||||
|
||||
struct image_info image;
|
||||
// Arguments are stored here
|
||||
uintptr_t argp_page;
|
||||
uintptr_t argp_page_phys;
|
||||
|
||||
uint64_t flags;
|
||||
uint32_t pid;
|
||||
|
||||
+52
-1
@@ -1,6 +1,7 @@
|
||||
#include "sys/amd64/mm/mm.h"
|
||||
#include "sys/amd64/mm/phys.h"
|
||||
#include "sys/amd64/mm/pool.h"
|
||||
#include "sys/amd64/mm/map.h"
|
||||
#include "sys/binfmt_elf.h"
|
||||
#include "sys/amd64/cpu.h"
|
||||
#include "sys/assert.h"
|
||||
@@ -52,6 +53,14 @@ int thread_init(
|
||||
t->data.data_flags |= 2 /* Don't free ustack */;
|
||||
}
|
||||
|
||||
if (!(flags & THREAD_KERNEL)) {
|
||||
_assert((t->argp_page_phys = amd64_phys_alloc_page()) != MM_NADDR);
|
||||
t->argp_page = 0x100000000;
|
||||
_assert(!amd64_map_single(space, t->argp_page, t->argp_page_phys, 1 | (1 << 1) | (1 << 2)));
|
||||
} else {
|
||||
t->argp_page = MM_NADDR;
|
||||
}
|
||||
|
||||
t->data.stack0_base = rsp0_base;
|
||||
t->data.stack0_size = rsp0_size;
|
||||
t->data.rsp0 = t->data.stack0_base + t->data.stack0_size - sizeof(struct cpu_context);
|
||||
@@ -61,7 +70,6 @@ int thread_init(
|
||||
t->data.stack3_size = rsp3_size;
|
||||
}
|
||||
|
||||
|
||||
// Alloc signal handling kstack
|
||||
void *kstack_sig = kmalloc(THREAD_KSTACK_SIZE);
|
||||
_assert(kstack_sig);
|
||||
@@ -206,6 +214,36 @@ int sys_execve(const char *filename, const char *const argv[], const char *const
|
||||
|
||||
mm_space_t space = thr->space;
|
||||
|
||||
// Buffer page used for argp construction
|
||||
// Before we released the old memory, copy
|
||||
// the needed stuff from it
|
||||
uintptr_t argp_page_phys = amd64_phys_alloc_page();
|
||||
_assert(argp_page_phys != MM_NADDR);
|
||||
char **dst_argp = (char **) MM_VIRTUALIZE(argp_page_phys);
|
||||
size_t argp_offset = 0, argp_offset2 = 0;
|
||||
size_t argc = 0;
|
||||
if (argv) {
|
||||
while (argv[argc]) {
|
||||
dst_argp[argc] = (char *) argp_offset2;
|
||||
argp_offset2 += strlen(argv[argc]) + 1;
|
||||
if (argp_offset2 >= 4096) {
|
||||
panic("argp buffer overflow\n");
|
||||
}
|
||||
++argc;
|
||||
}
|
||||
dst_argp[argc] = NULL;
|
||||
argp_offset = (size_t) &dst_argp[argc + 1];
|
||||
// Convert offsets to pointers
|
||||
for (size_t i = 0; i < argc; ++i) {
|
||||
char *ent = dst_argp[i] + argp_offset;
|
||||
dst_argp[i] = (char *) (MM_PHYS(ent) - argp_page_phys);
|
||||
strcpy(ent, argv[i]);
|
||||
kdebug("Cloning argument: %s -> %p\n", ent, dst_argp[i]);
|
||||
}
|
||||
} else {
|
||||
dst_argp[0] = NULL;
|
||||
}
|
||||
|
||||
// 1. Discard memory
|
||||
// XXX: And this is why I need CoW
|
||||
mm_space_release(space);
|
||||
@@ -221,7 +259,20 @@ int sys_execve(const char *filename, const char *const argv[], const char *const
|
||||
THREAD_CTX_ONLY,
|
||||
NULL
|
||||
) == 0);
|
||||
// Revirtualize offsets
|
||||
for (size_t i = 0; i < argc; ++i) {
|
||||
dst_argp[i] = (char *) ((uintptr_t) dst_argp[i] + thr->argp_page);
|
||||
}
|
||||
// Copy the data block
|
||||
memcpy((void *) MM_VIRTUALIZE(thr->argp_page_phys), dst_argp, 4096);
|
||||
amd64_phys_free(argp_page_phys);
|
||||
for (size_t i = 0; i < argc; ++i) {
|
||||
kdebug("%p[%d] = %p\n", thr->argp_page, i, ((char **) MM_VIRTUALIZE(thr->argp_page_phys))[i]);
|
||||
}
|
||||
kdebug("argp buffer = %p\n", thr->argp_page);
|
||||
|
||||
struct cpu_context *ctx = (struct cpu_context *) thr->data.rsp0;
|
||||
ctx->rdi = thr->argp_page;
|
||||
|
||||
// 3. Load new binary
|
||||
_assert(elf_load(thr, file_buf) == 0);
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ intptr_t amd64_syscall(uintptr_t rdi, uintptr_t rsi, uintptr_t rdx, uintptr_t rc
|
||||
case SYSCALL_NR_STAT:
|
||||
return sys_stat((const char *) rdi, (struct stat *) rsi);
|
||||
case SYSCALL_NR_EXECVE:
|
||||
return sys_execve((const char *) rdi, NULL, NULL);
|
||||
return sys_execve((const char *) rdi, (const char **) rsi, NULL);
|
||||
case SYSCALL_NR_READDIR:
|
||||
return sys_readdir((int) rdi, (struct dirent *) rsi);
|
||||
case SYSCALL_NR_GETCWD:
|
||||
|
||||
+91
-2
@@ -1,6 +1,95 @@
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello!\n");
|
||||
#define LINE_LENGTH 16
|
||||
|
||||
static void line_print(size_t off, const char *line, size_t len) {
|
||||
printf("%08x: ", off);
|
||||
for (size_t i = 0; i < LINE_LENGTH; ++i) {
|
||||
// XXX: This is needed because I didn't implement h/hh modifiers in printf
|
||||
uint64_t byte = (uint64_t) line[i] & 0xFF;
|
||||
if (i < len) {
|
||||
printf("%02x", byte);
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
if (i % 2) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("| ");
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
// TODO: isprint?
|
||||
if (line[i] >= ' ') {
|
||||
printf("%c", line[i]);
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int fd;
|
||||
const char *path;
|
||||
char buf[512];
|
||||
char line[LINE_LENGTH];
|
||||
ssize_t bread;
|
||||
size_t offset;
|
||||
size_t linel;
|
||||
size_t n_full_zero;
|
||||
|
||||
// TODO: first argument is used for the program name itself
|
||||
if (argc != 1) {
|
||||
printf("wrong\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = argv[0];
|
||||
printf("open file %s\n", path);
|
||||
|
||||
if ((fd = open(path, O_RDONLY, 0)) < 0) {
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
linel = 0;
|
||||
n_full_zero = 0;
|
||||
while ((bread = read(fd, buf, sizeof(buf))) > 0) {
|
||||
for (size_t i = 0; i < bread; ++i) {
|
||||
line[linel++] = buf[i];
|
||||
if (linel == LINE_LENGTH) {
|
||||
// Check if the line is all zeros
|
||||
int all_zeros = 1;
|
||||
for (size_t j = 0; j < LINE_LENGTH; ++j) {
|
||||
if (line[j]) {
|
||||
all_zeros = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_zeros) {
|
||||
++n_full_zero;
|
||||
} else {
|
||||
n_full_zero = 0;
|
||||
}
|
||||
|
||||
if (n_full_zero < 3) {
|
||||
line_print(offset, line, linel);
|
||||
} else if (n_full_zero == 3) {
|
||||
printf(" ... \n");
|
||||
}
|
||||
offset += LINE_LENGTH;
|
||||
linel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (linel) {
|
||||
line_print(offset, line, linel);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+6
-2
@@ -57,13 +57,17 @@ static int cmd_exec(const char *cmd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(cmd, "hello")) {
|
||||
if (!strcmp(cmd, "hello") || !strncmp(cmd, "hello ", 6)) {
|
||||
int res;
|
||||
|
||||
if ((res = fork()) == 0) {
|
||||
const char *argument = cmd[5] ? &cmd[6] : "nothing";
|
||||
printf("In child\n");
|
||||
const char *argp[] = {
|
||||
argument, 0
|
||||
};
|
||||
|
||||
res = execve("/hello", NULL, NULL);
|
||||
res = execve("/hello", argp, NULL);
|
||||
|
||||
if (res < 0) {
|
||||
perror("execve()");
|
||||
|
||||
+4
-4
@@ -2,8 +2,7 @@
|
||||
.global _start
|
||||
.type _start, %function
|
||||
// Arguments:
|
||||
// %rdi - argc (well, not quite yet)
|
||||
// %rsi - argv
|
||||
// %rdi - argp
|
||||
_start:
|
||||
movq $0, %rbp
|
||||
// For callee linkage
|
||||
@@ -11,12 +10,13 @@ _start:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
|
||||
push %rdi
|
||||
call __libc_init
|
||||
|
||||
call _init
|
||||
|
||||
// Ignore %rdi/%rsi for now
|
||||
xorq %rdi, %rdi
|
||||
mov __libc_argc, %rdi
|
||||
pop %rsi
|
||||
|
||||
// exit(main(argc, argv))
|
||||
call main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "bits/global.h"
|
||||
|
||||
void *__cur_brk;
|
||||
uint64_t __libc_argc = 0;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
extern void *__cur_brk;
|
||||
extern uint64_t __libc_argc;
|
||||
|
||||
+9
-1
@@ -3,9 +3,17 @@
|
||||
|
||||
extern char __heap_start;
|
||||
extern void __libc_signal_init(void);
|
||||
static const char *argp_dummy[] = { 0 };
|
||||
|
||||
void __libc_init(void) {
|
||||
void __libc_init(char **argp) {
|
||||
__libc_signal_init();
|
||||
__libc_argc = 0;
|
||||
if (argp) {
|
||||
while (argp[__libc_argc]) {
|
||||
printf("%s\n", argp[__libc_argc]);
|
||||
++__libc_argc;
|
||||
}
|
||||
}
|
||||
__cur_brk = &__heap_start;
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user