aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--02_process_init/Makefile8
-rw-r--r--02_process_init/entry.c18
-rw-r--r--include/io.h43
3 files changed, 49 insertions, 20 deletions
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 <asm/unistd.h>
#include <elf.h>
-#include <fmt.h>
-#include <stdint.h>
-#include <syscall.h>
+#define MAX_PRINTF_LEN 128
+#include <io.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) {
+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 <asm/unistd.h>
+
+// `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;
+}