summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/Makefile37
-rw-r--r--service/dynamic_x86_64.c139
-rw-r--r--service/kc.h46
-rw-r--r--service/kc.ld97
-rw-r--r--service/kjarna.c13
-rw-r--r--service/main.c17
-rw-r--r--service/start_x86_64.S63
7 files changed, 412 insertions, 0 deletions
diff --git a/service/Makefile b/service/Makefile
new file mode 100644
index 0000000..d6e762d
--- /dev/null
+++ b/service/Makefile
@@ -0,0 +1,37 @@
+include ../defaults.mk
+
+LDFLAGS += -z max-page-size=4096 --export-dynamic -pic \
+ -z separate-code -pie -Bsymbolic -shared \
+ -z noexecstack -g
+
+VPATH := ../lib
+
+TARGET := kjarna.os
+.DEFAULT: $(TARGET)
+
+CPPFLAGS += -I../api/posix -I../api/libc -I../api -I.
+
+CFLAGS += -fPIC -fvisibility=hidden -mgeneral-regs-only
+
+LDSCRIPT := kc.ld
+
+CRT_OBJS := start_x86_64.o dynamic_x86_64.o elf64.o kjarna.o
+LIB_OBJS := memcmp.o memcpy.o memmove.o memset.o string.o stdio.o \
+ printf.o
+APP_OBJS := main.o
+
+OBJS := $(CRT_OBJS) $(LIB_OBJS) $(APP_OBJS)
+
+DEPS := $(patsubst %.o,%.d,$(OBJS))
+
+$(TARGET): $(LDSCRIPT) $(MAKEFILE_LIST)
+$(TARGET): $(OBJS)
+
+CLEANLIST := $(wildcard $(OBJS) $(TARGET))
+DCLEANLIST := $(wildcard $(DEPS))
+
+include ../rules.mk
+-include $(DEPS)
+
+.DEFAULT: $(TARGET)
+
diff --git a/service/dynamic_x86_64.c b/service/dynamic_x86_64.c
new file mode 100644
index 0000000..02538ec
--- /dev/null
+++ b/service/dynamic_x86_64.c
@@ -0,0 +1,139 @@
+#include <kc.h>
+
+#include <libc/string.h>
+#include <lib/elf.h>
+
+extern void _rtld_link(void);
+
+struct elf64_relatab
+{
+ Elf64_Rela *entries;
+ size_t size;
+ size_t entsize;
+};
+
+struct elf64_symtab
+{
+ Elf64_Sym *entries;
+ const char *strings;
+ size_t strsize;
+};
+
+struct elf64_dso_info
+{
+ char *base;
+ struct elf64_relatab jmprel;
+ struct elf64_relatab reladyn;
+ struct elf64_symtab dynsym;
+ Elf64_Addr *pltgot;
+};
+
+static struct elf64_dso_info dso_info;
+
+void kc_dynamic_init(char *base, Elf64_Dyn *dyn)
+{
+ dso_info = (struct elf64_dso_info)
+ {
+ base,
+ {
+ elf64_dt_ptr(base, dyn, DT_JMPREL),
+ elf64_dt_val(dyn, DT_PLTRELSZ),
+ elf64_dt_val(dyn, DT_PLTREL) == DT_RELA ? sizeof(Elf64_Rela) : -1
+ },
+ {
+ elf64_dt_ptr(base, dyn, DT_RELA),
+ elf64_dt_val(dyn, DT_RELASZ),
+ elf64_dt_val(dyn, DT_RELAENT)
+ },
+ {
+ elf64_dt_ptr(base, dyn, DT_SYMTAB),
+ elf64_dt_ptr(base, dyn, DT_STRTAB),
+ elf64_dt_val(dyn, DT_STRSZ)
+ },
+ elf64_dt_ptr(base, dyn, DT_PLTGOT)
+ };
+
+ if (dso_info.pltgot != nullptr)
+ {
+ dso_info.pltgot[1] = (uintptr_t)&dso_info;
+ dso_info.pltgot[2] = (uintptr_t)_rtld_link;
+ }
+
+ kc_dynamic_reloc(base, &dso_info.jmprel);
+ kc_dynamic_reloc(base, &dso_info.reladyn);
+}
+
+void *kc_dynamic_link(struct elf64_dso_info *dso, int index)
+{
+ struct kjarna_interface *ftab = entry_params->interface;
+
+ int symindex = ELF64_R_SYM(dso->jmprel.entries[index].r_info);
+ int strindex = dso->dynsym.entries[symindex].st_name;
+ const char *name = &dso->dynsym.strings[strindex];
+ uintptr_t *fixup = (uintptr_t *)(dso->base + dso->jmprel.entries[index].r_offset);
+
+ // TODO: generate a symbol table for kjarna interface
+ // TODO: implement symbol lookup (maybe hashed too)
+ if (strcmp(name, "open") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->open;
+ }
+ else if (strcmp(name, "close") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->close;
+ }
+ else if (strcmp(name, "read") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->read;
+ }
+ else if (strcmp(name, "write") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->write;
+ }
+ else if (strcmp(name, "lseek") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->lseek;
+ }
+ else if (strcmp(name, "mmap") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->mmap;
+ }
+ else if (strcmp(name, "munmap") == 0)
+ {
+ *fixup = (uintptr_t)*ftab->munmap;
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ return fixup;
+}
+
+static void do_rela(char *base, Elf64_Rela *rela)
+{
+ uintptr_t *fixup = (uintptr_t *)(base + rela->r_offset);
+
+ switch (ELF64_R_TYPE(rela->r_info))
+ {
+ case R_X86_64_JUMP_SLOT:
+ *fixup += (uintptr_t)base;
+ break;
+ case R_X86_64_RELATIVE:
+ *fixup = (uintptr_t)(rela->r_addend + base);
+ break;
+ default:
+ break;
+ }
+}
+
+void kc_dynamic_reloc(char *base, struct elf64_relatab *rela)
+{
+ size_t entries = rela->size / rela->entsize;
+
+ for (size_t i = 0; rela->entries && (i < entries); i++)
+ {
+ do_rela(base, &rela->entries[i]);
+ }
+}
+
diff --git a/service/kc.h b/service/kc.h
new file mode 100644
index 0000000..ff3a1ca
--- /dev/null
+++ b/service/kc.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#ifndef __ASSEMBLER__
+
+#include <elf/elf64.h>
+
+#include <stddef.h>
+
+#include <kjarna/interface.h>
+
+extern struct kjarna_entry_params *entry_params;
+
+#define KC_EXPORT __attribute__((visibility("default")))
+
+extern unsigned char kc_image_base;
+extern unsigned char kc_text_begin;
+extern unsigned char kc_text_end;
+extern unsigned char kc_rodata_begin;
+extern unsigned char kc_data_begin;
+extern unsigned char kc_data_end;
+extern unsigned char kc_image_end;
+
+struct elf64_dso_info;
+struct elf64_relatab;
+
+extern void kc_dynamic_init(char *base, Elf64_Dyn *dyn);
+extern void *kc_dynamic_link(struct elf64_dso_info *dso, int index);
+extern void kc_dynamic_reloc(char *base, struct elf64_relatab *dso);
+
+#else
+
+.extern kc_image_base
+.extern kc_text_begin
+.extern kc_text_end
+.extern kc_rodata_begin
+.extern kc_rodata_end
+.extern kc_data_begin
+.extern kc_data_end
+.extern kc_image_end
+.extern _DYNAMIC
+
+.extern kc_dynamic_init
+.extern kc_dynamic_link
+
+#endif // __ASSEMBLER__
+
diff --git a/service/kc.ld b/service/kc.ld
new file mode 100644
index 0000000..f7b0339
--- /dev/null
+++ b/service/kc.ld
@@ -0,0 +1,97 @@
+ENTRY(_start)
+
+SECTIONS
+{
+ PROVIDE_HIDDEN(kc_image_base = .);
+
+ . = SIZEOF_HEADERS;
+
+ .rela.plt :
+ {
+ *(.rela.plt)
+ }
+
+ .rela.dyn :
+ {
+ *(.rela.dyn)
+ }
+
+ .hash :
+ {
+ *(.hash)
+ }
+
+ .dynsym :
+ {
+ *(.dynsym)
+ }
+
+ .dynstr :
+ {
+ *(.dynstr)
+ }
+
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata.*)
+ }
+
+ .text : ALIGN(4K)
+ {
+ PROVIDE_HIDDEN(kc_text_begin = .);
+ *(.text.start)
+ *(.text)
+ }
+
+ .plt :
+ {
+ *(.plt)
+ . = ALIGN(4K);
+ PROVIDE_HIDDEN(kc_text_end = .);
+ } =0xcc
+
+ .dynamic : ALIGN(4K)
+ {
+ PROVIDE_HIDDEN(kc_data_begin = .);
+ *(.dynamic)
+ }
+
+ .got :
+ {
+ *(.got)
+ }
+
+ .got.plt :
+ {
+ *(.got.plt)
+ }
+
+ .data :
+ {
+ *(.data)
+ }
+
+ .data.rel :
+ {
+ *(.data.rel)
+ *(.data.rel.*)
+ }
+
+ .bss :
+ {
+ *(.bss)
+ *(.dynbss)
+ . = ALIGN(4K);
+ PROVIDE_HIDDEN(kc_data_end = .);
+ }
+
+ PROVIDE_HIDDEN(kc_image_end = .);
+
+ /DISCARD/ :
+ {
+ *(.eh_frame)
+ *(.comment)
+ }
+}
+
diff --git a/service/kjarna.c b/service/kjarna.c
new file mode 100644
index 0000000..6b37d1e
--- /dev/null
+++ b/service/kjarna.c
@@ -0,0 +1,13 @@
+#include <kjarna/interface.h>
+
+struct kjarna_entry_params *entry_params;
+
+extern int main(int argc, char **argv);
+
+int kjarna_entry(struct kjarna_entry_params *params)
+{
+ entry_params = params;
+
+ return main(params->argc, params->argv);
+}
+
diff --git a/service/main.c b/service/main.c
new file mode 100644
index 0000000..12a5522
--- /dev/null
+++ b/service/main.c
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <stdio.h>
+
+#define KJARNA_REVISION 1
+
+int main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ printf("kjarna %d\n", KJARNA_REVISION);
+
+ while (1);
+
+ return 0;
+}
+
diff --git a/service/start_x86_64.S b/service/start_x86_64.S
new file mode 100644
index 0000000..19db34f
--- /dev/null
+++ b/service/start_x86_64.S
@@ -0,0 +1,63 @@
+#include <kc.h>
+
+.section .text.start
+
+.extern kjarna_entry
+
+.hidden _start
+.global _start
+.type _start, @function
+_start:
+ push %rbp
+ push %rdi
+ push %rsi
+ mov %rsp, %rbp
+ and $-0x10, %rsp
+ lea kc_image_base(%rip), %rdi
+ lea _DYNAMIC(%rip), %rsi
+ call kc_dynamic_init
+ mov %rbp, %rsp
+ pop %rsi
+ pop %rdi
+ mov %rsp, %rbp
+ and $-0x10, %rsp
+ call kjarna_entry
+ mov %rbp, %rsp
+ pop %rbp
+ ret
+.size _start, . - _start
+
+.section .text
+
+.hidden _rtld_link
+.global _rtld_link
+.type _rtld_link, @function
+_rtld_link:
+ push %rbp
+ mov %rsp, %rbp
+ push %r9
+ push %r8
+ push %rcx
+ push %rdx
+ push %rsi
+ push %rdi
+ mov 8(%rbp), %rdi
+ mov 16(%rbp), %rsi
+ push %rbp
+ mov %rsp, %rbp
+ and $-0x10, %rsp
+ call kc_dynamic_link
+ mov %rbp, %rsp
+ pop %rbp
+ pop %rdi
+ pop %rsi
+ pop %rdx
+ pop %rcx
+ pop %r8
+ pop %r9
+ mov %rbp, %rsp
+ pop %rbp
+ add $0x10, %rsp
+ jmp *(%rax)
+.size _rtld_link, . - _rtld_link
+