From 57e4efe91798516df7ebe3ddd9a4aba5cadc497b Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 24 Nov 2013 03:15:06 +0200 Subject: [PATCH] start bridge gen tool but some registers should probably be saved.. --- run_mkpubinc.sh | 5 +- tools/Makefile | 6 +- tools/asmproc.c | 33 +------ tools/mkbridge.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++ tools/my_str.h | 56 ++++++++++++ 5 files changed, 289 insertions(+), 36 deletions(-) create mode 100644 tools/mkbridge.c create mode 100644 tools/my_str.h diff --git a/run_mkpubinc.sh b/run_mkpubinc.sh index 3cbcac8..889e0db 100755 --- a/run_mkpubinc.sh +++ b/run_mkpubinc.sh @@ -23,6 +23,7 @@ echo "; funcs called from C" >> $3 cat $2 | \ while read a; do - echo "_$a equ $a" >> $3 - echo "PUBLIC _$a" >> $3 +# echo "_$a equ $a" >> $3 +# echo "PUBLIC _$a" >> $3 + echo "PUBLIC $a" >> $3 done diff --git a/tools/Makefile b/tools/Makefile index 7c03266..2f21042 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,6 +1,8 @@ CFLAGS += -Wall -ggdb -all: asmproc cmpmrg_text +T = asmproc cmpmrg_text mkbridge + +all: $(T) clean: - $(RM) asmproc cmpmrg_text + $(RM) $(T) diff --git a/tools/asmproc.c b/tools/asmproc.c index 4b40090..02d06a3 100644 --- a/tools/asmproc.c +++ b/tools/asmproc.c @@ -3,38 +3,7 @@ #include #include "my_assert.h" - -static int my_isblank(char c) -{ - return c == '\t' || c == ' ' || c == '\r' || c == '\n'; -} - -static char *sskip(char *s) -{ - while (my_isblank(*s)) - s++; - - return s; -} - -static char *next_word(char *w, size_t wsize, char *s) -{ - size_t i; - - s = sskip(s); - - for (i = 0; i < wsize - 1; i++) { - if (*s == 0 || my_isblank(s[i])) - break; - w[i] = s[i]; - } - w[i] = 0; - - if (*s != 0 && !my_isblank(s[i])) - printf("warning: '%s' truncated\n", w); - - return s + i; -} +#include "my_str.h" struct sl_item { char *name; diff --git a/tools/mkbridge.c b/tools/mkbridge.c new file mode 100644 index 0000000..e3b0068 --- /dev/null +++ b/tools/mkbridge.c @@ -0,0 +1,225 @@ +#include +#include +#include + +#include "my_assert.h" +#include "my_str.h" + +static int find_protostr(char *dst, size_t dlen, FILE *fhdr, + const char *sym, int *pline) +{ + int line = 0; + char *p; + + while (fgets(dst, dlen, fhdr)) + { + line++; + if (strstr(dst, sym) != NULL) + break; + } + *pline = line; + + if (feof(fhdr)) + return -1; + + p = dst + strlen(dst); + for (p--; p > dst && my_isblank(*p); --p) + *p = 0; + + return 0; +} + +static int get_regparm(char *dst, size_t dlen, char *p) +{ + int i, o; + + if (*p != '<') + return 0; + + for (o = 0, i = 1; o < dlen; i++) { + if (p[i] == 0) + return 0; + if (p[i] == '>') + break; + dst[o++] = p[i]; + } + dst[o] = 0; + return i + 1; +} + +static const char *known_types[] = { + "unsigned int", + "signed int", + "int", + "void", + "DWORD", + "HMODULE", + "HANDLE", + "HWND", +}; + +static int check_type(const char *name) +{ + int i, l; + + for (i = 0; i < sizeof(known_types) / sizeof(known_types[0]); i++) { + l = strlen(known_types[i]); + if (strncmp(known_types[i], name, l) == 0) + return l; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + FILE *fout, *fsyms, *fhdr; + const char *hdrfn; + char protostr[256]; + char line[256]; + char sym[256]; + char buf[256]; + char regparm[16]; + char *p; + int first_regparm = 0; + int have_regparm; + int pline = 0; + int xarg; + int ret; + + if (argc != 4) { + // -c - patch callsites + printf("usage:\n%s \n", + argv[0]); + return 1; + } + + hdrfn = argv[3]; + fhdr = fopen(hdrfn, "r"); + my_assert_not(fhdr, NULL); + + fsyms = fopen(argv[2], "r"); + my_assert_not(fsyms, NULL); + + fout = fopen(argv[1], "w"); + my_assert_not(fout, NULL); + + fprintf(fout, ".text\n\n"); + + while (fgets(line, sizeof(line), fsyms)) + { + next_word(sym, sizeof(sym), line); + if (sym[0] == 0 || sym[0] == ';' || sym[0] == '#') + continue; + + ret = find_protostr(protostr, sizeof(protostr), fhdr, + sym, &pline); + if (ret != 0) { + printf("%s: sym '%s' is missing\n", + hdrfn, sym); + return 1; + } + + p = protostr; + if (p[0] == '/' && p[1] == '/') { + printf("warning: decl for sym '%s' is commented out\n", sym); + p = sskip(p + 2); + } + + ret = check_type(p); + if (ret <= 0) { + printf("%s:%d:%ld: unhandled return in '%s'\n", + hdrfn, pline, (p - protostr) + 1, protostr); + return 1; + } + p += ret; + p = sskip(p); + + // ignore calling convention specifier, for now + p = next_word(buf, sizeof(buf), p); + p = sskip(p); + if (buf[0] == 0) { + printf("%s:%d:%ld: cconv missing\n", + hdrfn, pline, (p - protostr) + 1); + return 1; + } + + p = next_idt(buf, sizeof(buf), p); + p = sskip(p); + if (buf[0] == 0) { + printf("%s:%d:%ld: func name missing\n", + hdrfn, pline, (p - protostr) + 1); + return 1; + } + + ret = get_regparm(regparm, sizeof(regparm), p); + if (ret > 0) { + if (strcmp(regparm, "eax") && strcmp(regparm, "ax")) { + printf("%s:%d:%ld: bad regparm: %s\n", + hdrfn, pline, (p - protostr) + 1, regparm); + return 1; + } + p += ret; + p = sskip(p); + } + + if (*p != '(') { + printf("%s:%d:%ld: '(' expected, got '%c'\n", + hdrfn, pline, (p - protostr) + 1, *p); + return 1; + } + p++; + + fprintf(fout, ".global _asm_%s\n", sym); + fprintf(fout, "_asm_%s:\n", sym); + + xarg = 1; + while (1) { + p = sskip(p); + if (*p == ')') + break; + if (*p == ',') + p = sskip(p + 1); + + ret = check_type(p); + if (ret <= 0) { + printf("%s:%d:%ld: unhandled type for arg%d\n", + hdrfn, pline, (p - protostr) + 1, xarg); + return 1; + } + p += ret; + p = sskip(p); + + p = next_idt(buf, sizeof(buf), p); + p = sskip(p); + if (buf[0] == 0) { + printf("%s:%d:%ld: idt missing for arg%d\n", + hdrfn, pline, (p - protostr) + 1, xarg); + return 1; + } + + have_regparm = 0; + ret = get_regparm(regparm, sizeof(regparm), p); + if (ret > 0) { + p += ret; + p = sskip(p); + + have_regparm = 1; + fprintf(fout, "\t movl %d(%%esp), %%%s\n", + xarg * 4, regparm); + } + if (xarg == 1) + first_regparm = have_regparm; + else if (have_regparm != first_regparm) { + printf("%s:%d:%ld: mixed regparm is unhandled\n", + hdrfn, pline, (p - protostr) + 1); + return 1; + } + } + + fprintf(fout, "\t jmp %s\n\n", sym); + } + + fclose(fout); + return 0; +} diff --git a/tools/my_str.h b/tools/my_str.h new file mode 100644 index 0000000..44caa7c --- /dev/null +++ b/tools/my_str.h @@ -0,0 +1,56 @@ +static int my_isblank(char c) +{ + return c == '\t' || c == ' ' || c == '\r' || c == '\n'; +} + +static int my_issep(char c) +{ + return c == '(' || c == ')' || c == '[' || c == ']' + || c == '<' || c == '>' || c == ','; +} + +static char *sskip(char *s) +{ + while (my_isblank(*s)) + s++; + + return s; +} + +static char *next_word(char *w, size_t wsize, char *s) +{ + size_t i; + + s = sskip(s); + + for (i = 0; i < wsize - 1; i++) { + if (*s == 0 || my_isblank(s[i])) + break; + w[i] = s[i]; + } + w[i] = 0; + + if (*s != 0 && !my_isblank(s[i])) + printf("warning: '%s' truncated\n", w); + + return s + i; +} + +static inline char *next_idt(char *w, size_t wsize, char *s) +{ + size_t i; + + s = sskip(s); + + for (i = 0; i < wsize - 1; i++) { + if (*s == 0 || my_isblank(s[i]) || my_issep(s[i])) + break; + w[i] = s[i]; + } + w[i] = 0; + + if (*s != 0 && !my_isblank(s[i]) && !my_issep(s[i])) + printf("warning: '%s' truncated\n", w); + + return s + i; +} -- 2.39.2