From f9f2b6bb2d685556bc3346ca3f7e55f4c865fc16 Mon Sep 17 00:00:00 2001 From: johannst Date: Tue, 24 Nov 2020 21:23:08 +0100 Subject: add process init chapter Add chapter on process initialization. Add program to visualize data provided by the Linux Kernel as specified in the SysV ABI. Add utils for syscalls and printing + tests. --- 02_process_init/entry.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 02_process_init/entry.c (limited to '02_process_init/entry.c') diff --git a/02_process_init/entry.c b/02_process_init/entry.c new file mode 100644 index 0000000..a6b0918 --- /dev/null +++ b/02_process_init/entry.c @@ -0,0 +1,75 @@ +// Copyright (c) 2020 Johannes Stoelp + +#include +#include +#include +#include +#include + +#if !defined(__linux__) || !defined(__x86_64__) +# error "Only supported in linux(x86_64)!" +#endif + +int dynld_printf(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + char buf[64]; + int ret = dynld_vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + syscall3(__NR_write, 1 /* stdout */, buf, ret); + return ret; +} + +void entry(long* prctx) { + // Interpret data on the stack passed by the OS kernel as specified in the + // x86_64 SysV ABI. + + long argc = *prctx; + const char** argv = (const char**)(prctx + 1); + const char** envv = (const char**)(argv + argc + 1); + + int envc = 0; + for (const char** env = envv; *env; ++env) { + ++envc; + } + + uint64_t auxv[AT_MAX_CNT]; + for (unsigned i = 0; i < AT_MAX_CNT; ++i) { + auxv[i] = 0; + } + + const uint64_t* auxvp = (const uint64_t*)(envv + envc + 1); + for (unsigned i = 0; auxvp[i] != AT_NULL; i += 2) { + if (auxvp[i] < AT_MAX_CNT) { + auxv[auxvp[i]] = auxvp[i + 1]; + } + } + + // Print for demonstration + + dynld_printf("Got %d arg(s)\n", argc); + for (const char** arg = argv; *arg; ++arg) { + dynld_printf("\targ = %s\n", *arg); + } + + const int max_env = 10; + dynld_printf("Print first %d env var(s)\n", max_env - 1); + for (const char** env = envv; *env && (env - envv < max_env); ++env) { + dynld_printf("\tenv = %s\n", *env); + } + + dynld_printf("Print auxiliary vector\n"); + dynld_printf("\tAT_EXECFD: %ld\n", auxv[AT_EXECFD]); + dynld_printf("\tAT_PHDR : %p\n", auxv[AT_PHDR]); + dynld_printf("\tAT_PHENT : %ld\n", auxv[AT_PHENT]); + dynld_printf("\tAT_PHNUM : %ld\n", auxv[AT_PHNUM]); + dynld_printf("\tAT_PAGESZ: %ld\n", auxv[AT_PAGESZ]); + dynld_printf("\tAT_BASE : %lx\n", auxv[AT_BASE]); + dynld_printf("\tAT_FLAGS : %ld\n", auxv[AT_FLAGS]); + dynld_printf("\tAT_ENTRY : %p\n", auxv[AT_ENTRY]); + dynld_printf("\tAT_NOTELF: %lx\n", auxv[AT_NOTELF]); + dynld_printf("\tAT_UID : %ld\n", auxv[AT_UID]); + dynld_printf("\tAT_EUID : %ld\n", auxv[AT_EUID]); + dynld_printf("\tAT_GID : %ld\n", auxv[AT_GID]); + dynld_printf("\tAT_EGID : %ld\n", auxv[AT_EGID]); +} -- cgit v1.2.3