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 -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 /* 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 -# 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