aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2010-01-14 20:55:51 +0100
committergrischka <grischka>2010-01-14 20:59:42 +0100
commit2341ee5142c184e06964f66696ebf88931953e7d (patch)
tree6f858fd311ae47ec4508301e6ebf1df33bd42c8a
parentbdb9387a7494d7d5e299cb13bcc94f00215976dd (diff)
downloadtinycc-2341ee5142c184e06964f66696ebf88931953e7d.tar.gz
tinycc-2341ee5142c184e06964f66696ebf88931953e7d.tar.bz2
tccpe: improve dllimport/export and use for tcc_add_symbol
-rw-r--r--i386-gen.c10
-rw-r--r--libtcc.c44
-rw-r--r--tcc.h10
-rw-r--r--tccgen.c26
-rw-r--r--tccpe.c172
-rw-r--r--win32/tools/tiny_impdef.c40
-rw-r--r--x86_64-gen.c8
7 files changed, 177 insertions, 133 deletions
diff --git a/i386-gen.c b/i386-gen.c
index 9a8ceee..5ea70df 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -215,9 +215,10 @@ ST_FUNC void load(int r, SValue *sv)
SValue v1;
#ifdef TCC_TARGET_PE
- if (pe_dllimport(r, sv, load))
- return;
+ SValue v2;
+ sv = pe_getimport(sv, &v2);
#endif
+
fr = sv->r;
ft = sv->type.t;
fc = sv->c.ul;
@@ -283,9 +284,10 @@ ST_FUNC void store(int r, SValue *v)
int fr, bt, ft, fc;
#ifdef TCC_TARGET_PE
- if (pe_dllimport(r, v, store))
- return;
+ SValue v2;
+ v = pe_getimport(v, &v2);
#endif
+
ft = v->type.t;
fc = v->c.ul;
fr = v->r & VT_VALMASK;
diff --git a/libtcc.c b/libtcc.c
index cc1c6af..ae80bc6 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -393,7 +393,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
unsigned long value, unsigned long size,
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;
const char *name;
char buf1[256];
@@ -405,26 +405,12 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
else
sh_num = section->sh_num;
- other = attr = 0;
-
if ((sym->type.t & VT_BTYPE) == VT_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) {
sym_type = STT_NOTYPE;
} else {
sym_type = STT_OBJECT;
-#ifdef TCC_TARGET_PE
- if (sym->type.t & VT_EXPORT)
- other |= 1;
-#endif
}
if (sym->type.t & VT_STATIC)
@@ -463,12 +449,27 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
}
}
#endif
+ other = 0;
#ifdef TCC_TARGET_PE
- if ((other & 2) && can_add_underscore) {
- sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
- name = buf1;
- } else
+ if (sym->type.t & VT_EXPORT)
+ other |= 1;
+ if (sym_type == STT_FUNC && sym->type.ref) {
+ 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
if (tcc_state->leading_underscore && can_add_underscore) {
buf1[0] = '_';
@@ -482,7 +483,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
esym->st_value = value;
esym->st_size = size;
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)
{
+#ifdef TCC_TARGET_PE
+ pe_putimport(s, 0, name, val);
+#else
add_elf_sym(symtab_section, (uplong)val, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
SHN_ABS, name);
+#endif
return 0;
}
diff --git a/tcc.h b/tcc.h
index 700d0c5..780c18e 100644
--- a/tcc.h
+++ b/tcc.h
@@ -261,12 +261,13 @@ typedef struct DLLReference {
/* GNUC attribute definition */
typedef struct AttributeDef {
unsigned
- packed : 1,
- aligned : 5, /* alignement (0..16) */
func_call : 3, /* calling convention (0..5), see below */
+ aligned : 5, /* alignement (0..16) */
+ packed : 1,
func_export : 1,
func_import : 1,
- func_args : 8;
+ func_args : 5,
+ fill : 16;
struct Section *section;
} 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_add_dll(struct TCCState *s, const char *libraryname);
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 */
ST_FUNC char *get_export_names(FILE *fp);
#ifdef TCC_TARGET_X86_64
diff --git a/tccgen.c b/tccgen.c
index b608c1f..be8d80f 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -1343,10 +1343,8 @@ static void gen_opic(int op)
}
goto general_case;
} else if (c2 && (op == '+' || op == '-') &&
- (((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_SYM)) == (VT_CONST | VT_SYM))
+ || (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
/* symbol + constant case */
if (op == '-')
l2 = -l2;
@@ -2973,7 +2971,7 @@ static void post_type(CType *type, AttributeDef *ad)
type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
if ((pt.t & VT_BTYPE) == VT_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 {
old_proto:
n = tok;
@@ -5284,6 +5282,12 @@ ST_FUNC void decl(int l)
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 (l == VT_LOCAL)
error("cannot use local functions");
@@ -5402,10 +5406,6 @@ ST_FUNC void decl(int l)
/* NOTE: as GCC, uninitialized global static
arrays of null size are considered as
extern */
-#ifdef TCC_TARGET_PE
- if (ad.func_import)
- type.t |= VT_IMPORT;
-#endif
external_sym(v, &type, r);
} else {
type.t |= (btype.t & VT_STATIC); /* Retain "static". */
@@ -5415,12 +5415,7 @@ ST_FUNC void decl(int l)
r |= l;
if (has_init)
next();
-#ifdef TCC_TARGET_PE
- if (ad.func_export)
- type.t |= VT_EXPORT;
-#endif
- decl_initializer_alloc(&type, &ad, r,
- has_init, v, l);
+ decl_initializer_alloc(&type, &ad, r, has_init, v, l);
}
}
if (tok != ',') {
@@ -5432,4 +5427,3 @@ ST_FUNC void decl(int l)
}
}
}
-
diff --git a/tccpe.c b/tccpe.c
index 536f4cd..e8321dc 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -753,10 +753,10 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
int dll_index;
struct pe_import_info *p;
struct import_symbol *s;
+ ElfW(Sym) *isym;
- dll_index = ((ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index)->st_value;
- if (0 == dll_index)
- return NULL;
+ isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
+ dll_index = isym->st_size;
i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
if (-1 != i) {
@@ -804,14 +804,20 @@ static void pe_build_imports(struct pe_info *pe)
for (i = 0; i < pe->imp_count; ++i) {
IMAGE_IMPORT_DESCRIPTOR *hdr;
- int k, n;
+ int k, n, dllindex;
ADDR3264 v;
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 */
v = put_elf_str(pe->thunk, name);
-
hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
hdr->FirstThunk = thk_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);
#ifdef TCC_IS_NATIVE
if (pe->type == PE_RUN) {
- DLLReference *dllref = pe->s1->loaded_dlls[imp_sym->st_value-1];
- if ( !dllref->handle )
- dllref->handle = LoadLibrary(dllref->name);
- v = (ADDR3264)GetProcAddress(dllref->handle, name);
+ v = imp_sym->st_value;
+ if (dllref) {
+ if ( !dllref->handle )
+ dllref->handle = LoadLibrary(dllref->name);
+ v = (ADDR3264)GetProcAddress(dllref->handle, name);
+ }
if (!v)
error_noabort("undefined symbol '%s'", name);
}
@@ -1214,9 +1222,6 @@ static int pe_check_symbols(struct pe_info *pe)
if (0 == imp_sym)
goto not_found;
- is = pe_add_import(pe, imp_sym);
- if (!is)
- goto not_found;
if (type == STT_NOTYPE) {
/* 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;
}
+ is = pe_add_import(pe, imp_sym);
+
if (type == STT_FUNC) {
unsigned long offset = is->thk_offset;
if (offset) {
@@ -1425,6 +1432,75 @@ static void pe_print_sections(TCCState *s1, const char *fname)
#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)
{
@@ -1503,8 +1579,7 @@ static char *get_line(char *line, int size, FILE *fp)
/* ------------------------------------------------------------- */
static int pe_load_def(TCCState *s1, FILE *fp)
{
- DLLReference *dllref;
- int state = 0, ret = -1;
+ int state = 0, ret = -1, dllindex = 0;
char line[400], dllname[80], *p;
for (;;) {
@@ -1528,16 +1603,11 @@ static int pe_load_def(TCCState *s1, FILE *fp)
continue;
case 2:
- dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
- strcpy(dllref->name, dllname);
- dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
+ dllindex = add_dllref(s1, dllname);
++state;
default:
- add_elf_sym(s1->dynsymtab_section,
- s1->nb_loaded_dlls, 0,
- ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
- text_section->sh_num, p);
+ pe_putimport(s1, dllindex, p, NULL);
continue;
}
}
@@ -1552,24 +1622,16 @@ quit:
static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
{
- int i = 0;
char *p, *q;
+ int index;
p = get_export_names(fp);
- if (p) {
- DLLReference *dllref;
- dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
- strcpy(dllref->name, dllname);
- dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
- for (q = p, i = 0; *q; ++i) {
- add_elf_sym(s1->dynsymtab_section,
- 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;
+ if (!p)
+ return -1;
+ index = add_dllref(s1, dllname);
+ for (q = p; *q; q += 1 + strlen(q))
+ pe_putimport(s1, index, q, NULL);
+ tcc_free(p);
+ return 0;
}
/* ------------------------------------------------------------- */
@@ -1606,32 +1668,6 @@ ST_FUNC int pe_add_dll(struct TCCState *s, const char *libname)
}
/* ------------------------------------------------------------- */
-/* 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
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()' */
s1->output_type = TCC_OUTPUT_EXE;
}
+ else
+ pe_type = PE_EXE;
start_symbol =
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) {
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' */
add_elf_sym(symtab_section,
addr, 0,
@@ -1823,7 +1864,6 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
#ifndef TCC_IS_NATIVE
error_noabort("-run supported only on native platform");
#endif
- pe.type = PE_RUN;
pe.thunk = data_section;
pe_build_imports(&pe);
}
diff --git a/win32/tools/tiny_impdef.c b/win32/tools/tiny_impdef.c
index b024a90..f801e0b 100644
--- a/win32/tools/tiny_impdef.c
+++ b/win32/tools/tiny_impdef.c
@@ -60,6 +60,7 @@ int main(int argc, char **argv)
fp = op = NULL;
v = 0;
ret = 1;
+ p = NULL;
for (i = 1; i < argc; ++i) {
const char *a = argv[i];
@@ -90,19 +91,20 @@ usage:
if (0 == outfile[0])
{
strcpy(outfile, file_basename(infile));
- p = strrchr(outfile, '.');
- if (NULL == p)
- p = strchr(outfile, 0);
- strcpy(p, ".def");
+ q = strrchr(outfile, '.');
+ if (NULL == q)
+ q = strchr(outfile, 0);
+ strcpy(q, ".def");
}
file = infile;
+
#ifdef _WIN32
- for (pp = ext; *pp; ++pp)
- if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
- file = path;
- break;
- }
+ pp = ext;
+ do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
+ file = path;
+ break;
+ } while (*pp++);
#endif
fp = fopen(file, "rb");
@@ -110,28 +112,26 @@ usage:
fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
goto the_end;
}
-
- op = fopen(outfile, "w");
- if (NULL == op) {
- fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
- goto the_end;
- }
-
if (v)
- printf("--> %s\n", infile);
+ printf("--> %s\n", file);
- 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;
}
+ op = fopen(outfile, "w");
+ if (NULL == op) {
+ fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
+ goto the_end;
+ }
+
+ fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
for (q = p, i = 0; *q; ++i) {
fprintf(op, "%s\n", q);
q += strlen(q) + 1;
}
- free(p);
if (v) {
printf("<-- %s\n", outfile);
@@ -141,6 +141,8 @@ usage:
ret = 0;
the_end:
+ if (p)
+ free(p);
if (fp)
fclose(fp);
if (op)
diff --git a/x86_64-gen.c b/x86_64-gen.c
index a80020f..10003d1 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -335,8 +335,8 @@ void load(int r, SValue *sv)
SValue v1;
#ifdef TCC_TARGET_PE
- if (pe_dllimport(r, sv, load))
- return;
+ SValue v2;
+ sv = pe_getimport(sv, &v2);
#endif
fr = sv->r;
@@ -469,8 +469,8 @@ void store(int r, SValue *v)
int pic = 0;
#ifdef TCC_TARGET_PE
- if (pe_dllimport(r, v, store))
- return;
+ SValue v2;
+ v = pe_getimport(v, &v2);
#endif
ft = v->type.t;