| /* |
| genstubdll - Generate stub-library acting like an import-library |
| using .def file syntax. |
| Copyright (C) 2014-2016 mingw-w64 project |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <direct.h> |
| |
| #include "token.h" |
| |
| static void generate_stub_c (FILE *fp); |
| |
| const char *cur_IAT = NULL; |
| const char *cur_dllsym = NULL; |
| |
| static void printHeader (FILE *fp) |
| { |
| fprintf (fp, "/* This file was generated by genstubdll tool.\n"); |
| fprintf (fp, " * Written by Kai Tietz 2014\n"); |
| fprintf (fp, " */\n"); |
| fprintf (fp, "\n"); |
| } |
| |
| static void init_curIAT (void) |
| { |
| char *h; |
| char *r; |
| |
| h = (char *) strdup (cur_libname); |
| while ((r = strchr (h, '.')) != NULL) |
| *r = '_'; |
| cur_dllsym = unifyStr (h); |
| free (h); |
| |
| cur_IAT = unifyCat ("__IAT_", cur_dllsym); |
| } |
| |
| static void printStubCode (FILE *fp, const char *hname, const char *sym) |
| { |
| printHeader (fp); |
| |
| fprintf (fp, "\t.file \"stub_%s\"\n", hname); |
| fprintf (fp, "\t.text\n"); |
| fprintf (fp, "#ifdef __x86_64__\n"); |
| fprintf (fp,"\t.globl %s\n", sym); |
| fprintf (fp, "%s:\n", sym); |
| fprintf (fp, "\tjmp *__imp_%s(%%rip)\n", sym); |
| fprintf (fp, "#elif __i386__\n"); |
| fprintf (fp,"\t.globl _%s\n", sym); |
| fprintf (fp, "_%s:\n", sym); |
| fprintf (fp, "\tjmp *__imp__%s\n", sym); |
| fprintf (fp, "#else\n" |
| "#error \"Unknown target\"\n" |
| "#endif\n"); |
| } |
| |
| void |
| outputSyms (void) |
| { |
| FILE *fp; |
| sSymbol *l; |
| const char *pth = unifyCat ("./s_", cur_libname); |
| |
| _mkdir (pth); |
| |
| init_curIAT (); |
| |
| pth = unifyCat (pth, "/"); |
| |
| fp = fopen (unifyCat (pth, "do_init.c"), "wb"); |
| generate_stub_c (fp); |
| fclose (fp); |
| |
| fp = fopen (unifyCat (pth, "sec_start.S"), "wb"); |
| printHeader (fp); |
| |
| fprintf (fp, "\t.section .rdata, \"dr\"\n"); |
| fprintf (fp, "__def_module:\n"); |
| fprintf (fp, "\t.ascii \"%s\"\n", cur_libname); |
| fprintf (fp,"\t.section .rdata$imp.%s, \"dr\"\n", cur_libname); |
| fprintf (fp, "#ifdef __x86_64__\n"); |
| fprintf (fp, "\t.align 16\n"); |
| fprintf (fp, "\t.globl %s\n%s:\n", cur_IAT, cur_IAT); |
| fprintf (fp, "\t.quad __def_module, 0\n"); |
| fprintf (fp, "#elif __i386__\n"); |
| fprintf (fp, "\t.align 8\n"); |
| fprintf (fp, "\t.globl _%s\n_%s:\n", cur_IAT, cur_IAT); |
| fprintf (fp, "\t.long __def_module, 0\n"); |
| fprintf (fp, "#else\n#error \"Unknown target\"\n#endif\n"); |
| fprintf (fp, "\n"); |
| fprintf (fp,"\t.section .rdata$imp.xxxxxxxx, \"dr\"\n", cur_libname); |
| fprintf (fp,"\t.linkonce\n"); |
| fprintf (fp, "#ifdef __x86_64__\n"); |
| fprintf (fp, "\t.align 8\n"); |
| fprintf (fp, "\t.quad 0, 0\n"); |
| fprintf (fp, "#elif __i386__\n"); |
| fprintf (fp, "\t.align 4\n"); |
| fprintf (fp, "\t.long 0, 0\n"); |
| fprintf (fp, "#else\n#error \"Unknown target\"\n#endif\n"); |
| fclose (fp); |
| |
| l = t_sym; |
| while (l != NULL) |
| { |
| const char *hname = unifyCat (l->sym, ".S"); |
| |
| if (l->is_data == 0) |
| { |
| fp = fopen (unifyCat (pth, unifyCat ("stub_", hname)), "wb"); |
| |
| printStubCode (fp, hname, l->sym); |
| |
| fclose (fp); |
| } |
| fp = fopen (unifyCat (pth, unifyCat ("imp_", hname)), "wb"); |
| |
| printHeader (fp); |
| |
| fprintf (fp, "\t.file \"imp_%s\"\n", hname); |
| |
| fprintf (fp, "#ifdef __x86_64__\n"); |
| fprintf (fp, "\t.section .data$%s.iat.%s,\"w\"\n", cur_libname, l->sym); |
| fprintf (fp,"\t.globl __imp_%s\n", l->sym); |
| fprintf (fp, "\t.align 8\n"); |
| fprintf (fp, "__imp_%s:\n", l->sym); |
| fprintf (fp, "\t.quad %s\n", (l->libsym[0] != 0 ? l->libsym : "0")); |
| fprintf (fp, "\t.section .rdata, \"dr\"\n"); |
| fprintf (fp, "__imp_%s_name:\n", l->sym); |
| fprintf (fp, "\t.ascii \"%s\"\n", l->sym); |
| fprintf (fp, "\t.section .rdata$imp.%s.%s, \"dr\"\n", cur_libname, l->sym); |
| fprintf (fp, "\t.align 8\n"); |
| fprintf (fp, "\t.quad __imp_%s_name, __imp_%s\n", l->sym, l->sym); |
| |
| fprintf (fp, "#elif __i386__\n"); |
| fprintf (fp, "\t.section .data$%s.iat.%s, \"w\"\n", cur_libname, l->sym); |
| fprintf (fp, "\t.align 4\n"); |
| fprintf (fp,"\t.globl __imp__%s\n", l->sym); |
| fprintf (fp, "__imp__%s:\n", l->sym); |
| fprintf (fp, "\t.long %s%s\n", |
| (l->libsym[0] != 0 ? "_" : ""), |
| (l->libsym[0] != 0 ? l->libsym : "0")); |
| fprintf (fp, "\t.section .rdata, \"dr\"\n"); |
| fprintf (fp, "__imp__%s_name:\n", l->sym); |
| fprintf (fp, "\t.ascii \"%s\"\n", l->sym); |
| fprintf (fp, "\t.section .rdata$imp.%s.%s, \"dr\"\n", cur_libname, l->sym); |
| fprintf (fp, "\t.align 4\n"); |
| fprintf (fp, "\t.long __imp_%s__name, __imp__%s\n", l->sym, l->sym); |
| |
| fprintf (fp, "#else\n#error \"Unknown target\"\n#endif\n"); |
| |
| fclose (fp); |
| |
| if (l->subs != NULL) |
| { |
| sSymbol *p; |
| |
| p = l->subs; |
| while (p != NULL) |
| { |
| const char *hn = unifyCat (p->sym, ".S"); |
| fp = fopen (unifyCat (pth, unifyCat ("stub_", hn)), "wb"); |
| |
| printStubCode (fp, hn, p->sym); |
| |
| fclose (fp); |
| |
| p = p->next; |
| } |
| |
| p = l->subs; |
| while (p != NULL) |
| { |
| const char *hn = unifyCat (p->sym, ".S"); |
| fp = fopen (unifyCat (pth, unifyCat ("imp_", hn)), "wb"); |
| |
| printHeader (fp); |
| |
| fprintf (fp, "\t.file \"imp_%s\"\n", hn); |
| |
| fprintf (fp, "#ifdef __x86_64__\n"); |
| fprintf (fp, "\t.section .data$%s.iat.%s,\"w\"\n", cur_libname, p->sym); |
| fprintf (fp,"\t.globl __imp_%s\n", p->sym); |
| fprintf (fp, "\t.align 8\n"); |
| fprintf (fp, "__imp_%s:\n", p->sym); |
| fprintf (fp, "\t.quad %s\n", (p->libsym[0] != 0 ? p->libsym : (l->libsym[0] != 0 ? l->libsym : "0"))); |
| |
| fprintf (fp, "\t.section .rdata$imp.%s.%s, \"dr\"\n", cur_libname, p->sym); |
| fprintf (fp, "\t.align 8\n"); |
| fprintf (fp, "\t.quad __imp_%s, 1, __imp_%s, 0\n", l->sym, p->sym); |
| |
| fprintf (fp, "#elif __i386__\n"); |
| fprintf (fp, "\t.section .data$%s.iat.%s, \"w\"\n", cur_libname, p->sym); |
| fprintf (fp, "\t.align 4\n"); |
| fprintf (fp,"\t.globl __imp__%s\n", p->sym); |
| fprintf (fp, "__imp__%s:\n", p->sym); |
| fprintf (fp, "\t.long %s\n", (p->libsym[0] != 0 ? p->libsym : (l->libsym[0] != 0 ? l->libsym : "0"))); |
| |
| fprintf (fp, "\t.section .rdata$imp.%s.%s, \"dr\"\n", cur_libname, p->sym); |
| fprintf (fp, "\t.align 4\n"); |
| fprintf (fp, "\t.long __imp__%s, 1, __imp__%s, 0\n", l->sym, p->sym); |
| |
| fprintf (fp, "#else\n#error \"Unknown target\"\n#endif\n"); |
| |
| fclose (fp); |
| |
| p = p->next; |
| } |
| } |
| |
| l = l->next; |
| } |
| } |
| |
| static void generate_stub_c (FILE *fp) |
| { |
| printHeader (fp); |
| fprintf (fp, |
| "#include <windows.h>\n" |
| "#include <stdlib.h>\n" |
| "\n" |
| "extern size_t %s[];\n" |
| "\n" |
| "int do_stub_%s (void);\n" |
| "\n", cur_IAT, cur_dllsym); |
| fprintf (fp, |
| "int\n" |
| "do_stub_%s (void)\n" |
| "{\n" |
| " const char *pc, *dllname = \"\";\n" |
| " int i;\n" |
| " size_t *pimp, *piat, p;\n" |
| " HMODULE hmod = NULL;\n" |
| "\n" |
| " for (i = 0; %s[i] != 0;)\n" |
| " {\n" |
| " if (%s[i+1] == 0)\n", cur_dllsym, cur_IAT, cur_IAT); |
| fprintf (fp, |
| " {\n" |
| "\tdllname = (const char *) %s[0];\n" |
| "\tif (!hmod)\n" |
| "\t hmod = GetModuleHandleA (dllname);\n" |
| "\ti += 2;\n" |
| " }\n", cur_IAT); |
| |
| fprintf (fp, |
| " else if (%s[i+1] == 1)\n" |
| " {\n" |
| "\tpiat = (size_t *) %s[i];\n" |
| "\tp = piat[0];\n" |
| "\ti += 2;\n" |
| "\twhile ((piat = (size_t *) %s[i]) != NULL)\n" |
| "\t {\n" |
| "\t piat[0] = p;\n" |
| "\t ++i;\n" |
| "\t }\n" |
| "\t++i;\n" |
| " }\n", cur_IAT, cur_IAT, cur_IAT); |
| |
| fprintf (fp, |
| " else\n" |
| " {\n" |
| "\tif (!hmod)\n" |
| "\t hmod = LoadLibraryA (\"%s\");\n" |
| "\tpc = (const char *) %s[i];\n" |
| "\tpimp = (size_t *) %s[i+1];\n" |
| "\tp = (size_t) GetProcAddress (hmod, pc);\n" |
| "\n" |
| "\tif (p)\n" |
| "\t pimp[0] = p;\n" |
| "\ti += 2;\n" |
| " }\n", cur_libname, cur_IAT, cur_IAT); |
| |
| fprintf (fp, |
| " }\n" |
| "\n" |
| " return 0;\n" |
| "}\n"); |
| } |