blob: 074b326d8f97767f9a31a6886609ee4a778cd314 [file] [log] [blame]
/*
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");
}