Commit Diff


commit - cd0438ce5c0e5285e02b003de77438a71492de5d
commit + 764c56209e6f7ec63ac1a15059bd6a40fcae272d
blob - 4124e1203a82d28f1fc7418e37d6e6d3c628c626
blob + b245057f1e7392bdab164569fe3ae073316b2922
--- Makefile
+++ Makefile
@@ -47,6 +47,7 @@ install: linurv
 linurv: ${OBJ}
 	${CC} -o $@ ${OBJ} ${LDFLAGS}
 
+${OBJ}: src/linurv.h src/data.h
 src/ecall.o: src/syscalls.h
 
 src/cpu.o: src/signal-bootstrap-code.h
blob - c2f091bc7b9f67ffb6c76e1b9e89e6b274ba28d1
blob + ad3b92558169ad5a4f69fdba5a972d750e48c16f
--- src/data.dst
+++ src/data.dst
@@ -4,6 +4,7 @@ struct elf64_ehdr {
 	type: u16,
 	machine: u16,
 	version: u32,
+	entry: u64,
 	phoff: u64,
 	shoff: u64,
 	flags: u32,
blob - cb238ae4659091f4c53a5e07cf31b2bb9ecc5897
blob + 0fdb8431581673d815c4611a6f56838ddaf0b614
--- src/exec.c
+++ src/exec.c
@@ -5,23 +5,31 @@
 #include <errno.h>
 #include <ctype.h>
 #include "linurv.h"
+#include "data.h"
 
-
-int is_executable (const Elf64_Ehdr *ehdr)
+int is_executable (const struct elf64_ehdr *ehdr)
 {
-	return     ehdr->e_ident[EI_MAG0]	== ELFMAG0
-		&& ehdr->e_ident[EI_MAG1]	== ELFMAG1
-		&& ehdr->e_ident[EI_MAG2]	== ELFMAG2
-		&& ehdr->e_ident[EI_MAG3]	== ELFMAG3
-		&& ehdr->e_ident[EI_CLASS]	== ELFCLASS64
-		&& ehdr->e_ident[EI_DATA]	== ELFDATA2LSB
-		&& ehdr->e_machine		== EM_RISCV
+	return     ehdr->ident[EI_MAG0]		== ELFMAG0
+		&& ehdr->ident[EI_MAG1]		== ELFMAG1
+		&& ehdr->ident[EI_MAG2]		== ELFMAG2
+		&& ehdr->ident[EI_MAG3]		== ELFMAG3
+		&& ehdr->ident[EI_CLASS]	== ELFCLASS64
+		&& ehdr->ident[EI_DATA]		== ELFDATA2LSB
+		&& ehdr->machine		== EM_RISCV
 		;
 }
 
+void read_elf_ehdr (int fd, struct elf64_ehdr *ehdr)
+{
+	char buffer[sizeof (*ehdr)];
+	if (read (fd, buffer, sizeof (buffer)) != sizeof (buffer))
+		err (1, "read_elf_ehdr()");
+	decode_elf64_ehdr (ehdr, buffer);
+}
+
 int my_execve (const char *path, char **argv, char **envp)
 {
-	Elf64_Ehdr ehdr;
+	struct elf64_ehdr ehdr;
 	char buffer[256], *nl, *s;
 	int fd;
 
@@ -52,9 +60,9 @@ int my_execve (const char *path, char **argv, char **e
 		return my_execve (s, argv, envp);
 	}
 
-	memset (&ehdr, 0, sizeof (ehdr));
+	memset (buffer, 0, sizeof (ehdr));
 	lseek (fd, 0, SEEK_SET);
-	read (fd, &ehdr, sizeof (ehdr));
+	read_elf_ehdr (fd, &ehdr);
 	close (fd);
 
 	if (is_executable (&ehdr)) {
blob - aba351c137c52352baa240f38588b05c79aec9b1
blob + 4c367bd11bfe114032fcf6f6573f29b1054327f4
--- src/linurv.c
+++ src/linurv.c
@@ -22,19 +22,19 @@ const char *levelstr[] = {
 enum log_level curlevel;
 u64 brkval = 0;
 
-static void load_segment (int fd, Elf64_Phdr phdr)
+static void load_segment (int fd, const struct elf64_phdr *phdr)
 {
 	size_t end, len, ps;
 	int prot = 0;
 	void *addr, *ptr;
 
 
-	if (phdr.p_filesz > phdr.p_memsz)
-		errx (1, "invalid program header: p_filesz > p_memsz");
+	if (phdr->filesz > phdr->memsz)
+		errx (1, "invalid program header: filesz > memsz");
 
 	ps = getpagesize ();
-	addr = (void *)(phdr.p_vaddr & ~(ps - 1));
-	len = phdr.p_memsz + phdr.p_vaddr - (size_t)addr;
+	addr = (void *)(phdr->vaddr & ~(ps - 1));
+	len = phdr->memsz + phdr->vaddr - (size_t)addr;
 
 	ptr = mmap (
 		addr,
@@ -49,52 +49,54 @@ static void load_segment (int fd, Elf64_Phdr phdr)
 	if (ptr == NULL)
 		err (1, "mmap()");
 
-	if (phdr.p_filesz > 0) {
-		lseek (fd, phdr.p_offset, SEEK_SET);
-		read (fd, (void *)phdr.p_vaddr, phdr.p_filesz);
+	if (phdr->filesz > 0) {
+		lseek (fd, phdr->offset, SEEK_SET);
+		read (fd, (void *)phdr->vaddr, phdr->filesz);
 	}
 
-	if (phdr.p_flags & (PF_R | PF_X))
+	if (phdr->flags & (PF_R | PF_X))
 		prot |= PROT_READ;
-	if (phdr.p_flags & PF_W)
+	if (phdr->flags & PF_W)
 		prot |= PROT_WRITE;
 	if (mprotect (addr, len, prot) != 0)
 		err (1, "mprotect()");
 
-	end = (phdr.p_vaddr + phdr.p_memsz + ps - 1) & ~(ps - 1);
+	end = (phdr->vaddr + phdr->memsz + ps - 1) & ~(ps - 1);
 	if (end > brkval)
 		brkval = end;
 }
 
 static void load_image (const char *filename)
 {
-	Elf64_Ehdr ehdr;
+	struct elf64_ehdr ehdr;
 	int fd;
 
 	fd = open (filename, O_RDONLY);
 	if (fd < 0)
 		err (1, "open('%s')", filename);
 
-	if (read (fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
-		err (1, "read('%s')", filename);
+	read_elf_ehdr (fd, &ehdr);
 
 	if (!is_executable (&ehdr))
 		errx (1, "Invalid argument");
 
-	pc = ehdr.e_entry;
+	pc = ehdr.entry;
 
-	for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
-		Elf64_Phdr phdr;
+	for (unsigned i = 0; i < ehdr.phnum; ++i) {
+		struct elf64_phdr phdr;
+		char buffer[sizeof (phdr)];
 
-		lseek (fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET);
-		if (read (fd, &phdr, ehdr.e_phentsize) != ehdr.e_phentsize)
+		lseek (fd, ehdr.phoff + i * ehdr.phentsize, SEEK_SET);
+		if (read (fd, buffer, ehdr.phentsize) != sizeof (buffer))
 			err (1, "failed to read program header %u", i);
 
-		switch (phdr.p_type) {
+		decode_elf64_phdr (&phdr, buffer);
+
+		switch (phdr.type) {
 		case PT_NULL:
 			break;
 		case PT_LOAD:
-			load_segment (fd, phdr);
+			load_segment (fd, &phdr);
 			break;
 		case PT_INTERP:
 		case PT_DYNAMIC:
blob - d565fc7a8b030875463a30066c3c5a63ca5fe009
blob + 9474a14e270beffd34ffdb1cb058ab2a21253438
--- src/linurv.h
+++ src/linurv.h
@@ -3,6 +3,7 @@
 #include <libelf.h>
 #include <stdio.h>
 #include <err.h>
+#include "data.h"
 
 enum log_level {
 	LOG_SILENT,	// don't print anything
@@ -74,7 +75,8 @@ void cpu_set (size_t reg, u64 val);
 void cpu_exec (u32 instr);
 void ecall (void);
 int my_execve (const char *path, char **argv, char **envp);
-int is_executable (const Elf64_Ehdr *);
+int is_executable (const struct elf64_ehdr *);
+void read_elf_ehdr (int fd, struct elf64_ehdr *);
 void logger (enum log_level, const char *, int, const char *, ...);
 void cpu_enter_signal (int sig, u64 handler);