diff options
author | Camil Staps | 2016-01-28 20:27:19 +0100 |
---|---|---|
committer | Camil Staps | 2016-01-28 20:27:19 +0100 |
commit | aa5ad07bb3c56a8d013cb76a693afefe0d28cfd5 (patch) | |
tree | 604c61592c3aeb35875a6af4c2181003d70db26a |
Inital commit
-rw-r--r-- | .gitignore | 15 | ||||
-rw-r--r-- | Clean.h | 43 | ||||
-rw-r--r-- | cleanc.c | 129 | ||||
-rw-r--r-- | cleanc.dcl | 10 | ||||
-rw-r--r-- | cleanc.h | 10 | ||||
-rw-r--r-- | cleanc.icl | 17 | ||||
-rw-r--r-- | test.icl | 12 |
7 files changed, 236 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..32fd324 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Executables +*.exe +*.out +test + +# Directory used to store object files, abc files and assembly files +Clean System Files/ + +# iTasks environment extra data +*-data/ +sapl/ + +# Object files +*.o + @@ -0,0 +1,43 @@ + +#define Clean(a) + +typedef struct clean_string *CleanString; + +/* a string in Clean is: + struct clean_string { + int clean_string_length; + char clean_string_characters[clean_string_length]; + }; + The string does not end with a '\0' ! +*/ + +/* CleanStringLength(clean_string) returns the length of the clean_string in characters */ +#define CleanStringLength(clean_string) (*(unsigned long *)(clean_string)) + +/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */ +#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned long *)(clean_string))) + +/* CleanStringSizeInts(string_length) return size of *CleanString in integers */ +#define CleanStringSizeInts(string_length) (1+(((unsigned int)(string_length)+3)>>2)) + +/* CleanStringVariable(clean_string,string_length) defines variable clean_string with length string_length, + before using the clean_string variable, cast to CleanString, except for the macros above */ +#define CleanStringVariable(clean_string,string_length) unsigned int clean_string[CleanStringSizeInts(string_length)] + +/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */ +#define CleanStringSizeBytes(string_length) (4+(((unsigned int)(string_length)+3) & -4)) + +typedef int *CleanIntArray; + +/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */ +#define CleanIntArraySize(clean_int_array) (((unsigned int *)(clean_int_array))[-2]) + +typedef double *CleanRealArray; + +/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */ +#define CleanRealArraySize(clean_real_array) (((unsigned int *)(clean_real_array))[-2]) + +typedef unsigned char *CleanCharArray; + +/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */ +#define CleanCharArraySize(clean_char_array) (((unsigned int *)(clean_char_array))[-1]) diff --git a/cleanc.c b/cleanc.c new file mode 100644 index 0000000..bc73574 --- /dev/null +++ b/cleanc.c @@ -0,0 +1,129 @@ +#include <fcntl.h> +#include <stdio.h> +#include <elf.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include "Clean.h" + +void call_funcname(char*); + +void hello(void) { + printf("Hello world!\n"); +} + +void* parameters[100]; +uint8_t param_ptr = 0; + +void init(void) { + parameters[0] = NULL; + param_ptr = 0; +} + +void puti(long i) { + printf("puti %d %d\n", param_ptr, i); + parameters[param_ptr] = malloc(sizeof(long)); + *((long*)parameters[param_ptr]) = i; + param_ptr++; +} + +char* cleantocstring(CleanString s) { + char* cs = malloc(sizeof(char) * CleanStringLength(s) + 1); + int i; + for (i = 0; i < CleanStringLength(s); i++) + cs[i] = CleanStringCharacters(s)[i]; + cs[i] = 0; + return cs; +} + +void call(CleanString fname) { + char*f = cleantocstring(fname); + call_funcname(f); + param_ptr = 0; + // todo +} + +long geti(void) { + printf("geti %d\n", param_ptr); + return (long)*((long*)parameters[param_ptr++]); +} + +void call_funcname(char* fname) { + // http://stackoverflow.com/a/1118808/1544337 + Elf64_Shdr * shdr; + Elf64_Ehdr * ehdr; + Elf * elf; + Elf_Scn * scn; + Elf_Data * data; + int cnt; + void (*fp)() = NULL; + + int fd = 0; + + /* This is probably Linux specific - Read in our own executable*/ + if ((fd = open("/proc/self/exe", O_RDONLY)) == -1) + exit(1); + + elf_version(EV_CURRENT); + + if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + fprintf(stderr, "file is not an ELF binary\n"); + exit(1); + } + /* Let's get the elf sections */ + if (((ehdr = elf64_getehdr(elf)) == NULL) || + ((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) || + ((data = elf_getdata(scn, NULL)) == NULL)) { + fprintf(stderr, "Failed to get SOMETHING\n"); + exit(1); + } + + /* Let's go through each elf section looking for the symbol table */ + for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); cnt++) { + if ((shdr = elf64_getshdr(scn)) == NULL) + exit(1); + + if (shdr->sh_type == SHT_SYMTAB) { + char *name; + char *strName; + data = 0; + if ((data = elf_getdata(scn, data)) == 0 || data->d_size == 0) { + fprintf(stderr, "No data in symbol table\n"); + continue; + } + + Elf64_Sym *esym = (Elf64_Sym*) data->d_buf; + Elf64_Sym *lastsym = (Elf64_Sym*) ((char*) data->d_buf + data->d_size); + + /* Look through all symbols */ + for (; esym < lastsym; esym++) { + if ((esym->st_value == 0) || + (ELF64_ST_BIND(esym->st_info)== STB_WEAK) || + (ELF64_ST_BIND(esym->st_info)== STB_NUM) || + (ELF64_ST_TYPE(esym->st_info)!= STT_FUNC)) + continue; + + name = elf_strptr(elf,shdr->sh_link , (size_t)esym->st_name); + + if(!name){ + fprintf(stderr,"%s\n",elf_errmsg(elf_errno())); + //exit(-1); + } else if(strcmp(fname, name) == 0 ) { + fp = (void(*)(void)) esym->st_value; + } + } + + /* Call and hope we don't segfault!*/ + if (fp != NULL) { + fp(); + return; + } + } + } + + elf_end(elf); + + fprintf(stderr, "done, nothing found\n"); +} + diff --git a/cleanc.dcl b/cleanc.dcl new file mode 100644 index 0000000..df97ffe --- /dev/null +++ b/cleanc.dcl @@ -0,0 +1,10 @@ +definition module cleanc + +:: State :== Int + +puti :: !Int !*State -> *State + +call :: !String !*State -> *State + +geti :: !*State -> (!Int, !*State) + diff --git a/cleanc.h b/cleanc.h new file mode 100644 index 0000000..9c3e043 --- /dev/null +++ b/cleanc.h @@ -0,0 +1,10 @@ +void hello(void); + +void init(void); + +void puti(long); + +void call(char*); + +long geti(void); + diff --git a/cleanc.icl b/cleanc.icl new file mode 100644 index 0000000..b3f037c --- /dev/null +++ b/cleanc.icl @@ -0,0 +1,17 @@ +implementation module cleanc + +puti :: !Int !*State -> *State +puti i s = code inline { + ccall puti "I:V:I" +} + +call :: !String !*State -> *State +call f s = code inline { + ccall call "S:V:I" +} + +geti :: !*State -> (!Int, !*State) +geti s = code inline { + ccall geti ":I:I" +} + diff --git a/test.icl b/test.icl new file mode 100644 index 0000000..e154d5c --- /dev/null +++ b/test.icl @@ -0,0 +1,12 @@ +module test + +import StdEnv +import cleanc + +Start +# s = 10 +# s = puti 50 s +# s = call "hello" s +# (i, s) = geti s += i + |