Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Loader Implementation
- *
- * 2018, Operating Systems
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <unistd.h>
- #include "exec_parser.h"
- int fd;
- static so_exec_t *exec;
- struct sigaction signals;
- static struct sigaction old_action;
- static void segv_handler(int signum, siginfo_t *info, void *context) {
- so_seg_t *seg;
- so_seg_t *segment;
- uintptr_t addr;
- switch (signum) {
- case SIGSEGV:
- addr = (uintptr_t)info->si_addr;
- int found = 0;
- for(int i = 0; i < exec->segments_no; i++) {
- seg = exec->segments + i;
- if(seg->vaddr <= addr && addr <= (seg->vaddr + seg->mem_size)) {
- segment = seg;
- found = 1;
- }
- }
- if(found == 0) {
- goto default_h;
- }
- /*int index = (addr - segment->vaddr) / getpagesize();
- uintptr_t page = segment->vaddr + index * getpagesize();*/
- uintptr_t page = ALIGN_DOWN((uintptr_t)info->si_addr, getpagesize());
- uintptr_t offset_p = ALIGN_DOWN((uintptr_t)info->si_addr - segment->vaddr, getpagesize());
- if(page + getpagesize() <= (segment->vaddr + segment->file_size)) {
- void* rc = mmap((void *)page, getpagesize(), segment->perm,
- MAP_PRIVATE | MAP_FIXED, fd, segment->offset + offset_p);
- if(rc == MAP_FAILED) {
- goto default_h;
- }
- } else if(page <= (segment->vaddr + segment->file_size)) {
- void* rc = mmap((void *)page, getpagesize(), PROT_WRITE | PROT_READ,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, segment->offset + offset_p);
- if(rc == MAP_FAILED) {
- goto default_h;
- }
- lseek(fd, segment->offset + offset_p, SEEK_SET);
- read(fd, rc, segment->vaddr + segment->file_size - page);
- mprotect((void *)page, getpagesize(), segment->perm);
- } else if(page >= (segment->vaddr + segment->file_size)) {
- mmap((void *)page, getpagesize(), segment->perm,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, segment->offset + offset_p);
- }
- default:
- default_h:
- old_action.sa_sigaction(signum, info, context);
- }
- }
- int so_init_loader(void)
- {
- /* TODO: initialize on-demand loader */
- struct sigaction action;
- int rc;
- action.sa_flags = SA_SIGINFO;
- action.sa_sigaction = segv_handler;
- rc = sigaction(SIGSEGV, &action, &old_action);
- return rc;
- }
- int so_execute(char *path, char *argv[])
- {
- exec = so_parse_exec(path);
- if (!exec)
- return -1;
- fd = open(path, O_RDONLY);
- so_start_exec(exec, argv);
- return -1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement