Add more code on dynamic link testing

This commit is contained in:
Mark
2020-08-02 00:44:08 +03:00
parent 13c4ce7bda
commit ed786bffe6
5 changed files with 208 additions and 9 deletions
+1
View File
@@ -1,3 +1,4 @@
kernel-hdr
build
progs/rsh
etc/rc.d/99-imtesting
+16 -6
View File
@@ -1,7 +1,13 @@
CC?=$(CROSS_COMPILE)gcc
O=build
all: mkdirs $(O)/dyn $(O)/ld
CFLAGS=-Wall \
-Werror \
-Wextra \
-z max-page-size=0x1000 \
-O0
all: mkdirs $(O)/dyn $(O)/test $(O)/ld
mkdirs:
mkdir -p $(O)
@@ -9,20 +15,24 @@ mkdirs:
clean:
rm -rf $(O)
install: mkdirs $(O)/dyn $(O)/ld
install: mkdirs $(O)/dyn $(O)/test $(O)/ld
mkdir -p $(DESTDIR)/lib $(DESTDIR)/bin
install -D -m 0755 $(O)/dyn $(DESTDIR)/bin/
install -D -m 0755 $(O)/libfunc.so $(DESTDIR)/lib/
install -D -m 0755 $(O)/ld $(DESTDIR)/lib/
install -D -m 0755 $(O)/test $(DESTDIR)/bin/dyntest
$(O)/ld: ld.c
$(CC) -static -o $@ $+
$(O)/ld: ld.c ld-link.ld
$(CC) $(CFLAGS) -Tld-link.ld -static -o $@ ld.c
$(O)/libfunc.o: lib.c
$(CC) -fPIC -c -o $@ $<
$(CC) $(CFLAGS) -fPIC -c -o $@ $<
$(O)/libfunc.so: $(O)/libfunc.o
$(CROSS_COMPILE)ld -shared -o $@ $+
$(O)/test: test.c
$(CC) $(CFLAGS) -nostdlib -o $@ test.c
$(O)/dyn: dyn.c $(O)/libfunc.so
$(CC) -L$(O) -lfunc -o $@ dyn.c
$(CC) $(CFLAGS) -L$(O) -lfunc -o $@ dyn.c
+23
View File
@@ -0,0 +1,23 @@
ENTRY(_start);
SECTIONS {
. = 0x200000;
_ld_start = .;
.text : ALIGN(4K) {
*(.init .fini)
*(.text .text.*)
*(.rodata .rodata.*)
}
.data : ALIGN(4K) {
*(.ctors .dtors)
*(.data .data.*)
}
.bss : ALIGN(4K) {
*(.bss)
*(COMMON)
}
_ld_end = .;
}
+133 -3
View File
@@ -1,9 +1,139 @@
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include "elf.h"
int main(int argc, char **argv) {
fprintf(stderr, "Dynamic linking not yet implemented\n");
exit(-1);
extern char _ld_start, _ld_end;
struct object {
//FILE *fp;
int fd;
Elf64_Ehdr ehdr;
};
static int elf_read(struct object *obj, void *dst, size_t count, off_t pos) {
ssize_t bread;
if (lseek(obj->fd, pos, SEEK_SET) != pos) {
return -1;
}
if ((bread = read(obj->fd, dst, count)) < 0) {
return -1;
}
if ((size_t) bread != count) {
errno = ENOEXEC;
return -1;
}
return 0;
}
static struct object *object_open(const char *pathname) {
struct object *obj = calloc(1, sizeof(struct object));
obj->fd = open(pathname, O_RDONLY, 0);
if (obj->fd < 0) {
return NULL;
}
if (elf_read(obj, &obj->ehdr, sizeof(Elf64_Ehdr), 0) != 0) {
close(obj->fd);
free(obj);
return NULL;
}
return obj;
}
static void object_close(struct object *obj) {
close(obj->fd);
free(obj);
}
static int object_load(struct object *obj) {
Elf64_Phdr phdr;
printf("%u program headers\n", obj->ehdr.e_phnum);
for (size_t i = 0; i < obj->ehdr.e_phnum; ++i) {
off_t phoff = obj->ehdr.e_phoff + i * obj->ehdr.e_phentsize;
if (elf_read(obj, &phdr, obj->ehdr.e_phentsize, phoff) != 0) {
return -1;
}
switch (phdr.p_type) {
case PT_LOAD:
{
uintptr_t base = phdr.p_vaddr & ~0xFFF;
size_t size = (((phdr.p_vaddr + phdr.p_memsz + 0xFFF) & ~0xFFF) - base) / 0x1000;
if (base < (uintptr_t) &_ld_end) {
fprintf(stderr, "Segment will overwrite the loader code\n");
errno = ENOEXEC;
return -1;
}
void *addr = mmap((void *) base,
size * 0x1000,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
if (addr == MAP_FAILED) {
perror("mmap()");
return -1;
}
// Load filesz bytes
if (elf_read(obj, (void *) phdr.p_vaddr, phdr.p_filesz, phdr.p_offset) != 0) {
return -1;
}
// Zero (memsz - filesz) bytes
if (phdr.p_memsz > phdr.p_filesz) {
memset((void *) phdr.p_vaddr + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz);
}
}
break;
case PT_DYNAMIC:
fprintf(stderr, "TODO: handle dynamic binaries\n");
return -1;
}
}
return 0;
}
int main(int argc, char **argv) {
const char *prog;
struct object *program;
printf("_ld_start = %p, _ld_end = %p\n", &_ld_start, &_ld_end);
if (argc < 2) {
fprintf(stderr, "usage: %s PROGRAM [ARGS...]\n", argv[0]);
return -1;
}
prog = argv[1];
program = object_open(prog);
if (!program) {
fprintf(stderr, "Failed to load program: %s\n", prog);
return -1;
}
if (object_load(program) != 0) {
fprintf(stderr, "Failed to load object\n");
}
void (*entry) (void *p) = (void (*) (void *)) program->ehdr.e_entry;
object_close(program);
// TODO: form arg pointer like kernel does
entry(NULL);
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
static inline long __syscall3(long n, long a1, long a2, long a3) {
unsigned long ret;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n),"D"(a1),"S"(a2),"d"(a3)
:"rcx","r11","memory");
return ret;
}
static inline long __syscall1(long n, long a1) {
unsigned long ret;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n),"D"(a1)
:"rcx","r11","memory");
return ret;
}
char data[128] = {0};
void _start(void *arg) {
(void) arg;
const char *src = "abcde!\n";
for (long i = 0; i < 128; ++i) {
data[i] = src[i];
if (!src[i]) {
break;
}
}
__syscall3(1, 1, (long) data, 7);
__syscall1(60, 0);
while (1);
}