Add more code on dynamic link testing
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
kernel-hdr
|
kernel-hdr
|
||||||
build
|
build
|
||||||
progs/rsh
|
progs/rsh
|
||||||
|
etc/rc.d/99-imtesting
|
||||||
|
|||||||
+16
-6
@@ -1,7 +1,13 @@
|
|||||||
CC?=$(CROSS_COMPILE)gcc
|
CC?=$(CROSS_COMPILE)gcc
|
||||||
O=build
|
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:
|
mkdirs:
|
||||||
mkdir -p $(O)
|
mkdir -p $(O)
|
||||||
@@ -9,20 +15,24 @@ mkdirs:
|
|||||||
clean:
|
clean:
|
||||||
rm -rf $(O)
|
rm -rf $(O)
|
||||||
|
|
||||||
install: mkdirs $(O)/dyn $(O)/ld
|
install: mkdirs $(O)/dyn $(O)/test $(O)/ld
|
||||||
mkdir -p $(DESTDIR)/lib $(DESTDIR)/bin
|
mkdir -p $(DESTDIR)/lib $(DESTDIR)/bin
|
||||||
install -D -m 0755 $(O)/dyn $(DESTDIR)/bin/
|
install -D -m 0755 $(O)/dyn $(DESTDIR)/bin/
|
||||||
install -D -m 0755 $(O)/libfunc.so $(DESTDIR)/lib/
|
install -D -m 0755 $(O)/libfunc.so $(DESTDIR)/lib/
|
||||||
install -D -m 0755 $(O)/ld $(DESTDIR)/lib/
|
install -D -m 0755 $(O)/ld $(DESTDIR)/lib/
|
||||||
|
install -D -m 0755 $(O)/test $(DESTDIR)/bin/dyntest
|
||||||
|
|
||||||
$(O)/ld: ld.c
|
$(O)/ld: ld.c ld-link.ld
|
||||||
$(CC) -static -o $@ $+
|
$(CC) $(CFLAGS) -Tld-link.ld -static -o $@ ld.c
|
||||||
|
|
||||||
$(O)/libfunc.o: lib.c
|
$(O)/libfunc.o: lib.c
|
||||||
$(CC) -fPIC -c -o $@ $<
|
$(CC) $(CFLAGS) -fPIC -c -o $@ $<
|
||||||
|
|
||||||
$(O)/libfunc.so: $(O)/libfunc.o
|
$(O)/libfunc.so: $(O)/libfunc.o
|
||||||
$(CROSS_COMPILE)ld -shared -o $@ $+
|
$(CROSS_COMPILE)ld -shared -o $@ $+
|
||||||
|
|
||||||
|
$(O)/test: test.c
|
||||||
|
$(CC) $(CFLAGS) -nostdlib -o $@ test.c
|
||||||
|
|
||||||
$(O)/dyn: dyn.c $(O)/libfunc.so
|
$(O)/dyn: dyn.c $(O)/libfunc.so
|
||||||
$(CC) -L$(O) -lfunc -o $@ dyn.c
|
$(CC) $(CFLAGS) -L$(O) -lfunc -o $@ dyn.c
|
||||||
|
|||||||
@@ -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
@@ -1,9 +1,139 @@
|
|||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
extern char _ld_start, _ld_end;
|
||||||
fprintf(stderr, "Dynamic linking not yet implemented\n");
|
|
||||||
exit(-1);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user