diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2022-12-14 18:26:49 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2022-12-14 18:26:49 +0100 |
| commit | d179f1846f9372920ef02f08cfb4d3abe99b383f (patch) | |
| tree | 4b6ddc71566be95a1ce520ef9d957f4cac1af6c9 /lib | |
first commit
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/README.md | 4 | ||||
| -rw-r--r-- | lib/avl_tree/avl_tree.c | 463 | ||||
| -rw-r--r-- | lib/avl_tree/avl_tree.h | 52 | ||||
| -rw-r--r-- | lib/cstr/cstr.c | 353 | ||||
| -rw-r--r-- | lib/cstr/cstr.h | 23 | ||||
| -rw-r--r-- | lib/malloc/malloc.c | 187 | ||||
| -rw-r--r-- | lib/malloc/malloc.h | 9 | ||||
| -rw-r--r-- | lib/sys/brk.h | 10 | ||||
| -rw-r--r-- | lib/sys/execve.h | 11 | ||||
| -rw-r--r-- | lib/sys/mmap.h | 17 | ||||
| -rw-r--r-- | lib/sys/munmap.h | 9 | ||||
| -rw-r--r-- | lib/sys/read.h | 9 | ||||
| -rw-r--r-- | lib/sys/reboot.h | 21 | ||||
| -rw-r--r-- | lib/sys/sbrk.h | 10 | ||||
| -rw-r--r-- | lib/sys/sizes.h | 16 | ||||
| -rw-r--r-- | lib/sys/start.S | 6 | ||||
| -rw-r--r-- | lib/sys/stat.h | 62 | ||||
| -rw-r--r-- | lib/sys/syscalls.h | 336 | ||||
| -rw-r--r-- | lib/sys/time.h | 11 | ||||
| -rw-r--r-- | lib/sys/write.h | 10 |
20 files changed, 1619 insertions, 0 deletions
diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..7c4c97b --- /dev/null +++ b/lib/README.md @@ -0,0 +1,4 @@ +# stdlib for sll + +Use the [scrubs](https://nathanreiner.xyz/git/scrubs) tool to read its +documentation. diff --git a/lib/avl_tree/avl_tree.c b/lib/avl_tree/avl_tree.c new file mode 100644 index 0000000..db3e44e --- /dev/null +++ b/lib/avl_tree/avl_tree.c @@ -0,0 +1,463 @@ +#include "avl_tree.h" +#include "../malloc/malloc.h" + +avl_tree_node_t *__new_avl_tree_node(avl_tree_node_t *parent, void *value); +void __free_avl_tree_node(avl_tree_t *tree, avl_tree_node_t *node); +void __avl_tree_rebalance(avl_tree_node_t *node); + +/** DOC + * @type function + * @name new_avl_tree + * + * @param u8(*compare)(void*, void*) + * @return avl_tree_t* + * + * @description + * Creates a new empty AVL-Tree. + */ +avl_tree_t *new_avl_tree(i8(*compare)(void*, void*), u8 free_value) +{ + avl_tree_t *tree = malloc(sizeof(avl_tree_t)); + tree->root = 0; + tree->size = 0; + tree->compare = compare; + tree->free_value = free_value; + + return tree; +} + + +/** DOC + * @type function + * @name free_avl_tree + * + * @param avl_tree_t *tree + * + * @description + * Frees a given `avl_tree_t`. + */ +void free_avl_tree(avl_tree_t *tree) +{ + if (tree->root) + __free_avl_tree_node(tree, tree->root); + + free(tree); +} + + +/** DOC + * @type function + * @name avl_tree_search + * + * @param avl_tree_t *tree + * @param void *value + * @return void* + * + * @description + * Searches the value returns it when found. + * Returns `0` if node was not found. + */ +void *avl_tree_search(avl_tree_t *tree, void *value) +{ + if (!tree->root) + return 0; + + avl_tree_node_t *current = tree->root; + u8 factor = tree->compare(current->value, value); + + while (current->left || current->right) { + factor = tree->compare(current->value, value); + + switch (factor) { + case (u8)1: current = current->right; break; + case (u8)0: return current->value; break; + case (u8)-1: current = current->left; break; + } + } + + factor = tree->compare(current->value, value); + if (!factor) + return current->value; + + return 0; +} + + +/** DOC + * @type function + * @name avl_tree_insert + * + * @param avl_tree_t *tree + * @param void *value + * + * @description + * Inserts `value` into `tree`. + * If `value` is equal to a node according to `tree->compare` + * the `value` of the node is overwritten by `value`. + */ +void avl_tree_insert(avl_tree_t *tree, void *value) +{ + avl_tree_node_t *current = tree->root; + avl_tree_node_t *last = current; + u8 factor = 0; + + if (current) + factor = tree->compare(current->value, value); + + while (current && (current->left || current->right)) { + factor = tree->compare(current->value, value); + current->balance_factor += factor; + last = current; + + switch (factor) { + case (u8)1: current = current->right; break; + case (u8)0: + free(current->value); + current->value = value; + current = 0; + break; + case (u8)-1: current = current->left; break; + } + } + + if (factor) { + ++tree->size; + current = __new_avl_tree_node(last, value); + + switch (factor) { + case (u8)1: last->right = current; break; + case (u8)-1: last->left = current; break; + } + } else if (!last) { + ++tree->size; + current = __new_avl_tree_node(0, value); + tree->root = current; + } + + if (factor || !last) + __avl_tree_rebalance(current); + else { + while (current->parent) { + current = current->parent; + current->balance_factor -= tree->compare(current->value, value); + } + } +} + + +/* DOC + * @type function + * @name avl_tree_remove + * + * @param avl_tree_t *tree + * @param void *value + * + * @description + * Removes `value` from tree if exists. + */ +void avl_tree_remove(avl_tree_t *tree, void *value) +{ + avl_tree_node_t *current = tree->root; + avl_tree_node_t *last = current; + u8 factor = 0; + + if (current) + factor = tree->compare(current->value, value); + + while (current && (current->left || current->right)) { + factor = tree->compare(current->value, value); + current->balance_factor -= factor; + last = current; + + switch (factor) { + case (u8)1: current = current->right; break; + case (u8)0: current = 0; break; + case (u8)-1: current = current->left; break; + } + } + + if (!factor) { + --tree->size; + + avl_tree_node_t *next; + avl_tree_node_t *parent; + + if (last->right) { + next = last->right; + + while (next->left) + next = next->left; + + next->parent->left = next->right; + if (next->right) + next->right->parent = next->parent; + + next->left = last->left; + if (last->left) + last->left->parent = next; + + } else if (last->left) { + next = last->left; + + while (next->right) + next = next->right; + + next->parent->right = next->left; + if (next->left) + next->left->parent = next->parent; + + next->right = last->right; + if (last->right) + last->right->parent = next; + } + + next->parent = last->parent; + + if (last->parent) { + if (last->parent->left == last) + last->parent->left = next; + else + last->parent->right = next; + } + + last->right = 0; + last->left = 0; + + __free_avl_tree_node(tree, last); + + __avl_tree_rebalance(parent); + } else { + while (current->parent) { + current = current->parent; + current->balance_factor += tree->compare(current->value, value); + } + } +} + + +/** DOC + * @type function + * @name __new_avl_tree_node + * + * @param avl_tree_node_t *parent + * @param void *value + * @return avl_tree_node_t* + * + * @description + * Creates a new `avl_tree_node_t` + */ +avl_tree_node_t *__new_avl_tree_node(avl_tree_node_t *parent, void *value) +{ + avl_tree_node_t *node = malloc(sizeof(avl_tree_node_t)); + node->left = 0; + node->right = 0; + node->balance_factor = 0; + node->parent = parent; + node->value = value; + + return node; +} + + +/** DOC + * @type function + * @name __free_avl_tree_node + * + * @param avl_tree_node_t *node + * + * @description + * Frees a `avl_tree_node_t` recurlively. + */ +void __free_avl_tree_node(avl_tree_t *tree, avl_tree_node_t *node) +{ + if (node) { + if (node->left) + __free_avl_tree_node(tree, node->left); + if (node->right) + __free_avl_tree_node(tree, node->right); + + if (tree->free_value) + free(node->value); + free(node); + } +} + + +/** DOC + * @type function + * @name __avl_tree_rebalance + * + * @param avl_tree_node_t *node + * + * @description + * Rebalances the tree from the `node` upwards. + */ +void __avl_tree_rebalance(avl_tree_node_t *node) +{ + while (node) { + if (node->balance_factor == 2) { + avl_tree_node_t *parent = node->parent; + avl_tree_node_t *right = node->right; + + if (parent->left == node) + parent->left = right; + else + parent->right = right; + + right->parent = parent; + + node->right = right->left; + right->left = node; + + node->balance_factor = 0; + right->balance_factor = 0; + } else if (node->balance_factor == -2) { + avl_tree_node_t *parent = node->parent; + avl_tree_node_t *left= node->left; + + if (parent->left == node) + parent->left = left; + else + parent->right = left; + + left->parent = parent; + + node->left = left->right; + left->right = node; + + node->balance_factor = 0; + left->balance_factor = 0; + } + + node = node->parent; + } +} + +/** DOC + * @type function + * @name <type>_compare + * + * @param void *a + * @param void *b + * @return i8 + * + * @description + * This functions compare `u8 - u64` and `i8 - i64` values + * for the generic avl_tree implementation. In this way + * the avl_tree can hold any type. + * + * A compare function returns the following values: + * `-1 <=> a < b` + * `0 <=> a = b` + * `1 <=> a > b` + */ +i8 u8_compare(void *a, void *b) +{ + u8 x = *((u8*)a); + u8 y = *((u8*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 i8_compare(void *a, void *b) +{ + i8 x = *((i8*)a); + i8 y = *((i8*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 u16_compare(void *a, void *b) +{ + u16 x = *((u16*)a); + u16 y = *((u16*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 i16_compare(void *a, void *b) +{ + i16 x = *((i16*)a); + i16 y = *((i16*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 u32_compare(void *a, void *b) +{ + u32 x = *((u32*)a); + u32 y = *((u32*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 i32_compare(void *a, void *b) +{ + i32 x = *((i32*)a); + i32 y = *((i32*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 u64_compare(void *a, void *b) +{ + u64 x = *((u64*)a); + u64 y = *((u64*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} + + +i8 i64_compare(void *a, void *b) +{ + i64 x = *((i64*)a); + i64 y = *((i64*)b); + + if (x < y) + return -1; + else if (x == y) + return 0; + else + return 1; +} diff --git a/lib/avl_tree/avl_tree.h b/lib/avl_tree/avl_tree.h new file mode 100644 index 0000000..2f0563a --- /dev/null +++ b/lib/avl_tree/avl_tree.h @@ -0,0 +1,52 @@ +#ifndef AVL_TREE_H +#define AVL_TREE_H + +#include "../sys/sizes.h" + +typedef struct avl_tree_node_t__ { + i8 balance_factor; + struct avl_tree_node_t__ *parent; + struct avl_tree_node_t__ *left; + struct avl_tree_node_t__ *right; + void *value; +} avl_tree_node_t; + +/** DOC + * @type typename + * @name avl_tree_t + * + * @member avl_tree_node_t *root + * @member u64 size + * @member u8(*compare)(void*, void*) + * + * @description + * This type describes the head of an `avl_tree_t` + * It contains its `size` and holds its `root`. + * Additionally it holds the `compare` function + * which is used for having a custom order of elements. + * To use the normal order for an `avl_tree_t` just holding + * integers use the `<type>_compare` functions given by this header. + */ +typedef struct { + avl_tree_node_t *root; + u64 size; + i8(*compare)(void*, void*); + u8 free_value; +} avl_tree_t; + +avl_tree_t *new_avl_tree(i8(*compare)(void*, void*), u8 free_value); +void free_avl_tree(avl_tree_t *tree); +void *avl_tree_search(avl_tree_t *tree, void *value); +void avl_tree_insert(avl_tree_t *tree, void *value); +void avl_tree_remove(avl_tree_t *tree, void *value); + +i8 u8_compare(void*, void*); +i8 i8_compare(void*, void*); +i8 u16_compare(void*, void*); +i8 i16_compare(void*, void*); +i8 u32_compare(void*, void*); +i8 i32_compare(void*, void*); +i8 u64_compare(void*, void*); +i8 i64_compare(void*, void*); + +#endif diff --git a/lib/cstr/cstr.c b/lib/cstr/cstr.c new file mode 100644 index 0000000..fcb91f4 --- /dev/null +++ b/lib/cstr/cstr.c @@ -0,0 +1,353 @@ +#include "cstr.h" + +/** DOC + * @type function + * @name string_length + * + * @param char *str + * @return u64 + * + * @description + * Computes the length of an `ASCII` cstr. + */ +u64 cstr_length(const char *str) +{ + const char *p = str; + while (*p) ++p; + return p - str; +} + + +/** DOC + * @type function + * @name cstr_compare + * + * @param const char *a + * @param const char *b + * @return u8 + * + * @description + * Compares two strings. + * Returns 1 if a has a higher alphabethical value. + * Returns -1 if a has a lower alphabethical value. + * Returns 0 if strings are equal. + */ +i8 cstr_compare(const char *a, const char *b) +{ + while (*a && *b) { + if (*a < *b) + return -1; + if (*a > *b) + return 1; + + ++a; + ++b; + } + + if (*a < *b) + return -1; + if (*a > *b) + return 1; + + return 0; +} + + +/** DOC + * @type function + * @name cstr_split + * + * @param char *cstr + * @param char split + * @return u64 + * + * @description + * Splits a string on every `split` char. + * Returns the number of splits. + * ``WARNING`` This function does replace all `split` char with `0`. + * The old string does not exist after calling this function. + */ +u64 cstr_split(char *cstr, char split) +{ + u64 splits = 1; + + while (*cstr) { + if (*cstr == split) { + *cstr = 0; + ++splits; + } + + ++cstr; + } + + return splits; +} + + +/** DOC + * @type function + * @name next_split + * + * @param const char *previous; + * @return const char* + * + * @description + * Returns the next split of a `split list` created by `cstr_split`. + */ +const char *next_split(const char *previous) +{ + while (*previous) ++previous; + return previous + 1; +} + + +/** DOC + * @type function + * @name strip_front + * + * @param char *cstr + * @param char strip + * @return u64 + * + * @description + * Remove `strip` from front. + */ +u64 strip_front(char *cstr, char strip) +{ + char *front = cstr; + + while (*front && *front == strip) ++front; + + while (*front) { + *cstr = *front; + ++cstr; + ++front; + } + + while (*cstr) { + *cstr = 0; + ++cstr; + } + + return front - cstr; +} + + +/** DOC + * @type function + * @name strip_back + * + * @param char *cstr + * @param char stip + * @return u64 + * + * @description + * Removes `strip` char from back of the cstr. + */ +u64 strip_back(char *cstr, char strip) +{ + u64 diff = 0; + + while (*cstr) ++cstr; + --cstr; + + while (*cstr == strip) { + *cstr = 0; + ++diff; + } + + return diff; +} + +/** DOC + * @type function + * @name strip_cstr + * + * @param char *cstr + * @param char strip + * @return u64 + * + * @description + * Strips `strip` char from start and end of the string. + */ +u64 strip_cstr(char *cstr, char strip) +{ + return strip_front(cstr, strip) + strip_back(cstr, strip); +} + +/* DOC + * @type function + * @name string_utf8_length + * + * @param char *str + * @return u64 + * + * @description + * Computes the length of a `UTF-8` cstr. + */ +u64 cstr_utf8_length(const char * str) +{ + const char *p = str; + u64 length = 0; + int a = 0; + + while (*p) { + next_utf8(&p); + ++length; + } + + return length; +} + + +/** DOC + * @type function + * @name next_utf8 + * + * @param char **c + * @return u8 + * + * @description + * Set `c` to the next `UTF-8` char. + * Returns the difference relative to `ASCII` chars. + */ +u8 next_utf8(const char **c) +{ + int a; + + switch (**c & 0xf0) { + case 0xf0: a = 4; break; + case 0xe0: a = 3; break; + case 0xc0: a = 2; break; + default: a = 1; break; + } + + *c += a; + return a; +} + +/** DOC + * @type function + * @name previous_utf8 + * + * @param char **c + * @return u8 + * + * @description + * Set `c` to the previous `UTF-8` char. + * Returns the difference relative to `ASCII` chars. + */ +u8 previous_utf8(const char **c) +{ + int a = 1; + --(*c); + + while ((**c & 0xc0) == 0x80) { + --(*c); + ++a; + } + + return a; +} + +/** DOC + * @type function + * @name u64_to_cstr + * + * @param u64 n + * @param char *cstr + * @param u64 length + * + * @description + * Writes the string representation of `n` to the `cstr`. + */ +void u64_to_cstr(u64 n, char *cstr, u64 length) +{ + char *p = cstr + length - 1; + u64 d; + int i = 0; + + for (;n && i < length; ++i) { + *(p--) = (n % 10) + '0'; + n /= 10; + } + + d = p - cstr; + + for (i = 0; i < length - d; ++i) + cstr[i] = cstr[i + d]; +} + +/** DOC + * @type function + * @name i64_to_cstr + * + * @param i64 n + * @param char *cstr + * @param u64 length + * + * @description + * Writes the string representation of `n` to the `cstr`. + */ +void i64_to_cstr(i64 n, char *cstr, u64 length) +{ + if (n < 0) { + *cstr = '-'; + n = -n; + u64_to_cstr((u64)n, cstr + 1, length - 1); + } else { + u64_to_cstr((u64)n, cstr, length); + } +} + +/** DOC + * @type function + * @name cstr_to_u64 + * + * @param const char *cstr + * @return u64 + * + * @description + * Parses an `u64` to cstr. + */ +u64 cstr_to_u64(const char *cstr) +{ + u64 n = 0; + u64 e = 1; + const char *p = cstr; + + while (*p) { + if ((const unsigned char)(*p - '0') > 9) + return 0; + ++p; + } + + --p; + + while (p >= cstr) { + n += (*p - '0') * e; + e *= 10; + --p; + } + + return n; +} + + +/** DOC + * @type function + * @name cstr_to_i64 + */ +i64 cstr_to_i64(const char *cstr) +{ + i64 n = 0; + + if (*cstr == '-') { + n = (i64)cstr_to_u64(cstr + 1); + n = -n; + } else { + n = (i64)cstr_to_u64(cstr); + } + + return n; +} diff --git a/lib/cstr/cstr.h b/lib/cstr/cstr.h new file mode 100644 index 0000000..80dc359 --- /dev/null +++ b/lib/cstr/cstr.h @@ -0,0 +1,23 @@ +#ifndef CSTR_H +#define CSTR_H + +#include "../sys/sizes.h" + +u64 cstr_length(const char *); +i8 cstr_compare(const char *a, const char *b); +u64 cstr_split(char *cstr, char split); +const char *next_split(const char *previous); +u64 strip_front(char *cstr, char strip); +u64 strip_back(char *cstr, char strip); +u64 strip_cstr(char *cstr, char strip); + +u64 cstr_utf8_length(const char *); +u8 next_utf8(const char **); +u8 previous_utf8(const char **); + +void u64_to_cstr(u64 n, char *cstr, u64 length); +void i64_to_cstr(i64 n, char *cstr, u64 length); +u64 cstr_to_u64(const char *cstr); +i64 cstr_to_i64(const char *cstr); + +#endif diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c new file mode 100644 index 0000000..a0e9ebf --- /dev/null +++ b/lib/malloc/malloc.c @@ -0,0 +1,187 @@ +#include "malloc.h" + +#include "../sys/brk.h" + +/** DOC + * @type typename + * @name segment_t + * + * @member void *ptr + * @member u64 size + * @member u8 free + * @member segment_t *next + * + * @description + * A segment is a meta block for an allocated area. + * It contains the pointer `(void *ptr)` for the memory location + * its size and if its free `(u8 free)`. + * The segment_t is a single linked list node because of that + * it also holds a `(segment_t *next)` pointer to the next segment. + */ +typedef struct __segment_t { + void *ptr; + u64 size; + u8 free; + struct __segment_t *next; +} segment_t; + + +/** DOC + * @type instance + * @name mbrk + * + * @member u64 initial + * @member u64 current + * @member segment_t *first + * @member segment_t *last + * + * @description + * The mbrk instance holds the current brk `(see [man 2 brk])` + * and the first and last element of the segement list. + */ +struct __break { + u64 initial; + u64 current; + segment_t *first; + segment_t *last; +} mbrk = { + .initial = 0, + .current = 0, + .first = 0, + .last = 0 +}; + + +void __initialize_memory(); +segment_t *__find_free_segment(u64 size); +segment_t *__allocate_new(u64 size); + + +/** DOC + * @type function + * @name malloc + * + * @param u64 size + * @return void* + * + * @description + * Allocates memory. If there is no space left requests new space. + */ +void* malloc(u64 size) +{ + segment_t *seg; + + if (!mbrk.initial) + __initialize_memory(); + + seg = __find_free_segment(size); + + if (!seg) + seg = __allocate_new(size); + + seg->free = 0; + return seg->ptr; +} + + +/** DOC + * @type function + * @name free + * + * @param void *ptr + * @return void + * + * @description + * Frees the memory allocated by `malloc`. + * + * ``IMPORTANT`` this function does not free the memory to be accessible + * for the whole system. The freed memory is only accessible for the current + * process and is released on exit. + */ +void free(void *ptr) +{ + segment_t * seg = mbrk.first; + + for (; seg; seg = seg->next) { + if (ptr == seg->ptr) { + seg->free = 1; + break; + } + } +} + + +/** DOC + * @type function + * @name __initialize_memory + * + * @description + * Initalizes `mbrk` by calling `brk(0)`. + * Is only called if `mbrk.initial` is zero. + */ +void __initialize_memory() +{ + mbrk.initial = brk(0); + mbrk.current = mbrk.initial; +} + + +/** DOC + * @type function + * @name __find_free_segment + * + * @param u64 size + * @return segment_t* + * + * @description + * Searches a segment with the given `size` in + * the segment linked-list. + * If there is no such segment it returns `0` + */ +segment_t *__find_free_segment(u64 size) +{ + segment_t * seg = mbrk.first; + + for (; seg; seg = seg->next) { + if (seg->free && size == seg->size) + return seg; + } + + return 0; +} + +/** DOC + * @type function + * @name __allocate_new + * + * @param u64 size + * @return segment_t* + * + * @description + * Allocates a new segement. + * This function is only called if no free segment with + * the given `size` was found. A new segment is allocated + * by using the `brk` syscall and adding `size + sizeof(segment_t)` + * new memory to the process. + */ +segment_t *__allocate_new(u64 size) +{ + u64 last = mbrk.current; + mbrk.current += size + sizeof(segment_t); + brk((void*)mbrk.current); + + segment_t *seg = (segment_t*)last; + seg->ptr = (void*)(mbrk.current - size); + seg->size = size; + seg->free = 0; + seg->next = 0; + + if (!mbrk.first) + mbrk.first = seg; + else + mbrk.last->next = seg; + + mbrk.last = seg; + + return seg; +} diff --git a/lib/malloc/malloc.h b/lib/malloc/malloc.h new file mode 100644 index 0000000..d4896bf --- /dev/null +++ b/lib/malloc/malloc.h @@ -0,0 +1,9 @@ +#ifndef MALLOC_H +#define MALLOC_H + +#include "../sys/sizes.h" + +void * malloc(u64 size); +void free(void * ptr); + +#endif diff --git a/lib/sys/brk.h b/lib/sys/brk.h new file mode 100644 index 0000000..d2221a2 --- /dev/null +++ b/lib/sys/brk.h @@ -0,0 +1,10 @@ +#ifndef BRK_H +#define BRK_H + +#include "syscalls.h" + +static unsigned long brk(void * addr) { + return syscall(BRK, addr); +} + +#endif diff --git a/lib/sys/execve.h b/lib/sys/execve.h new file mode 100644 index 0000000..04d6dea --- /dev/null +++ b/lib/sys/execve.h @@ -0,0 +1,11 @@ +#ifndef EXECVE_H +#define EXECVE_H + +#include "syscalls.h" + +int execve(const char *pathname, char *const argv[], char *const envp[]) +{ + return syscall(EXECVE, pathname, argv, envp); +} + +#endif diff --git a/lib/sys/mmap.h b/lib/sys/mmap.h new file mode 100644 index 0000000..7e885c4 --- /dev/null +++ b/lib/sys/mmap.h @@ -0,0 +1,17 @@ +#ifndef MMAP_H +#define MMAP_H +#include "syscalls.h" + +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 +#define PROT_NONE 0x0 + +#define MAP_SHARED 0x1 +#define MAP_PRIVATE 0x2 + +static void * mmap(void * addr, unsigned long size, int prot, int flags, int fd, int offset) { + return syscall(MMAP, size, prot, flags, fd, offset); +} + +#endif diff --git a/lib/sys/munmap.h b/lib/sys/munmap.h new file mode 100644 index 0000000..4a876d6 --- /dev/null +++ b/lib/sys/munmap.h @@ -0,0 +1,9 @@ +#ifndef MUNMAP_H +#define MUNMAP_H +#include "syscall.h" + +static int munmap(void * addr, unsigned long size) { + return syscall(MUNMAP, addr, size); +} + +#endif diff --git a/lib/sys/read.h b/lib/sys/read.h new file mode 100644 index 0000000..7dba6e7 --- /dev/null +++ b/lib/sys/read.h @@ -0,0 +1,9 @@ +#ifndef READ_H +#define READ_H +#include "syscalls.h" + +static int read(unsigned int fd, char * buf, unsigned long count) { + return syscall(READ, fd, buf, count, 0, 0); +} + +#endif diff --git a/lib/sys/reboot.h b/lib/sys/reboot.h new file mode 100644 index 0000000..fd119c5 --- /dev/null +++ b/lib/sys/reboot.h @@ -0,0 +1,21 @@ +#ifndef SHUTDOWN_H +#define SHUTDOWN_H + +#include "syscalls.h" + +#define REBOOT_HALT_SYSTEM 0xcdef0123 +#define REBOOT_HARD_RESET 0x01234567 +#define REBOOT_ENABLE_CAD 0x89abcdef +#define REBOOT_DISABLE_CAD 0 +#define REBOOT_POWEROFF 0x4321fedc +#define REBOOT_SUSPEND 0xd000fce2 +#define REBOOT_NEW_KERNEL 0x45584543 + +static int reboot(int cmd) { + const int magic1 = 0xfee1dead; + const int magic2 = 537993216; + + return syscall((void*)REBOOT, magic1, magic2, cmd, 0); +} + +#endif diff --git a/lib/sys/sbrk.h b/lib/sys/sbrk.h new file mode 100644 index 0000000..25d9c6c --- /dev/null +++ b/lib/sys/sbrk.h @@ -0,0 +1,10 @@ +#ifndef SBRK_H +#define SBRK_H + +#include "syscalls.h" + +static int brk(void * addr) { + return syscall(BRK, addr); +} + +#endif diff --git a/lib/sys/sizes.h b/lib/sys/sizes.h new file mode 100644 index 0000000..127d483 --- /dev/null +++ b/lib/sys/sizes.h @@ -0,0 +1,16 @@ +#ifndef SIZES_H +#define SIZES_H + +typedef signed char i8; +typedef unsigned char u8; + +typedef signed short int i16; +typedef unsigned short int u16; + +typedef signed int i32; +typedef unsigned int u32; + +typedef signed long int i64; +typedef unsigned long int u64; + +#endif diff --git a/lib/sys/start.S b/lib/sys/start.S new file mode 100644 index 0000000..deafd67 --- /dev/null +++ b/lib/sys/start.S @@ -0,0 +1,6 @@ +.global _start +_start: + call main + mov %rax, %rdi + mov $60, %rax + syscall diff --git a/lib/sys/stat.h b/lib/sys/stat.h new file mode 100644 index 0000000..02bdc48 --- /dev/null +++ b/lib/sys/stat.h @@ -0,0 +1,62 @@ +#ifndef STAT_H +#define STAT_H + +#include "sizes.h" +#include "time.h" +#include "syscalls.h" + +#define S_IFMT 0170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 + +#define S_ISUID 04000 +#define S_ISGID 02000 +#define S_ISVTX 01000 + +#define S_IRWXU 00700 + +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 + +#define S_IRWXG 00070 + +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 + +#define S_IRWXO 00007 + +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 + +struct stat { + i64 dev; + i64 ino; + u64 nlink; + u32 mode; + u32 uid; + u32 gid; + u64 rdev; + u64 size; + u64 blksize; + i64 blocks; + + struct timespec atime; + struct timespec mtime; + struct timespec ctime; + + u64 __[3]; +}; + +static int stat(const char * filename, struct stat * statbuf) { + return syscall(STAT, filename, statbuf); +} + +#endif diff --git a/lib/sys/syscalls.h b/lib/sys/syscalls.h new file mode 100644 index 0000000..03ce997 --- /dev/null +++ b/lib/sys/syscalls.h @@ -0,0 +1,336 @@ +#ifndef SYSCALLS_H +#define SYSCALLS_H + +__asm__ ( + "syscall:\n" + "endbr64\n" + "mov %rdi, %rax\n" + "mov %rsi, %rdi\n" + "mov %rdx, %rsi\n" + "mov %rcx, %rdx\n" + "mov %r8, %rcx\n" + "mov %r9, %r8\n" + "mov 8(%rsp), %r9\n" + "syscall\n" + "ret\n" +); + +enum { + READ, + WRITE, + OPEN, + CLOSE, + STAT, + FSTAT, + LSTAT, + POLL, + LSEEK, + MMAP, + MPROTECT, + MUNMAP, + BRK, + RT_SIGACTION, + RT_SIGPROCMASK, + RT_SIGRETURN, + IOCTL, + PREAD64, + PWRITE64, + READV, + WRITEV, + ACCESS, + PIPE, + SELECT, + SCHED_YIELD, + MREMAP, + MSYNC, + MINCORE, + MADVISE, + SHMGET, + SHMAT, + SHMCTL, + DUP, + DUP2, + PAUSE, + NANOSLEEP, + GETITIMER, + ALARM, + SETITIMER, + GETPID, + SENDFILE, + SOCKET, + CONNECT, + ACCEPT, + SENDTO, + RECVFROM, + SENDMSG, + RECVMSG, + SHUTDOWN, + BIND, + LISTEN, + GETSOCKNAME, + GETPEERNAME, + SOCKETPAIR, + SETSOCKOPT, + GETSOCKOPT, + CLONE, + FORK, + VFORK, + EXECVE, + EXIT, + WAIT4, + KILL, + UNAME, + SEMGET, + SEMOP, + SEMCTL, + SHMDT, + MSGGET, + MSGSND, + MSGRCV, + MSGCTL, + FCNTL, + FLOCK, + FSYNC, + FDATASYNC, + TRUNCATE, + FTRUNCATE, + GETDENTS, + GETCWD, + CHDIR, + FCHDIR, + RENAME, + MKDIR, + RMDIR, + CREAT, + LINK, + UNLINK, + SYMLINK, + READLINK, + CHMOD, + FCHMOD, + CHOWN, + FCHOWN, + LCHOWN, + UMASK, + GETTIMEOFDAY, + GETRLIMIT, + GETRUSAGE, + SYSINFO, + TIMES, + PTRACE, + GETUID, + SYSLOG, + GETGID, + SETUID, + SETGID, + GETEUID, + GETEGID, + SETPGID, + GETPPID, + GETPGRP, + SETSID, + SETREUID, + SETREGID, + GETGROUPS, + SETGROUPS, + SETRESUID, + GETRESUID, + SETRESGID, + GETRESGID, + GETPGID, + SETFSUID, + SETFSGID, + GETSID, + CAPGET, + CAPSET, + RT_SIGPENDING, + RT_SIGTIMEDWAIT, + RT_SIGQUEUEINFO, + RT_SIGSUSPEND, + SIGALTSTACK, + UTIME, + MKNOD, + USELIB, + PERSONALITY, + USTAT, + STATFS, + FSTATFS, + SYSFS, + GETPRIORITY, + SETPRIORITY, + SCHED_SETPARAM, + SCHED_GETPARAM, + SCHED_SETSCHEDULER, + SCHED_GETSCHEDULER, + SCHED_GET_PRIORITY_MAX, + SCHED_GET_PRIORITY_MIN, + SCHED_RR_GET_INTERVAL, + MLOCK, + MUNLOCK, + MLOCKALL, + MUNLOCKALL, + VHANGUP, + MODIFY_LDT, + PIVOT_ROOT, + _SYSCTL, + PRCTL, + ARCH_PRCTL, + ADJTIMEX, + SETRLIMIT, + CHROOT, + SYNC, + ACCT, + SETTIMEOFDAY, + MOUNT, + UMOUNT2, + SWAPON, + SWAPOFF, + REBOOT, + SETHOSTNAME, + SETDOMAINNAME, + IOPL, + IOPERM, + CREATE_MODULE, + INIT_MODULE, + DELETE_MODULE, + GET_KERNEL_SYMS, + QUERY_MODULE, + QUOTACTL, + NFSSERVCTL, + GETPMSG, + PUTPMSG, + AFS_SYSCALL, + TUXCALL, + SECURITY, + GETTID, + READAHEAD, + SETXATTR, + LSETXATTR, + FSETXATTR, + GETXATTR, + LGETXATTR, + FGETXATTR, + LISTXATTR, + LLISTXATTR, + FLISTXATTR, + REMOVEXATTR, + LREMOVEXATTR, + FREMOVEXATTR, + TKILL, + TIME, + FUTEX, + SCHED_SETAFFINITY, + SCHED_GETAFFINITY, + SET_THREAD_AREA, + IO_SETUP, + IO_DESTROY, + IO_GETEVENTS, + IO_SUBMIT, + IO_CANCEL, + GET_THREAD_AREA, + LOOKUP_DCOOKIE, + EPOLL_CREATE, + EPOLL_CTL_OLD, + EPOLL_WAIT_OLD, + REMAP_FILE_PAGES, + GETDENTS64, + SET_TID_ADDRESS, + RESTART_SYSCALL, + SEMTIMEDOP, + FADVISE64, + TIMER_CREATE, + TIMER_SETTIME, + TIMER_GETTIME, + TIMER_GETOVERRUN, + TIMER_DELETE, + CLOCK_SETTIME, + CLOCK_GETTIME, + CLOCK_GETRES, + CLOCK_NANOSLEEP, + EXIT_GROUP, + EPOLL_WAIT, + EPOLL_CTL, + TGKILL, + UTIMES, + VSERVER, + MBIND, + SET_MEMPOLICY, + GET_MEMPOLICY, + MQ_OPEN, + MQ_UNLINK, + MQ_TIMEDSEND, + MQ_TIMEDRECEIVE, + MQ_NOTIFY, + MQ_GETSETATTR, + KEXEC_LOAD, + WAITID, + ADD_KEY, + REQUEST_KEY, + KEYCTL, + IOPRIO_SET, + IOPRIO_GET, + INOTIFY_INIT, + INOTIFY_ADD_WATCH, + INOTIFY_RM_WATCH, + MIGRATE_PAGES, + OPENAT, + MKDIRAT, + MKNODAT, + FCHOWNAT, + FUTIMESAT, + NEWFSTATAT, + UNLINKAT, + RENAMEAT, + LINKAT, + SYMLINKAT, + READLINKAT, + FCHMODAT, + FACCESSAT, + PSELECT6, + PPOLL, + UNSHARE, + SET_ROBUST_LIST, + GET_ROBUST_LIST, + SPLICE, + TEE, + SYNC_FILE_RANGE, + VMSPLICE, + MOVE_PAGES, + UTIMENSAT, + EPOLL_PWAIT, + SIGNALFD, + TIMERFD_CREATE, + EVENTFD, + FALLOCATE, + TIMERFD_SETTIME, + TIMERFD_GETTIME, + ACCEPT4, + SIGNALFD4, + EVENTFD2, + EPOLL_CREATE1, + DUP3, + PIPE2, + INOTIFY_INIT1, + PREADV, + PWRITEV, + RT_TGSIGQUEUEINFO, + PERF_EVENT_OPEN, + RECVMMSG, + FANOTIFY_INIT, + FANOTIFY_MARK, + PRLIMIT64, + NAME_TO_HANDLE_AT, + OPEN_BY_HANDLE_AT, + CLOCK_ADJTIME, + SYNCFS, + SENDMMSG, + SETNS, + GETCPU, + PROCESS_VM_READV, + PROCESS_VM_WRITEV, + KCMP, + FINIT_MODULE, +}; + + +#endif diff --git a/lib/sys/time.h b/lib/sys/time.h new file mode 100644 index 0000000..920ee5c --- /dev/null +++ b/lib/sys/time.h @@ -0,0 +1,11 @@ +#ifndef TIME_H +#define TIME_H + +#include "sizes.h" + +struct timespec { + u64 tv_sec; + long tv_nsec; +}; + +#endif diff --git a/lib/sys/write.h b/lib/sys/write.h new file mode 100644 index 0000000..a705873 --- /dev/null +++ b/lib/sys/write.h @@ -0,0 +1,10 @@ +#ifndef WRITE_H +#define WRITE_H + +#include "syscalls.h" + +static int write(unsigned int fd, const char * buf, unsigned long count) { + return syscall((void*)WRITE, (void*)fd, (void*)buf, (void*)count); +} + +#endif |