Crude argument passing, added hex dump as demo program

This commit is contained in:
Mark
2019-12-30 17:26:33 +02:00
parent 582507c17f
commit 8380cd3155
9 changed files with 169 additions and 11 deletions
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,3 +1,4 @@
#include "bits/global.h"
void *__cur_brk;
uint64_t __libc_argc = 0;
+2
View File
@@ -1,3 +1,5 @@
#pragma once
#include <stdint.h>
extern void *__cur_brk;
extern uint64_t __libc_argc;
+9 -1
View File
@@ -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;
}