From 7b64bbce7b62cfd564d6a0d664ae7ce07b707225 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Sun, 31 Jan 2016 15:52:34 +0100 Subject: Documentation --- CleanC.dcl | 10 +++++ Makefile | 2 +- hacking.c | 129 ------------------------------------------------------------ hacking.h | 32 --------------- interface.c | 2 +- magic.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ magic.h | 32 +++++++++++++++ 7 files changed, 173 insertions(+), 163 deletions(-) delete mode 100644 hacking.c delete mode 100644 hacking.h create mode 100644 magic.c create mode 100644 magic.h diff --git a/CleanC.dcl b/CleanC.dcl index ba744cd..a385a50 100644 --- a/CleanC.dcl +++ b/CleanC.dcl @@ -62,21 +62,31 @@ instance toCParamList (a,b,c,d,e) | toCParam a & toCParam b & toCParam c & toCPa instance toCParamList (a,b,c,d,e,f) | toCParam a & toCParam b & toCParam c & toCParam d & toCParam e & toCParam f instance toCParamList (a,b,c,d,e,f,g) | toCParam a & toCParam b & toCParam c & toCParam d & toCParam e & toCParam f & toCParam g +// Must be called before using any other function, initialises the interface cInit :: !*State -> *State +// Low-level functions to send function arguments to C cPuti :: !Int !*State -> *State cPuts :: !String !*State -> *State cPutr :: !Real !*State -> *State +// Low-level: send any function argument to C cPutParam :: !CParam -> *State -> *State +// Low-level: set the return type of the function you're going to call cSetReturnType :: !CType -> *State -> *State +// Low-level: call a function cCall_ :: !String !*State -> *State +// Low-level: get the return value of a function cGeti :: !*State -> (!Int, !*State) cGets :: !*State -> (!String, !*State) cGetr :: !*State -> (!Real, !*State) +// Call a function with arguments and get the return value +// +// E.g., for a function int add(int x, int y) you would use: +// (sum, st) = cCall Int "add" (15, 20) st cCall :: !CType !String !a !*State -> (!CParam, !*State) | toCParamList a diff --git a/Makefile b/Makefile index 786a992..0cfd63d 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ CFLAGS=-O0 -Wall NAME=CleanC OBJ=$(NAME).o -INTERMEDIATE=interface.o cleanstring.o hacking.o +INTERMEDIATE=interface.o cleanstring.o magic.o TEST_SCRIPT=test CLM=clm diff --git a/hacking.c b/hacking.c deleted file mode 100644 index 44f6bd3..0000000 --- a/hacking.c +++ /dev/null @@ -1,129 +0,0 @@ -/** The MIT License (MIT) - -Copyright (c) 2016 Camil Staps - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "hacking.h" - -Callable* newCallable() { - Callable* c = malloc(sizeof(Callable)); - c->cif = malloc(sizeof(ffi_cif)); - c->fp = NULL; - return c; -} - -Callable* funcnameToCallable(char* fname, - uint8_t n_params, ffi_type** parameter_types, ffi_type* return_type) { - // 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; - Callable* callable = newCallable(); - if (callable == NULL) return 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; - 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())); - } else if(strcmp(fname, name) == 0 ) { - fp = (void(*)(void)) esym->st_value; - } - } - - /* Call and hope we don't segfault!*/ - if (fp != NULL) { - if (ffi_prep_cif(callable->cif, FFI_DEFAULT_ABI, n_params, - return_type, parameter_types) == FFI_OK) { - elf_end(elf); - callable->fp = fp; - return callable; - } - } - } - } - - elf_end(elf); - - fprintf(stderr, "No function %s found\n", fname); - - return NULL; -} - -void call(Callable* callable, void** parameters, void* return_val) { - ffi_call(callable->cif, callable->fp, return_val, parameters); -} - diff --git a/hacking.h b/hacking.h deleted file mode 100644 index 9d7835f..0000000 --- a/hacking.h +++ /dev/null @@ -1,32 +0,0 @@ -/** The MIT License (MIT) - -Copyright (c) 2016 Camil Staps - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. */ - -typedef struct { - ffi_cif* cif; - void(*fp)(void); -} Callable; - -Callable* funcnameToCallable(char* fname, - uint8_t n_params, ffi_type** parameter_types, ffi_type* return_type); - -void call(Callable*, void** parameters, void* return_val); - diff --git a/interface.c b/interface.c index 5002a6c..2a9a106 100644 --- a/interface.c +++ b/interface.c @@ -26,7 +26,7 @@ SOFTWARE. */ #include #include -#include "hacking.h" +#include "magic.h" #include "Clean.h" #include "cleanstring.h" diff --git a/magic.c b/magic.c new file mode 100644 index 0000000..c99fb06 --- /dev/null +++ b/magic.c @@ -0,0 +1,129 @@ +/** The MIT License (MIT) + +Copyright (c) 2016 Camil Staps + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "magic.h" + +Callable* newCallable() { + Callable* c = malloc(sizeof(Callable)); + c->cif = malloc(sizeof(ffi_cif)); + c->fp = NULL; + return c; +} + +Callable* funcnameToCallable(char* fname, + uint8_t n_params, ffi_type** parameter_types, ffi_type* return_type) { + // 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; + Callable* callable = newCallable(); + if (callable == NULL) return 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; + 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())); + } else if(strcmp(fname, name) == 0 ) { + fp = (void(*)(void)) esym->st_value; + } + } + + /* Call and hope we don't segfault!*/ + if (fp != NULL) { + if (ffi_prep_cif(callable->cif, FFI_DEFAULT_ABI, n_params, + return_type, parameter_types) == FFI_OK) { + elf_end(elf); + callable->fp = fp; + return callable; + } + } + } + } + + elf_end(elf); + + fprintf(stderr, "No function %s found\n", fname); + + return NULL; +} + +void call(Callable* callable, void** parameters, void* return_val) { + ffi_call(callable->cif, callable->fp, return_val, parameters); +} + diff --git a/magic.h b/magic.h new file mode 100644 index 0000000..9d7835f --- /dev/null +++ b/magic.h @@ -0,0 +1,32 @@ +/** The MIT License (MIT) + +Copyright (c) 2016 Camil Staps + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ + +typedef struct { + ffi_cif* cif; + void(*fp)(void); +} Callable; + +Callable* funcnameToCallable(char* fname, + uint8_t n_params, ffi_type** parameter_types, ffi_type* return_type); + +void call(Callable*, void** parameters, void* return_val); + -- cgit v1.2.3