implement more syscalls
This commit is contained in:
parent
93d66e8a25
commit
0f7d978071
8 changed files with 175 additions and 65 deletions
BIN
a.out
BIN
a.out
Binary file not shown.
BIN
grep
Executable file
BIN
grep
Executable file
Binary file not shown.
6
myfile
6
myfile
|
@ -1 +1,5 @@
|
||||||
hello
|
stuff
|
||||||
|
stuff
|
||||||
|
stuff
|
||||||
|
something
|
||||||
|
stuff
|
BIN
sam
Executable file
BIN
sam
Executable file
Binary file not shown.
49
src/main.c
49
src/main.c
|
@ -1,4 +1,3 @@
|
||||||
#include "syscall.h"
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -18,12 +17,14 @@
|
||||||
#include "mach.h"
|
#include "mach.h"
|
||||||
#include "tos.h"
|
#include "tos.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
#define ALIGN(v, a) (((v) + (a) - 1) & ~((a) - 1))
|
#define ALIGN(v, a) (((v) + (a) - 1) & ~((a) - 1))
|
||||||
#define DONE_ERR(M_err, M_ret) do { fprintf(stderr, (M_err)); defer_status = (M_ret); goto done; } while(0)
|
#define DONE_ERR(M_err, M_ret) do { fprintf(stderr, (M_err)); defer_status = (M_ret); goto done; } while(0)
|
||||||
|
|
||||||
static char sud_intercept = SYSCALL_DISPATCH_FILTER_ALLOW;
|
static char sud_intercept = SYSCALL_DISPATCH_FILTER_ALLOW;
|
||||||
|
void *data_segment = NULL;
|
||||||
|
size_t data_segment_size = 0;
|
||||||
|
|
||||||
extern void start(uintptr_t entry, Tos* tos, int argc, char **argv);
|
extern void start(uintptr_t entry, Tos* tos, int argc, char **argv);
|
||||||
void enter(uintptr_t entry, int argc, char **argv)
|
void enter(uintptr_t entry, int argc, char **argv)
|
||||||
|
@ -45,14 +46,41 @@ void handle_sigsys(int sig, siginfo_t *info, void *ptr)
|
||||||
int64_t *sp = (int64_t *)gregs[REG_RSP];
|
int64_t *sp = (int64_t *)gregs[REG_RSP];
|
||||||
int64_t syscall = gregs[REG_RBP];
|
int64_t syscall = gregs[REG_RBP];
|
||||||
|
|
||||||
printf("syscall %ld\n", syscall);
|
/*
|
||||||
|
printf("0x%"PRIxPTR"\n", (uintptr_t)info->si_call_addr);
|
||||||
|
|
||||||
|
for (int i = -4; i < 3; i++)
|
||||||
|
printf("%d: 0x%"PRIxPTR"\n", i, sp[i]);
|
||||||
|
printf("donezo\n");
|
||||||
|
*/
|
||||||
|
|
||||||
switch (syscall) {
|
switch (syscall) {
|
||||||
case OPEN:
|
case OPEN:
|
||||||
ret = sys$open((char *)sp[1], (int)sp[2]);
|
ret = sys$open((char *)sp[1], (int)sp[2]);
|
||||||
break;
|
break;
|
||||||
|
case EXITS:
|
||||||
|
sys$exits((char *)sp[1]);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
case PREAD:
|
||||||
|
ret = sys$pread((int)sp[1], (void*)sp[2], (int64_t)sp[3], (int64_t)sp[4]);
|
||||||
|
break;
|
||||||
|
case PWRITE:
|
||||||
|
ret = sys$pwrite((int)sp[1], (void*)sp[2], (int64_t)sp[3], (int64_t)sp[4]);
|
||||||
|
break;
|
||||||
|
case CLOSE:
|
||||||
|
ret = sys$close((int)sp[1]);
|
||||||
|
break;
|
||||||
|
case BRK_:
|
||||||
|
ret = sys$brk((void*)sp[1], data_segment, &data_segment_size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unimplemented syscall %ld\n", syscall);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("ret = %ld\n", ret);
|
||||||
|
|
||||||
gregs[REG_RAX] = ret;
|
gregs[REG_RAX] = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +107,7 @@ int findlibc(struct dl_phdr_info *info, size_t size, void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *program_argv[] = {
|
static char *program_argv[] = {
|
||||||
"out",
|
"sam",
|
||||||
"../myfile",
|
"../myfile",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -93,7 +121,7 @@ int main()
|
||||||
size_t text_addr = 0x200000;
|
size_t text_addr = 0x200000;
|
||||||
size_t data_addr;
|
size_t data_addr;
|
||||||
|
|
||||||
f = fopen("../a.out", "rb");
|
f = fopen("../sam", "rb");
|
||||||
|
|
||||||
if (fread(&header, 1, sizeof(header), f) != sizeof(header)) {
|
if (fread(&header, 1, sizeof(header), f) != sizeof(header)) {
|
||||||
DONE_ERR("failed to read file header\n", 1);
|
DONE_ERR("failed to read file header\n", 1);
|
||||||
|
@ -109,6 +137,8 @@ int main()
|
||||||
|
|
||||||
data_addr = ALIGN(text_addr + header.text, 0x200000);
|
data_addr = ALIGN(text_addr + header.text, 0x200000);
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
size_t segments_size = sizeof(Exec) + header.text + header.data;
|
size_t segments_size = sizeof(Exec) + header.text + header.data;
|
||||||
file_segments = malloc(segments_size);
|
file_segments = malloc(segments_size);
|
||||||
if (!file_segments) {
|
if (!file_segments) {
|
||||||
|
@ -125,14 +155,15 @@ int main()
|
||||||
}
|
}
|
||||||
printf("mapped text segment at 0x%"PRIxPTR"\n", (uintptr_t)text_segment);
|
printf("mapped text segment at 0x%"PRIxPTR"\n", (uintptr_t)text_segment);
|
||||||
|
|
||||||
void *data_segment = mmap((void*)data_addr, header.data + header.bss, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
data_segment_size = header.data + header.bss;
|
||||||
|
data_segment = mmap((void*)data_addr, data_segment_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
if (!text_segment) {
|
if (!text_segment) {
|
||||||
DONE_ERR("failed to map data segment into memory\n", 1);
|
DONE_ERR("failed to map data segment into memory\n", 1);
|
||||||
}
|
}
|
||||||
printf("mapped data segment at 0x%"PRIxPTR"\n", (uintptr_t)data_segment);
|
printf("mapped data segment at 0x%"PRIxPTR"\n", (uintptr_t)data_segment);
|
||||||
|
|
||||||
memcpy(text_segment, file_segments, header.text);
|
memcpy(text_segment, file_segments, header.text + sizeof(Exec));
|
||||||
memcpy(data_segment, file_segments + sizeof(Exec) + header.text, header.data);
|
memcpy(data_segment, file_segments + header.text + sizeof(Exec), header.data);
|
||||||
|
|
||||||
if (dl_iterate_phdr(findlibc, NULL) != 1) {
|
if (dl_iterate_phdr(findlibc, NULL) != 1) {
|
||||||
DONE_ERR("failed to find libc and enable SUD\n", 1);
|
DONE_ERR("failed to find libc and enable SUD\n", 1);
|
||||||
|
@ -144,7 +175,7 @@ int main()
|
||||||
};
|
};
|
||||||
sigaction(SIGSYS, &sa, NULL);
|
sigaction(SIGSYS, &sa, NULL);
|
||||||
|
|
||||||
enter(header.entry32, 2, program_argv);
|
enter(header.entry32, 3, program_argv);
|
||||||
done:
|
done:
|
||||||
free(file_segments);
|
free(file_segments);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
|
@ -2,10 +2,30 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
|
char *errstr = NULL;
|
||||||
|
|
||||||
|
static int check_error(int ret)
|
||||||
|
{
|
||||||
|
if (ret < 0) {
|
||||||
|
errstr = strerror(errno);
|
||||||
|
fprintf(stderr, "errstr says: %s\n", errstr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int mode_open(char *name, int mode, int perm, int flag)
|
static int mode_open(char *name, int mode, int perm, int flag)
|
||||||
{
|
{
|
||||||
|
printf("open %s\n", name);
|
||||||
|
|
||||||
switch (mode & 3) {
|
switch (mode & 3) {
|
||||||
case 0: flag |= O_RDONLY; break;
|
case 0: flag |= O_RDONLY; break;
|
||||||
case 1: flag |= O_WRONLY; break;
|
case 1: flag |= O_WRONLY; break;
|
||||||
|
@ -22,7 +42,54 @@ static int mode_open(char *name, int mode, int perm, int flag)
|
||||||
|
|
||||||
int sys$open(char *path, int mode)
|
int sys$open(char *path, int mode)
|
||||||
{
|
{
|
||||||
printf("sys$open(0x%"PRIxPTR", %d)\n", (uintptr_t)path, mode);
|
return check_error(mode_open(path, mode, 0, 0));
|
||||||
|
}
|
||||||
return mode_open(path, mode, 0, 0);
|
|
||||||
|
int sys$exits(char *msg)
|
||||||
|
{
|
||||||
|
if (!msg) {
|
||||||
|
printf("program exited successfully\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("program exited with error message: %s\n", msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys$pread(int fd, void *buf, int64_t nbytes, int64_t offset)
|
||||||
|
{
|
||||||
|
if (offset < 0) {
|
||||||
|
return check_error(read(fd, buf, nbytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return check_error(pread(fd, buf, nbytes, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys$pwrite(int fd, void *buf, int64_t nbytes, int64_t offset)
|
||||||
|
{
|
||||||
|
if (fd != 1 && fd != 2) {
|
||||||
|
fprintf(stderr, "Oh no.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0) {
|
||||||
|
return check_error(write(fd, buf, nbytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return check_error(pwrite(fd, buf, nbytes, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys$close(int fd)
|
||||||
|
{
|
||||||
|
return check_error(close(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys$brk(void *addr, void *_data_segment, size_t *_data_segment_size)
|
||||||
|
{
|
||||||
|
size_t new_size = addr - _data_segment;
|
||||||
|
if (mremap(_data_segment, *_data_segment_size, new_size, 0) == MAP_FAILED) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*_data_segment_size = new_size;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
int sys$open(char *path, int mode);
|
int sys$open(char *path, int mode);
|
||||||
|
int sys$exits(char *msg);
|
||||||
|
int sys$pread(int fd, void *buf, int64_t nbytes, int64_t offset);
|
||||||
|
int sys$pwrite(int fd, void *buf, int64_t nbytes, int64_t offset);
|
||||||
|
int sys$close(int fd);
|
||||||
|
int sys$brk(void *addr, void *_data_segment, size_t *_data_segment_size);
|
||||||
|
|
Loading…
Reference in a new issue