aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2009-07-06 21:34:22 +0200
committerunknown <gr@.(none)>2009-07-18 21:55:15 +0200
commit370cdeb628968fe1c9a53dbea0aae12c77008b67 (patch)
treed187c5951848966a82f3a2c11ae9a2f2b17ecfbf
parentbed17847bdfa872e219a12237e06df83e464bdba (diff)
downloadtinycc-370cdeb628968fe1c9a53dbea0aae12c77008b67.tar.gz
tinycc-370cdeb628968fe1c9a53dbea0aae12c77008b67.tar.bz2
tccpe: build IAT vector with with -run too
This prepares for x86_64 where we need the vector for far jumps. Also, resolve DLL symbols in place
-rw-r--r--libtcc.c13
-rw-r--r--tcc.h1
-rw-r--r--tccelf.c6
-rw-r--r--tccpe.c90
4 files changed, 42 insertions, 68 deletions
diff --git a/libtcc.c b/libtcc.c
index 43293e2..30cc552 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -212,12 +212,9 @@ static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
int tcc_output_coff(TCCState *s1, FILE *f);
/* tccpe.c */
-void *resolve_sym(TCCState *s1, const char *sym, int type);
int pe_load_def_file(struct TCCState *s1, int fd);
int pe_test_res_file(void *v, int size);
int pe_load_res_file(struct TCCState *s1, int fd);
-void pe_add_runtime(struct TCCState *s1);
-void pe_guess_outfile(char *objfilename, int output_type);
int pe_output_file(struct TCCState *s1, const char *filename);
/* tccasm.c */
@@ -306,7 +303,7 @@ static inline int toup(int c)
return c;
}
-void *resolve_sym(TCCState *s1, const char *sym, int type);
+void *resolve_sym(TCCState *s1, const char *sym);
/********************************************************/
@@ -412,7 +409,7 @@ void *resolve_sym(TCCState *s1, const char *symbol, int type)
#include <dlfcn.h>
-void *resolve_sym(TCCState *s1, const char *sym, int type)
+void *resolve_sym(TCCState *s1, const char *sym)
{
return dlsym(RTLD_DEFAULT, sym);
}
@@ -1666,15 +1663,15 @@ int tcc_relocate(TCCState *s1, void *ptr)
s1->runtime_added = 1;
s1->nb_errors = 0;
#ifdef TCC_TARGET_PE
- pe_add_runtime(s1);
- relocate_common_syms();
- tcc_add_linker_symbols(s1);
+ pe_output_file(s1, NULL);
#else
tcc_add_runtime(s1);
relocate_common_syms();
tcc_add_linker_symbols(s1);
build_got_entries(s1);
#endif
+ if (s1->nb_errors)
+ return -1;
}
offset = 0, mem = (unsigned long)ptr;
diff --git a/tcc.h b/tcc.h
index 6166dd0..60da4fa 100644
--- a/tcc.h
+++ b/tcc.h
@@ -46,6 +46,7 @@
#include <direct.h> /* getcwd */
#define inline __inline
#define inp next_inp
+#define dlclose FreeLibrary
#endif
#ifndef _WIN32
diff --git a/tccelf.c b/tccelf.c
index 1b0ed13..f0c12c3 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -432,7 +432,6 @@ static void relocate_syms(TCCState *s1, int do_resolve)
ElfW(Sym) *sym, *esym, *sym_end;
int sym_bind, sh_num, sym_index;
const char *name;
- unsigned long addr;
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
@@ -442,12 +441,15 @@ static void relocate_syms(TCCState *s1, int do_resolve)
if (sh_num == SHN_UNDEF) {
name = strtab_section->data + sym->st_name;
if (do_resolve) {
+#ifndef _WIN32
+ unsigned long addr;
name = symtab_section->link->data + sym->st_name;
- addr = (unsigned long)resolve_sym(s1, name, ELFW(ST_TYPE)(sym->st_info));
+ addr = (unsigned long)resolve_sym(s1, name);
if (addr) {
sym->st_value = addr;
goto found;
}
+#endif
} else if (s1->dynsym) {
/* if dynamic symbol exist, then use it */
sym_index = find_elf_sym(s1->dynsym, name);
diff --git a/tccpe.c b/tccpe.c
index 1e3fdb3..a25bad3 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -36,6 +36,10 @@
#define PE_MERGE_DATA
// #define PE_PRINT_SECTIONS
+#if defined _WIN32 && (defined _WIN64) == (defined TCC_TARGET_X86_64)
+#define TCC_IS_NATIVE
+#endif
+
/* ----------------------------------------------------------- */
#ifndef IMAGE_NT_SIGNATURE
/* ----------------------------------------------------------- */
@@ -411,6 +415,7 @@ struct pe_info {
#define PE_DLL 1
#define PE_GUI 2
#define PE_EXE 3
+#define PE_RUN 4
void error_noabort(const char *, ...);
@@ -455,54 +460,11 @@ ST_FN int pe_find_import(TCCState * s1, const char *symbol)
do {
s = n ? get_alt_symbol(buffer, symbol) : symbol;
sym_index = find_elf_sym(s1->dynsymtab_section, s);
- // printf("find %d %s\n", sym_index, s);
+ // printf("find (%d) %d %s\n", n, sym_index, s);
} while (0 == sym_index && ++n < 2);
return sym_index;
}
-#if defined _WIN32 || defined __CYGWIN__
-
-#ifdef __CYGWIN__
-# include <dlfcn.h>
-# define LoadLibrary(s) dlopen(s, RTLD_NOW)
-# define GetProcAddress(h,s) dlsym(h, s)
-#else
-# define dlclose(h) FreeLibrary(h)
-#endif
-
-/* for the -run option: dynamically load symbol from dll */
-void *resolve_sym(struct TCCState *s1, const char *symbol, int type)
-{
- char buffer[100];
- int sym_index, dll_index;
- void *addr, **m;
- DLLReference *dllref;
-
- sym_index = pe_find_import(s1, symbol);
- if (0 == sym_index)
- return NULL;
- dll_index = ((Elf32_Sym *)s1->dynsymtab_section->data + sym_index)->st_value;
- dllref = s1->loaded_dlls[dll_index-1];
- if ( !dllref->handle )
- {
- dllref->handle = LoadLibrary(dllref->name);
- }
- addr = GetProcAddress(dllref->handle, symbol);
- if (NULL == addr)
- addr = GetProcAddress(dllref->handle, get_alt_symbol(buffer, symbol));
-
- if (addr && STT_OBJECT == type) {
- /* need to return a pointer to the address for data objects */
- m = (void**)tcc_malloc(sizeof addr), *m = addr, addr = m;
-#ifdef MEM_DEBUG
- /* yep, we don't free it */
- mem_cur_size -= sizeof (void*);
-#endif
- }
- return addr;
-}
-#endif
-
/*----------------------------------------------------------------------------*/
ST_FN int dynarray_assoc(void **pp, int n, int key)
@@ -729,7 +691,8 @@ ST_FN void pe_build_imports(struct pe_info *pe)
for (i = 0; i < pe->imp_count; ++i) {
struct pe_import_header *hdr;
- int k, n, v;
+ int k, n;
+ DWORD v;
struct pe_import_info *p = pe->imp_info[i];
const char *name = pe->s1->loaded_dlls[p->dll_index-1]->name;
@@ -743,7 +706,7 @@ ST_FN void pe_build_imports(struct pe_info *pe)
for (k = 0, n = p->sym_count; k <= n; ++k) {
if (k < n) {
- DWORD iat_index = p->symbols[k]->iat_index;
+ int iat_index = p->symbols[k]->iat_index;
int sym_index = p->symbols[k]->sym_index;
Elf32_Sym *imp_sym = (Elf32_Sym *)pe->s1->dynsymtab_section->data + sym_index;
Elf32_Sym *org_sym = (Elf32_Sym *)symtab_section->data + iat_index;
@@ -754,7 +717,16 @@ ST_FN void pe_build_imports(struct pe_info *pe)
v = pe->thunk->data_offset + rva_base;
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
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 = (DWORD)GetProcAddress(dllref->handle, name);
+ if (!v)
+ error_noabort("undefined symbol '%s'", name);
+ }
+#endif
} else {
v = 0; /* last entry is zero */
}
@@ -1488,6 +1460,7 @@ ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
tcc_add_library(s1, "gdi32");
}
}
+ pe->type = pe_type;
if (start_symbol) {
addr = (unsigned long)tcc_get_symbol_err(s1, start_symbol);
@@ -1498,16 +1471,7 @@ ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
text_section->sh_num, "main");
}
-
- if (pe) {
- pe->type = pe_type;
- pe->start_addr = addr;
- }
-}
-
-PUB_FN void pe_add_runtime(TCCState *s1)
-{
- pe_add_runtime_ex(s1, NULL);
+ pe->start_addr = addr;
}
PUB_FN int pe_output_file(TCCState * s1, const char *filename)
@@ -1525,7 +1489,10 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename)
tcc_add_linker_symbols(s1);
ret = pe_check_symbols(&pe);
- if (0 == ret) {
+ if (ret)
+ return ret;
+
+ if (filename) {
if (PE_DLL == pe.type) {
pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
pe.imagebase = 0x10000000;
@@ -1546,6 +1513,13 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename)
else
ret = pe_write(&pe);
tcc_free(pe.sec_info);
+ } else {
+#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);
}
#ifdef PE_PRINT_SECTIONS