#include "errno.h" #include "libc.h" #include "stdarg.h" #include "stddef.h" #include "sys/mman.h" #include "thread.h" #include "tiny.h" #include "unistd.h" int func_help() { printf("\nAvailable Commands:\n"); printf(" help: this help\n"); printf(" suicide: userspace self kill\n"); printf(" syscall5: a syscall with parameters over the stack \n"); printf(" alloc: test allocation\n"); printf(" tiny: a tiny C-like interpreter\n"); printf(" mmap: test mmap \n"); printf(" munmap: test munmap \n"); printf(" thread: run a user thread\n"); return 0; } int func_suicide() { printf("User is about to suicide\n"); int *yolo = 0; *yolo = 1; return 0; } char *initialHeap = 0; int func_alloc() { if (initialHeap == 0) { initialHeap = sbrk(0); } printf("Testing allocation\n"); int allocSize = 4096 * 2; char *currentHeap = sbrk(0); if (currentHeap - initialHeap < allocSize) { brk(initialHeap + allocSize); } int *allocatedData = (int *)initialHeap; for (unsigned int i = 0; i < allocSize / sizeof(int); i++) { allocatedData[i] = i; } printf("Success\nTesting malloc\n"); uintptr_t heap = (uintptr_t)sbrk(0); for (int i = 0; i < 12; i++) { void *ptr = malloc(1 << i); printf("malloc size %d: 0x%p\n", (1 << i), ptr); if (ptr == NULL) { printf("Malloc failed\n"); } memset(ptr, 0, 1 << i); free(ptr); } uintptr_t newHeap = (uintptr_t)sbrk(0); printf("Malloc used %dB\n", newHeap - heap); return 0; } struct mmapedArea { void *addr; size_t size; struct mmapedArea *next; }; static struct mmapedArea *listMmap = NULL; int func_mmap() { struct mmapedArea *area = (struct mmapedArea *)malloc(sizeof(struct mmapedArea)); if (area == NULL) { printf("Fail to allocate area\n"); return -1; } char *path = "/dev/zero"; void *mapAddr = mmap((void *)0, 4096, PROT_READ | PROT_WRITE, 0, path); if (mapAddr == MAP_FAILED) { printf("mmap failed errno %d\n", errno); return -1; } printf("Zero mmaped at %p\n", mapAddr); int data = *(int *)mapAddr; *(int *)mapAddr = data; area->addr = mapAddr; area->size = 4096; area->next = listMmap; listMmap = area; return 0; } int func_munmap() { if (!listMmap) { printf("Nothing to unmap... mmap first! \n"); return -1; } struct mmapedArea *area = listMmap; int ret = munmap(area->addr, area->size); if (ret) { printf("Fail to unmap area at 0x%p (size %d) error %d\n", area->addr, area->size, ret); return ret; } printf("unmap done\n"); listMmap = listMmap->next; free(area); return ret; } static void *print_hello(void *arg) { (void)arg; printf("Hello World from thread %lu\n", gettid()); usleep(100); return NULL; } int func_thread() { pthread_t id; void *retval; thread_create(&id, print_hello, NULL, 4096); thread_join(id, &retval); return 0; } int main(int argc, char *argv[]) { (void)argc; (void)argv; char buf[64]; assert(getpid() == gettid()); printf("Shell starting... type \"help\" for help\n"); while (1) { printf(">"); if (readline(buf, sizeof(buf))) continue; if (strcmp(buf, "help") == 0) { func_help(); continue; } if (strcmp(buf, "suicide") == 0) { func_suicide(); continue; } if (strcmp(buf, "syscall5") == 0) { testSycall5(1, 2, 3, 4, 5); continue; } if (strcmp(buf, "alloc") == 0) { func_alloc(); continue; } if (strcmp(buf, "tiny") == 0) { pthread_t id; void *retval; thread_create(&id, func_tiny, NULL, 4096); thread_join(id, &retval); continue; } if (strcmp(buf, "mmap") == 0) { func_mmap(); continue; } if (strcmp(buf, "munmap") == 0) { func_munmap(); continue; } if (strcmp(buf, "thread") == 0) { func_thread(); continue; } } return 0; }