commit ef56b9d99377d6a8d10e2e687759aac2a9993032
parent 2637645b18ff9ca6c87f1f2c33771014dac50483
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Sat, 6 Nov 2021 16:53:41 -0500
write syscall support
This required generating a data segment. I also realized that section
headers are not necessary, because we're not worrying about linking
right now, so I got rid of it.
_array_add had to be adjusted to allow pushing multiple objects at
a time to an array. This is useful in the data segment, where we want
to push multiple chars.
Diffstat:
M | array.c | | | 9 | +++++---- |
M | array.h | | | 7 | +++++-- |
M | main.c | | | 101 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
M | prog.nc | | | 4 | ++-- |
4 files changed, 81 insertions(+), 40 deletions(-)
diff --git a/array.c b/array.c
@@ -1,21 +1,22 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
#include "array.h"
int
-_array_add(void **data, size_t size, size_t *len, size_t *cap, void *new)
+_array_add(void **data, size_t size, size_t count, size_t *len, size_t *cap, void *new)
{
if (*len == *cap) {
- *cap = *cap ? 2*(*cap)*size : 1;
+ *cap = *cap ? 2*(*cap)*size : count;
*data = realloc(*data, size*(*cap));
if (*data == NULL)
return -1;
}
- memcpy(*data + size*(*len), new, size);
- *len += 1;
+ memcpy(*data + size*(*len), new, size*count);
+ *len += count;
return *len;
}
diff --git a/array.h b/array.h
@@ -1,4 +1,7 @@
#define array_add(arr, new) \
- _array_add((void **) &(arr->data), sizeof(new), &(arr->len), &(arr->cap), &new);
+ _array_add((void **) &(arr->data), sizeof(new), 1, &(arr->len), &(arr->cap), &new);
-int _array_add(void **data, size_t size, size_t *len, size_t *cap, void *new);
+#define array_push(arr, new, count) \
+ _array_add((void **) &(arr->data), sizeof(*new), count, &(arr->len), &(arr->cap), new);
+
+int _array_add(void **data, size_t size, size_t count, size_t *len, size_t *cap, void *new);
diff --git a/main.c b/main.c
@@ -13,11 +13,11 @@
char code[] = {0xb8, 0, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xf, 0x5};
int
-elf(char *text, size_t len, FILE *f)
+elf(char *text, size_t len, char*data, size_t dlen, FILE *f)
{
Elf64_Ehdr ehdr = { 0 };
Elf64_Phdr phdr_text = { 0 };
- Elf64_Shdr shdr_text = { 0 };
+ Elf64_Phdr phdr_data = { 0 };
ehdr.e_ident[0] = ELFMAG0;
ehdr.e_ident[1] = ELFMAG1;
@@ -35,14 +35,11 @@ elf(char *text, size_t len, FILE *f)
ehdr.e_entry = 0x1000;
ehdr.e_phoff = sizeof(ehdr);
ehdr.e_phentsize = sizeof(phdr_text);
- ehdr.e_phnum = 1;
+ ehdr.e_phnum = 2;
- ehdr.e_shoff = sizeof(ehdr) + sizeof(phdr_text);
- ehdr.e_shentsize = sizeof(shdr_text);
- ehdr.e_shnum = 1;
ehdr.e_ehsize = sizeof(ehdr);
- size_t pretextlen = sizeof(ehdr) + sizeof(phdr_text) + sizeof(shdr_text);
+ size_t pretextlen = sizeof(ehdr) + sizeof(phdr_text) + sizeof(phdr_data);
phdr_text.p_type = PT_LOAD;
phdr_text.p_offset = 0x1000;
@@ -53,27 +50,33 @@ elf(char *text, size_t len, FILE *f)
phdr_text.p_flags = PF_R | PF_X;
phdr_text.p_align = 0x1000;
- shdr_text.sh_name = 10;
- shdr_text.sh_type = SHT_PROGBITS;
- shdr_text.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
- shdr_text.sh_addr = 0x1000;
- shdr_text.sh_offset = 0x1000;
- shdr_text.sh_size = len;
- shdr_text.sh_addralign = 1;
+ phdr_data.p_type = PT_LOAD;
+ phdr_data.p_offset = 0x2000;
+ phdr_data.p_vaddr = 0x2000;
+ phdr_data.p_paddr = 0x2000;
+ phdr_data.p_filesz = dlen;
+ phdr_data.p_memsz = dlen;
+ phdr_data.p_flags = PF_R;
+ phdr_data.p_align = 0x1000;
fwrite(&ehdr, 1, sizeof(Elf64_Ehdr), f);
fwrite(&phdr_text, sizeof(phdr_text), 1, f);
- fwrite(&shdr_text, sizeof(shdr_text), 1, f);
+ fwrite(&phdr_data, sizeof(phdr_data), 1, f);
char empty = 0;
- fprintf(stderr, "pretextlen: %u\n", pretextlen);
+
for (int i = 0; i < 0x1000 - pretextlen; i++) {
fwrite(&empty, 1, 1, f);
}
fwrite(text, 1, len, f);
+ for (int i = 0; i < 0x1000 - len; i++) {
+ fwrite(&empty, 1, 1, f);
+ }
+ fwrite(data, 1, dlen, f);
}
enum tokentype {
TOK_SYSCALL = 1,
+ TOK_PRINT,
TOK_EXIT,
TOK_LPAREN,
@@ -82,6 +85,7 @@ enum tokentype {
TOK_COMMA,
TOK_NUM,
+ TOK_STRING,
};
struct slice {
@@ -139,6 +143,20 @@ lex(struct slice start)
start.len--;
cur->slice.len++;
}
+ } else if (*start.ptr == '"') {
+ start.ptr++;
+ start.len--;
+ cur->slice.ptr = start.ptr;
+ cur->slice.len = 0;
+ cur->type = TOK_STRING;
+ while (*start.ptr != '"') {
+ start.ptr++;
+ start.len--;
+ cur->slice.len++;
+ }
+
+ start.ptr++;
+ start.len--;
}
cur->next = calloc(1, sizeof(struct token));
@@ -185,6 +203,22 @@ expect(struct token *tok, enum tokentype type)
error("mismatch");
}
+struct data {
+ size_t cap;
+ size_t len;
+ char *data;
+} data_seg;
+
+#define DATA_OFFSET 0x2000
+
+int
+data_push(char *ptr, size_t len)
+{
+ size_t dlen = data_seg.len;
+ array_push((&data_seg), ptr, len);
+ return 0x2000 + data_seg.len - len;
+}
+
struct fcall
parse(struct token *tok)
{
@@ -196,10 +230,18 @@ parse(struct token *tok)
int val;
while (1) {
- expect(tok, TOK_NUM);
- val = strtol(tok->slice.ptr, NULL, 10);
- array_add((&fcall.params), val);
- tok = tok->next;
+ switch (tok->type) {
+ case TOK_NUM:
+ val = strtol(tok->slice.ptr, NULL, 10);
+ array_add((&fcall.params), val);
+ tok = tok->next;
+ break;
+ case TOK_STRING:
+ val = data_push(tok->slice.ptr, tok->slice.len);
+ array_add((&fcall.params), val);
+ tok = tok->next;
+ break;
+ }
if (tok->type == TOK_RPAREN)
break;
@@ -231,9 +273,11 @@ gensyscall(char *buf, struct fparams *params)
ptr += 2;
char op1 = 0xc0 | regs[i];
*(ptr++) = op1;
- *(ptr++) = params->data[i];
- memset(ptr, 0, 3);
- ptr += 3;
+ int val = params->data[i];
+ *(ptr++) = val & 0xFF;
+ *(ptr++) = (val >> 8) & 0xFF;
+ *(ptr++) = (val >> 16) & 0xFF;
+ *(ptr++) = (val >> 24) & 0xFF;
}
char syscall[] = {0x0f, 0x05};
@@ -269,14 +313,8 @@ main(int argc, char *argv[])
struct token *head = lex((struct slice){addr, statbuf.st_size});
struct fcall fcall = parse(head);
-
- munmap(addr, statbuf.st_size);
- switch (fcall.func) {
- case FUNC_EXIT:
- code[1] = 60;
- code[6] = fcall.params.data[0];
- }
+ munmap(addr, statbuf.st_size);
FILE *out = fopen(argv[2], "w");
if (!out) {
@@ -292,8 +330,7 @@ main(int argc, char *argv[])
gensyscall(fcode, &(fcall.params));
- elf(fcode, len, out);
- fprintf(stderr, "size: %d\n", len);
+ elf(fcode, len, data_seg.data, data_seg.len, out);
fclose(out);
}
diff --git a/prog.nc b/prog.nc
@@ -1 +1 @@
-syscall(60, 12)-
\ No newline at end of file
+syscall(1, 0, "hello", 5)+
\ No newline at end of file