tccpe: improve dllimport/export and use for tcc_add_symbol
This commit is contained in:
parent
bdb9387a74
commit
2341ee5142
7 changed files with 178 additions and 134 deletions
10
i386-gen.c
10
i386-gen.c
|
@ -215,9 +215,10 @@ ST_FUNC void load(int r, SValue *sv)
|
||||||
SValue v1;
|
SValue v1;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (pe_dllimport(r, sv, load))
|
SValue v2;
|
||||||
return;
|
sv = pe_getimport(sv, &v2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fr = sv->r;
|
fr = sv->r;
|
||||||
ft = sv->type.t;
|
ft = sv->type.t;
|
||||||
fc = sv->c.ul;
|
fc = sv->c.ul;
|
||||||
|
@ -283,9 +284,10 @@ ST_FUNC void store(int r, SValue *v)
|
||||||
int fr, bt, ft, fc;
|
int fr, bt, ft, fc;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (pe_dllimport(r, v, store))
|
SValue v2;
|
||||||
return;
|
v = pe_getimport(v, &v2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ft = v->type.t;
|
ft = v->type.t;
|
||||||
fc = v->c.ul;
|
fc = v->c.ul;
|
||||||
fr = v->r & VT_VALMASK;
|
fr = v->r & VT_VALMASK;
|
||||||
|
|
44
libtcc.c
44
libtcc.c
|
@ -393,7 +393,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||||
unsigned long value, unsigned long size,
|
unsigned long value, unsigned long size,
|
||||||
int can_add_underscore)
|
int can_add_underscore)
|
||||||
{
|
{
|
||||||
int sym_type, sym_bind, sh_num, info, other, attr;
|
int sym_type, sym_bind, sh_num, info, other;
|
||||||
ElfW(Sym) *esym;
|
ElfW(Sym) *esym;
|
||||||
const char *name;
|
const char *name;
|
||||||
char buf1[256];
|
char buf1[256];
|
||||||
|
@ -405,26 +405,12 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||||
else
|
else
|
||||||
sh_num = section->sh_num;
|
sh_num = section->sh_num;
|
||||||
|
|
||||||
other = attr = 0;
|
|
||||||
|
|
||||||
if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
|
if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
|
||||||
sym_type = STT_FUNC;
|
sym_type = STT_FUNC;
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (sym->type.ref)
|
|
||||||
attr = sym->type.ref->r;
|
|
||||||
if (FUNC_EXPORT(attr))
|
|
||||||
other |= 1;
|
|
||||||
if (FUNC_CALL(attr) == FUNC_STDCALL)
|
|
||||||
other |= 2;
|
|
||||||
#endif
|
|
||||||
} else if ((sym->type.t & VT_BTYPE) == VT_VOID) {
|
} else if ((sym->type.t & VT_BTYPE) == VT_VOID) {
|
||||||
sym_type = STT_NOTYPE;
|
sym_type = STT_NOTYPE;
|
||||||
} else {
|
} else {
|
||||||
sym_type = STT_OBJECT;
|
sym_type = STT_OBJECT;
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (sym->type.t & VT_EXPORT)
|
|
||||||
other |= 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sym->type.t & VT_STATIC)
|
if (sym->type.t & VT_STATIC)
|
||||||
|
@ -463,12 +449,27 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
other = 0;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if ((other & 2) && can_add_underscore) {
|
if (sym->type.t & VT_EXPORT)
|
||||||
sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
|
other |= 1;
|
||||||
name = buf1;
|
if (sym_type == STT_FUNC && sym->type.ref) {
|
||||||
} else
|
int attr = sym->type.ref->r;
|
||||||
|
if (FUNC_EXPORT(attr))
|
||||||
|
other |= 1;
|
||||||
|
if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {
|
||||||
|
sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);
|
||||||
|
name = buf1;
|
||||||
|
other |= 2;
|
||||||
|
can_add_underscore = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (find_elf_sym(tcc_state->dynsymtab_section, name))
|
||||||
|
other |= 4;
|
||||||
|
if (sym->type.t & VT_IMPORT)
|
||||||
|
other |= 4;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (tcc_state->leading_underscore && can_add_underscore) {
|
if (tcc_state->leading_underscore && can_add_underscore) {
|
||||||
buf1[0] = '_';
|
buf1[0] = '_';
|
||||||
|
@ -482,7 +483,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||||
esym->st_value = value;
|
esym->st_value = value;
|
||||||
esym->st_size = size;
|
esym->st_size = size;
|
||||||
esym->st_shndx = sh_num;
|
esym->st_shndx = sh_num;
|
||||||
esym->st_other |= other;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,9 +1215,13 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, void *val)
|
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, void *val)
|
||||||
{
|
{
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
pe_putimport(s, 0, name, val);
|
||||||
|
#else
|
||||||
add_elf_sym(symtab_section, (uplong)val, 0,
|
add_elf_sym(symtab_section, (uplong)val, 0,
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||||
SHN_ABS, name);
|
SHN_ABS, name);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
tcc.h
10
tcc.h
|
@ -261,12 +261,13 @@ typedef struct DLLReference {
|
||||||
/* GNUC attribute definition */
|
/* GNUC attribute definition */
|
||||||
typedef struct AttributeDef {
|
typedef struct AttributeDef {
|
||||||
unsigned
|
unsigned
|
||||||
packed : 1,
|
|
||||||
aligned : 5, /* alignement (0..16) */
|
|
||||||
func_call : 3, /* calling convention (0..5), see below */
|
func_call : 3, /* calling convention (0..5), see below */
|
||||||
|
aligned : 5, /* alignement (0..16) */
|
||||||
|
packed : 1,
|
||||||
func_export : 1,
|
func_export : 1,
|
||||||
func_import : 1,
|
func_import : 1,
|
||||||
func_args : 8;
|
func_args : 5,
|
||||||
|
fill : 16;
|
||||||
struct Section *section;
|
struct Section *section;
|
||||||
} AttributeDef;
|
} AttributeDef;
|
||||||
|
|
||||||
|
@ -1176,7 +1177,8 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
|
||||||
ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd);
|
ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd);
|
||||||
ST_FUNC int pe_add_dll(struct TCCState *s, const char *libraryname);
|
ST_FUNC int pe_add_dll(struct TCCState *s, const char *libraryname);
|
||||||
ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
|
ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
|
||||||
ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv));
|
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, const void *value);
|
||||||
|
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
|
||||||
/* tiny_impdef.c */
|
/* tiny_impdef.c */
|
||||||
ST_FUNC char *get_export_names(FILE *fp);
|
ST_FUNC char *get_export_names(FILE *fp);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
|
26
tccgen.c
26
tccgen.c
|
@ -1343,10 +1343,8 @@ static void gen_opic(int op)
|
||||||
}
|
}
|
||||||
goto general_case;
|
goto general_case;
|
||||||
} else if (c2 && (op == '+' || op == '-') &&
|
} else if (c2 && (op == '+' || op == '-') &&
|
||||||
(((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM)
|
(((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM))
|
||||||
&& !(vtop[-1].sym->type.t & VT_IMPORT))
|
|| (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
|
||||||
||
|
|
||||||
(vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
|
|
||||||
/* symbol + constant case */
|
/* symbol + constant case */
|
||||||
if (op == '-')
|
if (op == '-')
|
||||||
l2 = -l2;
|
l2 = -l2;
|
||||||
|
@ -2973,7 +2971,7 @@ static void post_type(CType *type, AttributeDef *ad)
|
||||||
type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
|
type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
|
||||||
if ((pt.t & VT_BTYPE) == VT_VOID)
|
if ((pt.t & VT_BTYPE) == VT_VOID)
|
||||||
error("parameter declared as void");
|
error("parameter declared as void");
|
||||||
arg_size += (type_size(&pt, &align) + 3) & ~3;
|
arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
|
||||||
} else {
|
} else {
|
||||||
old_proto:
|
old_proto:
|
||||||
n = tok;
|
n = tok;
|
||||||
|
@ -5284,6 +5282,12 @@ ST_FUNC void decl(int l)
|
||||||
func_decl_list(sym);
|
func_decl_list(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
if (ad.func_import)
|
||||||
|
type.t |= VT_IMPORT;
|
||||||
|
if (ad.func_export)
|
||||||
|
type.t |= VT_EXPORT;
|
||||||
|
#endif
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
if (l == VT_LOCAL)
|
if (l == VT_LOCAL)
|
||||||
error("cannot use local functions");
|
error("cannot use local functions");
|
||||||
|
@ -5402,10 +5406,6 @@ ST_FUNC void decl(int l)
|
||||||
/* NOTE: as GCC, uninitialized global static
|
/* NOTE: as GCC, uninitialized global static
|
||||||
arrays of null size are considered as
|
arrays of null size are considered as
|
||||||
extern */
|
extern */
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (ad.func_import)
|
|
||||||
type.t |= VT_IMPORT;
|
|
||||||
#endif
|
|
||||||
external_sym(v, &type, r);
|
external_sym(v, &type, r);
|
||||||
} else {
|
} else {
|
||||||
type.t |= (btype.t & VT_STATIC); /* Retain "static". */
|
type.t |= (btype.t & VT_STATIC); /* Retain "static". */
|
||||||
|
@ -5415,12 +5415,7 @@ ST_FUNC void decl(int l)
|
||||||
r |= l;
|
r |= l;
|
||||||
if (has_init)
|
if (has_init)
|
||||||
next();
|
next();
|
||||||
#ifdef TCC_TARGET_PE
|
decl_initializer_alloc(&type, &ad, r, has_init, v, l);
|
||||||
if (ad.func_export)
|
|
||||||
type.t |= VT_EXPORT;
|
|
||||||
#endif
|
|
||||||
decl_initializer_alloc(&type, &ad, r,
|
|
||||||
has_init, v, l);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tok != ',') {
|
if (tok != ',') {
|
||||||
|
@ -5432,4 +5427,3 @@ ST_FUNC void decl(int l)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
172
tccpe.c
172
tccpe.c
|
@ -753,10 +753,10 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
|
||||||
int dll_index;
|
int dll_index;
|
||||||
struct pe_import_info *p;
|
struct pe_import_info *p;
|
||||||
struct import_symbol *s;
|
struct import_symbol *s;
|
||||||
|
ElfW(Sym) *isym;
|
||||||
|
|
||||||
dll_index = ((ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index)->st_value;
|
isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
|
||||||
if (0 == dll_index)
|
dll_index = isym->st_size;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
|
i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
|
||||||
if (-1 != i) {
|
if (-1 != i) {
|
||||||
|
@ -804,14 +804,20 @@ static void pe_build_imports(struct pe_info *pe)
|
||||||
|
|
||||||
for (i = 0; i < pe->imp_count; ++i) {
|
for (i = 0; i < pe->imp_count; ++i) {
|
||||||
IMAGE_IMPORT_DESCRIPTOR *hdr;
|
IMAGE_IMPORT_DESCRIPTOR *hdr;
|
||||||
int k, n;
|
int k, n, dllindex;
|
||||||
ADDR3264 v;
|
ADDR3264 v;
|
||||||
struct pe_import_info *p = pe->imp_info[i];
|
struct pe_import_info *p = pe->imp_info[i];
|
||||||
const char *name = pe->s1->loaded_dlls[p->dll_index-1]->name;
|
const char *name;
|
||||||
|
DLLReference *dllref;
|
||||||
|
|
||||||
|
dllindex = p->dll_index;
|
||||||
|
if (dllindex)
|
||||||
|
name = (dllref = pe->s1->loaded_dlls[dllindex-1])->name;
|
||||||
|
else
|
||||||
|
name = "", dllref = NULL;
|
||||||
|
|
||||||
/* put the dll name into the import header */
|
/* put the dll name into the import header */
|
||||||
v = put_elf_str(pe->thunk, name);
|
v = put_elf_str(pe->thunk, name);
|
||||||
|
|
||||||
hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
|
hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
|
||||||
hdr->FirstThunk = thk_ptr + rva_base;
|
hdr->FirstThunk = thk_ptr + rva_base;
|
||||||
hdr->OriginalFirstThunk = ent_ptr + rva_base;
|
hdr->OriginalFirstThunk = ent_ptr + rva_base;
|
||||||
|
@ -832,10 +838,12 @@ static void pe_build_imports(struct pe_info *pe)
|
||||||
put_elf_str(pe->thunk, name);
|
put_elf_str(pe->thunk, name);
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
if (pe->type == PE_RUN) {
|
if (pe->type == PE_RUN) {
|
||||||
DLLReference *dllref = pe->s1->loaded_dlls[imp_sym->st_value-1];
|
v = imp_sym->st_value;
|
||||||
if ( !dllref->handle )
|
if (dllref) {
|
||||||
dllref->handle = LoadLibrary(dllref->name);
|
if ( !dllref->handle )
|
||||||
v = (ADDR3264)GetProcAddress(dllref->handle, name);
|
dllref->handle = LoadLibrary(dllref->name);
|
||||||
|
v = (ADDR3264)GetProcAddress(dllref->handle, name);
|
||||||
|
}
|
||||||
if (!v)
|
if (!v)
|
||||||
error_noabort("undefined symbol '%s'", name);
|
error_noabort("undefined symbol '%s'", name);
|
||||||
}
|
}
|
||||||
|
@ -1214,9 +1222,6 @@ static int pe_check_symbols(struct pe_info *pe)
|
||||||
|
|
||||||
if (0 == imp_sym)
|
if (0 == imp_sym)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
is = pe_add_import(pe, imp_sym);
|
|
||||||
if (!is)
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
if (type == STT_NOTYPE) {
|
if (type == STT_NOTYPE) {
|
||||||
/* symbols from assembler have no type, find out which */
|
/* symbols from assembler have no type, find out which */
|
||||||
|
@ -1226,6 +1231,8 @@ static int pe_check_symbols(struct pe_info *pe)
|
||||||
type = STT_OBJECT;
|
type = STT_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is = pe_add_import(pe, imp_sym);
|
||||||
|
|
||||||
if (type == STT_FUNC) {
|
if (type == STT_FUNC) {
|
||||||
unsigned long offset = is->thk_offset;
|
unsigned long offset = is->thk_offset;
|
||||||
if (offset) {
|
if (offset) {
|
||||||
|
@ -1424,6 +1431,75 @@ static void pe_print_sections(TCCState *s1, const char *fname)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
/* helper function for load/store to insert one more indirection */
|
||||||
|
|
||||||
|
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
|
||||||
|
{
|
||||||
|
Sym *sym;
|
||||||
|
ElfW(Sym) *esym;
|
||||||
|
int r2;
|
||||||
|
|
||||||
|
if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
|
||||||
|
return sv;
|
||||||
|
sym = sv->sym;
|
||||||
|
if ((sym->type.t & (VT_EXTERN|VT_STATIC)) != VT_EXTERN)
|
||||||
|
return sv;
|
||||||
|
if (!sym->c)
|
||||||
|
put_extern_sym(sym, NULL, 0, 0);
|
||||||
|
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
|
||||||
|
if (!(esym->st_other & 4))
|
||||||
|
return sv;
|
||||||
|
|
||||||
|
// printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
|
||||||
|
|
||||||
|
memset(v2, 0, sizeof *v2);
|
||||||
|
v2->type.t = VT_PTR;
|
||||||
|
v2->r = VT_CONST | VT_SYM | VT_LVAL;
|
||||||
|
v2->sym = sv->sym;
|
||||||
|
|
||||||
|
r2 = get_reg(RC_INT);
|
||||||
|
load(r2, v2);
|
||||||
|
v2->r = r2;
|
||||||
|
|
||||||
|
if (sv->c.ui) {
|
||||||
|
vpushv(v2);
|
||||||
|
vpushi(sv->c.ui);
|
||||||
|
gen_opi('+');
|
||||||
|
*v2 = *vtop--;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2->type.t = sv->type.t;
|
||||||
|
v2->r |= sv->r & VT_LVAL;
|
||||||
|
return v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, const void *value)
|
||||||
|
{
|
||||||
|
return add_elf_sym(
|
||||||
|
s1->dynsymtab_section,
|
||||||
|
(uplong)value,
|
||||||
|
dllindex, /* st_size */
|
||||||
|
ELFW_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
|
0,
|
||||||
|
value ? SHN_ABS : SHN_UNDEF,
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_dllref(TCCState *s1, const char *dllname)
|
||||||
|
{
|
||||||
|
DLLReference *dllref;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < s1->nb_loaded_dlls; ++i)
|
||||||
|
if (0 == strcmp(s1->loaded_dlls[i]->name, dllname))
|
||||||
|
return i + 1;
|
||||||
|
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
|
||||||
|
strcpy(dllref->name, dllname);
|
||||||
|
dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
|
||||||
|
return s1->nb_loaded_dlls;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||||
|
@ -1503,8 +1579,7 @@ static char *get_line(char *line, int size, FILE *fp)
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
static int pe_load_def(TCCState *s1, FILE *fp)
|
static int pe_load_def(TCCState *s1, FILE *fp)
|
||||||
{
|
{
|
||||||
DLLReference *dllref;
|
int state = 0, ret = -1, dllindex = 0;
|
||||||
int state = 0, ret = -1;
|
|
||||||
char line[400], dllname[80], *p;
|
char line[400], dllname[80], *p;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1528,16 +1603,11 @@ static int pe_load_def(TCCState *s1, FILE *fp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
|
dllindex = add_dllref(s1, dllname);
|
||||||
strcpy(dllref->name, dllname);
|
|
||||||
dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
|
|
||||||
++state;
|
++state;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
add_elf_sym(s1->dynsymtab_section,
|
pe_putimport(s1, dllindex, p, NULL);
|
||||||
s1->nb_loaded_dlls, 0,
|
|
||||||
ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
|
|
||||||
text_section->sh_num, p);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1552,24 +1622,16 @@ quit:
|
||||||
|
|
||||||
static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
|
static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
int index;
|
||||||
p = get_export_names(fp);
|
p = get_export_names(fp);
|
||||||
if (p) {
|
if (!p)
|
||||||
DLLReference *dllref;
|
return -1;
|
||||||
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
|
index = add_dllref(s1, dllname);
|
||||||
strcpy(dllref->name, dllname);
|
for (q = p; *q; q += 1 + strlen(q))
|
||||||
dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
|
pe_putimport(s1, index, q, NULL);
|
||||||
for (q = p, i = 0; *q; ++i) {
|
tcc_free(p);
|
||||||
add_elf_sym(s1->dynsymtab_section,
|
return 0;
|
||||||
s1->nb_loaded_dlls, 0,
|
|
||||||
ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
|
|
||||||
text_section->sh_num, q);
|
|
||||||
q += 1 + strlen(q);
|
|
||||||
}
|
|
||||||
tcc_free(p);
|
|
||||||
}
|
|
||||||
return i ? 0 : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
@ -1605,32 +1667,6 @@ ST_FUNC int pe_add_dll(struct TCCState *s, const char *libname)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
/* helper function for load/store to insert one more indirection */
|
|
||||||
|
|
||||||
ST_FUNC int pe_dllimport(int r, SValue *sv, void (*fn)(int r, SValue *sv))
|
|
||||||
{
|
|
||||||
int t;
|
|
||||||
if ((sv->r & (VT_VALMASK|VT_SYM|VT_CONST)) != (VT_SYM|VT_CONST))
|
|
||||||
return 0;
|
|
||||||
t = sv->sym->type.t;
|
|
||||||
if (0 == (t & VT_IMPORT))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
sv->sym->type.t = t & ~VT_IMPORT;
|
|
||||||
//printf("import %x %04x %s\n", t, ind, get_tok_str(sv->sym->v, NULL));
|
|
||||||
|
|
||||||
vpushv(sv);
|
|
||||||
vtop->type.t &= ~(VT_ARRAY|VT_IMPORT);
|
|
||||||
mk_pointer(&vtop->type);
|
|
||||||
indir();
|
|
||||||
fn(r, vtop);
|
|
||||||
--vtop;
|
|
||||||
|
|
||||||
sv->sym->type.t = t;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||||
|
@ -1702,6 +1738,8 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
|
||||||
/* need this for 'tccelf.c:relocate_section()' */
|
/* need this for 'tccelf.c:relocate_section()' */
|
||||||
s1->output_type = TCC_OUTPUT_EXE;
|
s1->output_type = TCC_OUTPUT_EXE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
pe_type = PE_EXE;
|
||||||
|
|
||||||
start_symbol =
|
start_symbol =
|
||||||
TCC_OUTPUT_MEMORY == s1->output_type
|
TCC_OUTPUT_MEMORY == s1->output_type
|
||||||
|
@ -1731,9 +1769,12 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
||||||
|
pe_type = PE_RUN;
|
||||||
|
|
||||||
if (start_symbol) {
|
if (start_symbol) {
|
||||||
addr = (uplong)tcc_get_symbol_err(s1, start_symbol);
|
addr = (uplong)tcc_get_symbol_err(s1, start_symbol);
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY && addr)
|
if (PE_RUN == pe_type && addr)
|
||||||
/* for -run GUI's, put '_runwinmain' instead of 'main' */
|
/* for -run GUI's, put '_runwinmain' instead of 'main' */
|
||||||
add_elf_sym(symtab_section,
|
add_elf_sym(symtab_section,
|
||||||
addr, 0,
|
addr, 0,
|
||||||
|
@ -1823,7 +1864,6 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
|
||||||
#ifndef TCC_IS_NATIVE
|
#ifndef TCC_IS_NATIVE
|
||||||
error_noabort("-run supported only on native platform");
|
error_noabort("-run supported only on native platform");
|
||||||
#endif
|
#endif
|
||||||
pe.type = PE_RUN;
|
|
||||||
pe.thunk = data_section;
|
pe.thunk = data_section;
|
||||||
pe_build_imports(&pe);
|
pe_build_imports(&pe);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ int main(int argc, char **argv)
|
||||||
fp = op = NULL;
|
fp = op = NULL;
|
||||||
v = 0;
|
v = 0;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
p = NULL;
|
||||||
|
|
||||||
for (i = 1; i < argc; ++i) {
|
for (i = 1; i < argc; ++i) {
|
||||||
const char *a = argv[i];
|
const char *a = argv[i];
|
||||||
|
@ -90,19 +91,20 @@ usage:
|
||||||
if (0 == outfile[0])
|
if (0 == outfile[0])
|
||||||
{
|
{
|
||||||
strcpy(outfile, file_basename(infile));
|
strcpy(outfile, file_basename(infile));
|
||||||
p = strrchr(outfile, '.');
|
q = strrchr(outfile, '.');
|
||||||
if (NULL == p)
|
if (NULL == q)
|
||||||
p = strchr(outfile, 0);
|
q = strchr(outfile, 0);
|
||||||
strcpy(p, ".def");
|
strcpy(q, ".def");
|
||||||
}
|
}
|
||||||
|
|
||||||
file = infile;
|
file = infile;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
for (pp = ext; *pp; ++pp)
|
pp = ext;
|
||||||
if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
|
do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
|
||||||
file = path;
|
file = path;
|
||||||
break;
|
break;
|
||||||
}
|
} while (*pp++);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fp = fopen(file, "rb");
|
fp = fopen(file, "rb");
|
||||||
|
@ -110,6 +112,14 @@ usage:
|
||||||
fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
|
fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
if (v)
|
||||||
|
printf("--> %s\n", file);
|
||||||
|
|
||||||
|
p = get_export_names(fp);
|
||||||
|
if (NULL == p) {
|
||||||
|
fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
op = fopen(outfile, "w");
|
op = fopen(outfile, "w");
|
||||||
if (NULL == op) {
|
if (NULL == op) {
|
||||||
|
@ -117,21 +127,11 @@ usage:
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v)
|
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
|
||||||
printf("--> %s\n", infile);
|
|
||||||
|
|
||||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(infile));
|
|
||||||
p = get_export_names(fp);
|
|
||||||
if (NULL == p) {
|
|
||||||
fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (q = p, i = 0; *q; ++i) {
|
for (q = p, i = 0; *q; ++i) {
|
||||||
fprintf(op, "%s\n", q);
|
fprintf(op, "%s\n", q);
|
||||||
q += strlen(q) + 1;
|
q += strlen(q) + 1;
|
||||||
}
|
}
|
||||||
free(p);
|
|
||||||
|
|
||||||
if (v) {
|
if (v) {
|
||||||
printf("<-- %s\n", outfile);
|
printf("<-- %s\n", outfile);
|
||||||
|
@ -141,6 +141,8 @@ usage:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
the_end:
|
the_end:
|
||||||
|
if (p)
|
||||||
|
free(p);
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (op)
|
if (op)
|
||||||
|
|
|
@ -335,8 +335,8 @@ void load(int r, SValue *sv)
|
||||||
SValue v1;
|
SValue v1;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (pe_dllimport(r, sv, load))
|
SValue v2;
|
||||||
return;
|
sv = pe_getimport(sv, &v2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fr = sv->r;
|
fr = sv->r;
|
||||||
|
@ -469,8 +469,8 @@ void store(int r, SValue *v)
|
||||||
int pic = 0;
|
int pic = 0;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (pe_dllimport(r, v, store))
|
SValue v2;
|
||||||
return;
|
v = pe_getimport(v, &v2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ft = v->type.t;
|
ft = v->type.t;
|
||||||
|
|
Loading…
Reference in a new issue