summaryrefslogtreecommitdiff
path: root/src/user/lib
diff options
context:
space:
mode:
authordzwdz2022-07-23 18:20:06 +0200
committerdzwdz2022-07-23 18:20:06 +0200
commit3badc5ac30fcc0836a2604146788158b16b64f2d (patch)
treea05a6c7501119b779191414a2a6265382574732d /src/user/lib
parentcd12cbc75564fafd9c2519cdf1085e651c9d7cfd (diff)
init: compile as an elf
Diffstat (limited to 'src/user/lib')
-rw-r--r--src/user/lib/elfload.c1
-rw-r--r--src/user/lib/elfload.h2
-rw-r--r--src/user/lib/elfreloc.c42
3 files changed, 45 insertions, 0 deletions
diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c
index c32232e..6c75268 100644
--- a/src/user/lib/elfload.c
+++ b/src/user/lib/elfload.c
@@ -76,6 +76,7 @@ void elf_exec(void *base) {
struct Elf64_Ehdr *ehdr = base;
void *exebase;
if (!valid_ehdr(ehdr)) return;
+ _syscall_debug_klog("here", 4);
size_t spread = elf_spread(base);
switch (ehdr->e_type) {
case ET_EXEC:
diff --git a/src/user/lib/elfload.h b/src/user/lib/elfload.h
index c6afbdd..f79be6e 100644
--- a/src/user/lib/elfload.h
+++ b/src/user/lib/elfload.h
@@ -3,3 +3,5 @@
void elf_execf(libc_file *f);
void elf_exec(void *elf);
+
+void elf_selfreloc(void); // elfreloc.c
diff --git a/src/user/lib/elfreloc.c b/src/user/lib/elfreloc.c
new file mode 100644
index 0000000..550fe97
--- /dev/null
+++ b/src/user/lib/elfreloc.c
@@ -0,0 +1,42 @@
+#include <user/lib/elf.h>
+#include <user/lib/stdlib.h>
+
+__attribute__((visibility("hidden")))
+extern struct Elf64_Dyn _DYNAMIC[];
+
+__attribute__((visibility("hidden")))
+extern char _image_base[];
+
+static struct Elf64_Dyn *dyn_gettag(Elf64_Xword tag) {
+ for (size_t i = 0;; i++) {
+ if (_DYNAMIC[i].d_tag == tag) return &_DYNAMIC[i];
+ if (_DYNAMIC[i].d_tag == DT_NULL) return NULL;
+ }
+}
+
+void elf_selfreloc(void) {
+ // TODO DT_REL
+ if (dyn_gettag(DT_PLTGOT) || dyn_gettag(DT_JMPREL)) {
+ _klogf("elf: unimplemented tag in _DYNAMIC\n");
+ }
+
+ struct Elf64_Dyn *rela_tag = dyn_gettag(DT_RELA);
+ if (rela_tag) {
+ /* not checking pointer validity,
+ * crashing on an invalid elf is fine */
+ size_t relasz = dyn_gettag(DT_RELASZ)->d_val;
+ size_t relaent = dyn_gettag(DT_RELAENT)->d_val;
+ for (size_t o = 0; o < relasz; o += relaent) {
+ struct Elf64_Rela *r = (void*)_image_base + rela_tag->d_ptr + o;
+ uintptr_t *target = (void*)_image_base + r->r_offset;
+
+ switch (ELF64_R_TYPE(r->r_info)) {
+ case R_X86_64_RELATIVE:
+ *target = (uintptr_t)&_image_base + r->r_addend;
+ break;
+ default:
+ _klogf("elf: unsupported relocation type\n");
+ }
+ }
+ }
+}