From 9e90abfdb0b1b1f270b4ae0e4f5d8742d1f2f472 Mon Sep 17 00:00:00 2001 From: johannst Date: Tue, 24 Nov 2020 23:46:17 +0100 Subject: factorize printf into io.h --- 02_process_init/Makefile | 8 +++----- 02_process_init/entry.c | 18 +++--------------- include/io.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 20 deletions(-) create mode 100644 include/io.h diff --git a/02_process_init/Makefile b/02_process_init/Makefile index 6e1f512..430b0a9 100644 --- a/02_process_init/Makefile +++ b/02_process_init/Makefile @@ -1,18 +1,16 @@ # Copyright (c) 2020 Johannes Stoelp show: entry - #gdb -q --batch -ex 'starti' -ex 'x/g $$rsp' -ex 'x/s *(char**)($$rsp+8)' ./$^ ./entry 1 2 3 4 entry: entry.S entry.c gcc -o $@ \ - -I ../include \ + -g -O0 \ -Wall -Wextra \ - -static \ + -I ../include \ -nostartfiles -nodefaultlibs \ - -g -O0 \ + -static \ $^ - clean: rm -f entry diff --git a/02_process_init/entry.c b/02_process_init/entry.c index a6b0918..360d205 100644 --- a/02_process_init/entry.c +++ b/02_process_init/entry.c @@ -1,26 +1,14 @@ // Copyright (c) 2020 Johannes Stoelp -#include #include -#include -#include -#include +#define MAX_PRINTF_LEN 128 +#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) { +void entry(const long* prctx) { // Interpret data on the stack passed by the OS kernel as specified in the // x86_64 SysV ABI. diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000..4b3ea4b --- /dev/null +++ b/include/io.h @@ -0,0 +1,43 @@ +// Copyright (c) 2020 Johannes Stoelp + +#pragma once + +#include "fmt.h" +#include "syscall.h" + +#include + +// `dynld_printf` uses fixed-size buffer on the stack for formating the message +// (since we don't impl buffered I/O). +// +// Size can be re-configured by defining `MAX_PRINTF_LEN` before including +// `io.h`. +// +// NOTE: This allows to specify an arbitrarily large buffer on the stack, but +// for the purpose of this study that's fine, we are cautious. +#if !defined(MAX_PRINTF_LEN) +# define MAX_PRINTF_LEN 64 +#endif + +#define FD_STDOUT 1 +#define FD_STDERR 2 + +int dynld_printf(const char* fmt, ...) { + char buf[MAX_PRINTF_LEN]; + + va_list ap; + va_start(ap, fmt); + int ret = dynld_vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + if (ret > MAX_PRINTF_LEN - 1) { + syscall3(__NR_write, FD_STDERR, buf, MAX_PRINTF_LEN - 1); + + static const char warn[] = "\ndynld_printf: Message truncated, max length can be configured by defining MAX_PRINTF_LEN\n"; + syscall3(__NR_write, FD_STDOUT, warn, sizeof(warn)); + return MAX_PRINTF_LEN - 1; + } + + syscall3(__NR_write, FD_STDOUT, buf, ret); + return ret; +} -- cgit v1.2.3