diff options
author | johannst <johannes.stoelp@gmail.com> | 2020-11-24 21:23:08 +0100 |
---|---|---|
committer | johannst <johannes.stoelp@gmail.com> | 2020-11-24 21:23:08 +0100 |
commit | f9f2b6bb2d685556bc3346ca3f7e55f4c865fc16 (patch) | |
tree | 3ed8ac66323b6985713427d147826c5845212c13 /02_process_init/entry.c | |
parent | f9e7e2003266e70c0d018f5712c431d187159e65 (diff) | |
download | dynld-f9f2b6bb2d685556bc3346ca3f7e55f4c865fc16.tar.gz dynld-f9f2b6bb2d685556bc3346ca3f7e55f4c865fc16.zip |
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.
Diffstat (limited to '02_process_init/entry.c')
-rw-r--r-- | 02_process_init/entry.c | 75 |
1 files changed, 75 insertions, 0 deletions
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 <asm/unistd.h> +#include <elf.h> +#include <fmt.h> +#include <stdint.h> +#include <syscall.h> + +#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]); +} |