aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--02_process_init/Makefile17
-rw-r--r--02_process_init/entry.c1
-rw-r--r--include/elf.h26
-rw-r--r--lib/Makefile25
-rw-r--r--lib/include/auxv.h36
-rw-r--r--lib/include/elf.h75
-rw-r--r--lib/include/fmt.h8
-rw-r--r--lib/include/io.h5
-rw-r--r--lib/include/syscall.h (renamed from include/syscall.h)2
-rw-r--r--lib/src/fmt.c (renamed from include/fmt.h)77
-rw-r--r--lib/src/io.c (renamed from include/io.h)18
-rw-r--r--test/Makefile7
-rw-r--r--test/checker.cc5
13 files changed, 205 insertions, 97 deletions
diff --git a/02_process_init/Makefile b/02_process_init/Makefile
index db04941..0b51903 100644
--- a/02_process_init/Makefile
+++ b/02_process_init/Makefile
@@ -3,14 +3,17 @@
show: entry
./entry 1 2 3 4
-entry: entry.S entry.c
- gcc -o $@ \
- -g -O0 \
- -Wall -Wextra \
- -I ../include \
- -nostdlib \
- -static \
+entry: entry.S entry.c ../lib/libcommon.a
+ gcc -o $@ \
+ -g -O0 \
+ -Wall -Wextra \
+ -I../lib/include \
+ -nostdlib \
+ -static \
$^
+../lib/libcommon.a:
+ make -C ../lib
+
clean:
rm -f entry
diff --git a/02_process_init/entry.c b/02_process_init/entry.c
index 37d5fc8..ca24f77 100644
--- a/02_process_init/entry.c
+++ b/02_process_init/entry.c
@@ -2,7 +2,6 @@
#include <auxv.h>
#include <elf.h>
-#define MAX_PRINTF_LEN 128
#include <io.h>
#if !defined(__linux__) || !defined(__x86_64__)
diff --git a/include/elf.h b/include/elf.h
deleted file mode 100644
index 7e279fe..0000000
--- a/include/elf.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2020 Johannes Stoelp
-
-#pragma once
-
-#include <bits/stdint-uintn.h>
-#include <stdint.h>
-
-enum eAuxvTag {
- AT_NULL = 0, /* ignored */
- AT_IGNORE = 1, /* ignored */
- AT_EXECFD = 2, /* val */
- AT_PHDR = 3, /* ptr */
- AT_PHENT = 4, /* val */
- AT_PHNUM = 5, /* val */
- AT_PAGESZ = 6, /* val */
- AT_BASE = 7, /* ptr */
- AT_FLAGS = 8, /* val */
- AT_ENTRY = 9, /* ptr */
- AT_NOTELF = 10, /* val */
- AT_UID = 11, /* val */
- AT_EUID = 12, /* val */
- AT_GID = 13, /* val */
- AT_EGID = 14, /* val */
-
- AT_MAX_CNT,
-};
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..29c103a
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,25 @@
+# Copyright (c) 2020 Johannes Stoelp
+
+HDR+=include/auxv.h
+HDR+=include/elf.h
+HDR+=include/fmt.h
+HDR+=include/io.h
+HDR+=include/syscall.h
+
+DEP+=src/io.o
+DEP+=src/fmt.o
+
+libcommon.a: $(HDR) $(DEP)
+ ar -crs $@ $(filter %.o, $^)
+
+src/%.o: src/%.c
+ gcc -c -o $@ \
+ -g -O0 \
+ -Wall -Wextra \
+ -I$(CURDIR)/include \
+ -nostdlib \
+ $<
+
+clean:
+ rm -f $(DEP)
+ rm -f libcommon.a
diff --git a/lib/include/auxv.h b/lib/include/auxv.h
new file mode 100644
index 0000000..42dac38
--- /dev/null
+++ b/lib/include/auxv.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2020 Johannes Stoelp
+
+#pragma once
+
+#include <stdint.h>
+
+/// ----------------
+/// Auxiliary Vector
+/// ----------------
+
+// NOTE: [x86-64] Either AT_EXECFD or AT_PHDR must be supplied by the Kernel.
+
+#define AT_NULL 0 /* [ignored] Mark end of auxiliary vetcor */
+#define AT_IGNORE 1 /* [ignored] */
+#define AT_EXECFD 2 /* [val] File descriptor of user program (in case Linux Kernel didn't mapped) */
+#define AT_PHDR 3 /* [ptr] Address of Phdr of use program (in case Kernel mapped user program) */
+#define AT_PHENT 4 /* [val] Size in bytes of one Phdr entry */
+#define AT_PHNUM 5 /* [val] Number of Phread entries */
+#define AT_PAGESZ 6 /* [val] System page size */
+#define AT_BASE 7 /* [ptr] `base address` interpreter was loaded to */
+#define AT_FLAGS 8 /* [val] */
+#define AT_ENTRY 9 /* [ptr] Entry point of user program */
+#define AT_NOTELF 10 /* [val] >0 if not an ELF file */
+#define AT_UID 11 /* [val] Real user id of process */
+#define AT_EUID 12 /* [val] Effective user id of process */
+#define AT_GID 13 /* [val] Real group id of process */
+#define AT_EGID 14 /* [val] Effective user id of process */
+#define AT_MAX_CNT 15
+
+typedef struct {
+ uint64_t tag;
+ union {
+ uint64_t val;
+ void* ptr;
+ };
+} Auxv64Entry;
diff --git a/lib/include/elf.h b/lib/include/elf.h
new file mode 100644
index 0000000..a0fe6f7
--- /dev/null
+++ b/lib/include/elf.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2020 Johannes Stoelp
+
+#pragma once
+
+#include <stdint.h>
+
+/// --------------
+/// Program Header
+/// --------------
+
+#define PT_NULL 0 /* ignored */
+#define PT_LOAD 1 /* Mark loadable segment (allowed p_memsz > p_filesz). */
+#define PT_DYNAMIC 2 /* Location of .dynamic section */
+#define PT_INTERP 3 /* Location of .interp section */
+#define PT_NOTE 4 /* Location of auxiliary information */
+#define PT_SHLIB 5 /* Reserved, but unspecified semantic */
+#define PT_PHDR 6 /* Location & size of program headers itself */
+
+#define PT_GNU_EH_FRAME 0x6474e550 /* [x86-64] stack unwinding tables */
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+
+#define PF_X 0x1 /* Phdr flag eXecute flag bitmask */
+#define PF_W 0x2 /* Phdr flag Write flag bitmask */
+#define PF_R 0x4 /* Phdr flag Read flag bitmask */
+
+typedef struct {
+ uint32_t type; // Segment kind.
+ uint32_t flags; // Flags describing Segment attributes like R, W, X.
+ uint64_t offset; // Offset into the file where the Segment starts.
+ uint64_t vaddr; // Virtual address of first byte of Segment in memory.
+ uint64_t paddr; // Physical address, ignored in our case.
+ uint64_t filesz; // Number of bytes of the Segment in the file image.
+ uint64_t memsz; // Number of bytes of the segement in memory.
+ uint64_t align;
+} Elf64Phdr;
+
+/// ---------------
+/// Dynamic Section
+/// ---------------
+
+#define DT_NULL 0 /* [ignored] Marks end of dynamic section */
+#define DT_NEEDED 1 /* [val] Name of needed library */
+#define DT_PLTRELSZ 2 /* [val] Size in bytes of PLT relocs */
+#define DT_PLTGOT 3 /* [ptr] Processor defined value */
+#define DT_HASH 4 /* [ptr] Address of symbol hash table */
+#define DT_STRTAB 5 /* [ptr] Address of string table */
+#define DT_SYMTAB 6 /* [ptr] Address of symbol table */
+#define DT_RELA 7 /* [ptr] Address of Rela relocs */
+#define DT_RELASZ 8 /* [val] Total size of Rela relocs */
+#define DT_RELAENT 9 /* [val] Size of one Rela reloc */
+#define DT_STRSZ 10 /* [val] Size of string table */
+#define DT_SYMENT 11 /* [val] Size of one symbol table entry */
+#define DT_INIT 12 /* [ptr] Address of init function */
+#define DT_FINI 13 /* [ptr] Address of termination function */
+#define DT_SONAME 14 /* [val] Name of shared object */
+#define DT_RPATH 15 /* [val] Library search path (deprecated) */
+#define DT_SYMBOLIC 16 /* [ignored] Start symbol search here */
+#define DT_REL 17 /* [ptr] Address of Rel relocs */
+#define DT_RELSZ 18 /* [val] Total size of Rel relocs */
+#define DT_RELENT 19 /* [val] Size of one Rel reloc */
+#define DT_PLTREL 20 /* [val] Type of reloc in PLT */
+#define DT_DEBUG 21 /* [ptr] For debugging; unspecified */
+#define DT_TEXTREL 22 /* [ignored] Reloc might modify .text */
+#define DT_JMPREL 23 /* [ptr] Address of PLT relocs */
+#define DT_BIND_NOW 24 /* [ignored] Process relocations of object */
+#define DT_MAX_CNT 25
+
+typedef struct {
+ uint64_t tag;
+ union {
+ uint64_t val;
+ void* ptr;
+ };
+} Elf64Dyn;
diff --git a/lib/include/fmt.h b/lib/include/fmt.h
new file mode 100644
index 0000000..61215bc
--- /dev/null
+++ b/lib/include/fmt.h
@@ -0,0 +1,8 @@
+// Copyright (c) 2020 Johannes Stoelp
+
+#pragma once
+
+#include <stdarg.h>
+
+int vfmt(char* buf, unsigned long len, const char* fmt, va_list ap);
+int fmt(char* buf, unsigned long len, const char* fmt, ...);
diff --git a/lib/include/io.h b/lib/include/io.h
new file mode 100644
index 0000000..5ca78a3
--- /dev/null
+++ b/lib/include/io.h
@@ -0,0 +1,5 @@
+// Copyright (c) 2020 Johannes Stoelp
+
+#pragma once
+
+int pfmt(const char* fmt, ...);
diff --git a/include/syscall.h b/lib/include/syscall.h
index 0508b38..4947155 100644
--- a/include/syscall.h
+++ b/lib/include/syscall.h
@@ -28,7 +28,7 @@
// machine specific constraint.
// ```c
// register long r12 asm ("r12") = 42;
-// asm("nop" : : "r"(r10));
+// asm("nop" : : "r"(r12));
// ```
//
// Reference:
diff --git a/include/fmt.h b/lib/src/fmt.c
index f4be0b1..be1ca3a 100644
--- a/include/fmt.h
+++ b/lib/src/fmt.c
@@ -1,16 +1,40 @@
// Copyright (c) 2020 Johannes Stoelp
-#pragma once
+#include <fmt.h>
-#include <stdarg.h>
+static const char* num2dec(char* buf, unsigned long len, unsigned long long num) {
+ char* pbuf = buf + len - 1;
+ *pbuf = '\0';
-#define ALLOW_UNUSED __attribute__((unused))
+ if (num == 0) {
+ *(--pbuf) = '0';
+ }
-static const char* num2dec(char* buf, unsigned long len, unsigned long long num);
-static const char* num2hex(char* buf, unsigned long len, unsigned long long num);
+ while (num > 0 && pbuf != buf) {
+ char d = (num % 10) + '0';
+ *(--pbuf) = d;
+ num /= 10;
+ }
+ return pbuf;
+}
-ALLOW_UNUSED
-static int vfmt(char* buf, unsigned long len, const char* fmt, va_list ap) {
+static const char* num2hex(char* buf, unsigned long len, unsigned long long num) {
+ char* pbuf = buf + len - 1;
+ *pbuf = '\0';
+
+ if (num == 0) {
+ *(--pbuf) = '0';
+ }
+
+ while (num > 0 && pbuf != buf) {
+ char d = (num & 0xf);
+ *(--pbuf) = d + (d > 9 ? 'a' - 10 : '0');
+ num >>= 4;
+ }
+ return pbuf;
+}
+
+int vfmt(char* buf, unsigned long len, const char* fmt, va_list ap) {
unsigned i = 0;
#define put(c) \
@@ -84,47 +108,10 @@ static int vfmt(char* buf, unsigned long len, const char* fmt, va_list ap) {
return i;
}
-ALLOW_UNUSED
-static int fmt(char* buf, unsigned long len, const char* fmt, ...) {
+int fmt(char* buf, unsigned long len, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = vfmt(buf, len, fmt, ap);
va_end(ap);
return ret;
}
-
-/// Internal Helper
-
-ALLOW_UNUSED
-static const char* num2dec(char* buf, unsigned long len, unsigned long long num) {
- char* pbuf = buf + len - 1;
- *pbuf = '\0';
-
- if (num == 0) {
- *(--pbuf) = '0';
- }
-
- while (num > 0 && pbuf != buf) {
- char d = (num % 10) + '0';
- *(--pbuf) = d;
- num /= 10;
- }
- return pbuf;
-}
-
-ALLOW_UNUSED
-static const char* num2hex(char* buf, unsigned long len, unsigned long long num) {
- char* pbuf = buf + len - 1;
- *pbuf = '\0';
-
- if (num == 0) {
- *(--pbuf) = '0';
- }
-
- while (num > 0 && pbuf != buf) {
- char d = (num & 0xf);
- *(--pbuf) = d + (d > 9 ? 'a' - 10 : '0');
- num >>= 4;
- }
- return pbuf;
-}
diff --git a/include/io.h b/lib/src/io.c
index 4f61cbf..efe938b 100644
--- a/include/io.h
+++ b/lib/src/io.c
@@ -1,30 +1,22 @@
// Copyright (c) 2020 Johannes Stoelp
-#pragma once
-
-#include "fmt.h"
-#include "syscall.h"
+#include <io.h>
+#include <fmt.h>
+#include <syscall.h>
#include <asm/unistd.h>
// `pfmt` uses fixed-size buffer on the stack for formating the message
// (for simplicity and 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 a 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 128
-#elif MAX_PRINTF_LEN > 512
-# error MAX_PRINTF_LEN is limited by 512!
-#endif
+#define MAX_PRINTF_LEN 128
#define FD_STDOUT 1
#define FD_STDERR 2
-static int pfmt(const char* fmt, ...) {
+int pfmt(const char* fmt, ...) {
char buf[MAX_PRINTF_LEN];
va_list ap;
diff --git a/test/Makefile b/test/Makefile
index 3e6fd74..398ebc1 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,8 +3,11 @@
check: build
./checker
-build: checker.cc
- g++ -o checker -g -O2 -I ../include -Wall -Wextra $^
+build: checker.cc ../lib/libcommon.a
+ g++ -o checker -g -O2 -I ../lib/include -Wall -Wextra $^
+
+../lib/libcommon.a:
+ make -C ../lib
clean:
rm -f checker
diff --git a/test/checker.cc b/test/checker.cc
index d5afa87..2707929 100644
--- a/test/checker.cc
+++ b/test/checker.cc
@@ -2,8 +2,9 @@
#include "test_helper.h"
-#include <cstdio>
-#include <fmt.h>
+extern "C" {
+ #include <fmt.h>
+}
void check_dec() {
char have[16];