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 <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include "exec_parser.h"
- #define page_size sysconf(_SC_PAGE_SIZE)
- static so_exec_t *exec;
- static int fd;
- static void* sigsegv_handler(int signum, siginfo_t *info, void *ucontext)
- {
- int i;
- for (i = 0; i < exec->segments_no; ++i) {
- int addr_to_map = (int)info->si_addr;
- if (addr_to_map < exec->segments[i].vaddr +
- exec->segments[i].mem_size
- && addr_to_map >= exec->segments[i].vaddr) {
- if (exec->segments[i].data == NULL) {
- int nr = exec->segments[i].mem_size / page_size;
- exec->segments[i].data =
- (int *)calloc(nr + 1, sizeof(int));
- }
- int addr = exec->segments[i].vaddr;
- int page_count = 0;
- while (addr + page_size <= addr_to_map) {
- addr += page_size;
- page_count++;
- }
- int *p = exec->segments[i].data;
- if (p[page_count] != 0) {
- signal(SIGSEGV, SIG_DFL);
- raise(SIGSEGV);
- signal(SIGSEGV, (void *)(int)sigsegv_handler);
- }
- p[page_count] = 1;
- void *x = mmap((void *)addr, page_size,
- PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
- if (x < 0)
- return (void *)-1;
- void *read_buf = malloc(page_size);
- lseek(fd, exec->segments[i].offset +
- page_count * page_size, SEEK_SET);
- int to_read = page_size;
- if (addr + page_size >
- exec->segments[i].vaddr +
- exec->segments[i].file_size)
- to_read = exec->segments[i].file_size %
- page_size;
- if (addr > exec->segments[i].vaddr +
- exec->segments[i].file_size)
- to_read = 0;
- int rc = read(fd, read_buf, to_read);
- if (rc < 0)
- return (void *)-1;
- if (rc < page_size)
- memset(read_buf + rc, 0, page_size - rc);
- memcpy((void *)addr, read_buf, page_size);
- rc = mprotect((void *)addr, page_size,
- exec->segments[i].perm);
- free(read_buf);
- return 0;
- }
- }
- signal(SIGSEGV, SIG_DFL);
- raise(SIGSEGV);
- signal(SIGSEGV, (void *)(int)sigsegv_handler);
- return (void *)-1;
- }
- int so_init_loader(void)
- {
- /* TODO: initialize on-demand loader */
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = (void *)&sigsegv_handler;
- sa.sa_flags = SA_SIGINFO | SA_NODEFER;
- sigaction(SIGSEGV, &sa, NULL);
- return -1;
- }
- int so_execute(char *path, char *argv[])
- {
- exec = so_parse_exec(path);
- if (!exec)
- return -1;
- fd = open(path, O_RDONLY);
- if (fd < 0)
- exit(-1);
- so_start_exec(exec, argv);
- close(fd);
- return -1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement