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
This commit is contained in:
parent
bed17847bd
commit
370cdeb628
4 changed files with 42 additions and 68 deletions
13
libtcc.c
13
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);
|
int tcc_output_coff(TCCState *s1, FILE *f);
|
||||||
|
|
||||||
/* tccpe.c */
|
/* tccpe.c */
|
||||||
void *resolve_sym(TCCState *s1, const char *sym, int type);
|
|
||||||
int pe_load_def_file(struct TCCState *s1, int fd);
|
int pe_load_def_file(struct TCCState *s1, int fd);
|
||||||
int pe_test_res_file(void *v, int size);
|
int pe_test_res_file(void *v, int size);
|
||||||
int pe_load_res_file(struct TCCState *s1, int fd);
|
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);
|
int pe_output_file(struct TCCState *s1, const char *filename);
|
||||||
|
|
||||||
/* tccasm.c */
|
/* tccasm.c */
|
||||||
|
@ -306,7 +303,7 @@ static inline int toup(int c)
|
||||||
return 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>
|
#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);
|
return dlsym(RTLD_DEFAULT, sym);
|
||||||
}
|
}
|
||||||
|
@ -1666,15 +1663,15 @@ int tcc_relocate(TCCState *s1, void *ptr)
|
||||||
s1->runtime_added = 1;
|
s1->runtime_added = 1;
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
pe_add_runtime(s1);
|
pe_output_file(s1, NULL);
|
||||||
relocate_common_syms();
|
|
||||||
tcc_add_linker_symbols(s1);
|
|
||||||
#else
|
#else
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
relocate_common_syms();
|
relocate_common_syms();
|
||||||
tcc_add_linker_symbols(s1);
|
tcc_add_linker_symbols(s1);
|
||||||
build_got_entries(s1);
|
build_got_entries(s1);
|
||||||
#endif
|
#endif
|
||||||
|
if (s1->nb_errors)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = 0, mem = (unsigned long)ptr;
|
offset = 0, mem = (unsigned long)ptr;
|
||||||
|
|
1
tcc.h
1
tcc.h
|
@ -46,6 +46,7 @@
|
||||||
#include <direct.h> /* getcwd */
|
#include <direct.h> /* getcwd */
|
||||||
#define inline __inline
|
#define inline __inline
|
||||||
#define inp next_inp
|
#define inp next_inp
|
||||||
|
#define dlclose FreeLibrary
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
6
tccelf.c
6
tccelf.c
|
@ -432,7 +432,6 @@ static void relocate_syms(TCCState *s1, int do_resolve)
|
||||||
ElfW(Sym) *sym, *esym, *sym_end;
|
ElfW(Sym) *sym, *esym, *sym_end;
|
||||||
int sym_bind, sh_num, sym_index;
|
int sym_bind, sh_num, sym_index;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned long addr;
|
|
||||||
|
|
||||||
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
||||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
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) {
|
if (sh_num == SHN_UNDEF) {
|
||||||
name = strtab_section->data + sym->st_name;
|
name = strtab_section->data + sym->st_name;
|
||||||
if (do_resolve) {
|
if (do_resolve) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
unsigned long addr;
|
||||||
name = symtab_section->link->data + sym->st_name;
|
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) {
|
if (addr) {
|
||||||
sym->st_value = addr;
|
sym->st_value = addr;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} else if (s1->dynsym) {
|
} else if (s1->dynsym) {
|
||||||
/* if dynamic symbol exist, then use it */
|
/* if dynamic symbol exist, then use it */
|
||||||
sym_index = find_elf_sym(s1->dynsym, name);
|
sym_index = find_elf_sym(s1->dynsym, name);
|
||||||
|
|
88
tccpe.c
88
tccpe.c
|
@ -36,6 +36,10 @@
|
||||||
#define PE_MERGE_DATA
|
#define PE_MERGE_DATA
|
||||||
// #define PE_PRINT_SECTIONS
|
// #define PE_PRINT_SECTIONS
|
||||||
|
|
||||||
|
#if defined _WIN32 && (defined _WIN64) == (defined TCC_TARGET_X86_64)
|
||||||
|
#define TCC_IS_NATIVE
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
#ifndef IMAGE_NT_SIGNATURE
|
#ifndef IMAGE_NT_SIGNATURE
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
|
@ -411,6 +415,7 @@ struct pe_info {
|
||||||
#define PE_DLL 1
|
#define PE_DLL 1
|
||||||
#define PE_GUI 2
|
#define PE_GUI 2
|
||||||
#define PE_EXE 3
|
#define PE_EXE 3
|
||||||
|
#define PE_RUN 4
|
||||||
|
|
||||||
void error_noabort(const char *, ...);
|
void error_noabort(const char *, ...);
|
||||||
|
|
||||||
|
@ -455,54 +460,11 @@ ST_FN int pe_find_import(TCCState * s1, const char *symbol)
|
||||||
do {
|
do {
|
||||||
s = n ? get_alt_symbol(buffer, symbol) : symbol;
|
s = n ? get_alt_symbol(buffer, symbol) : symbol;
|
||||||
sym_index = find_elf_sym(s1->dynsymtab_section, s);
|
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);
|
} while (0 == sym_index && ++n < 2);
|
||||||
return sym_index;
|
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)
|
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) {
|
for (i = 0; i < pe->imp_count; ++i) {
|
||||||
struct pe_import_header *hdr;
|
struct pe_import_header *hdr;
|
||||||
int k, n, v;
|
int k, n;
|
||||||
|
DWORD 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 = 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) {
|
for (k = 0, n = p->sym_count; k <= n; ++k) {
|
||||||
if (k < n) {
|
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;
|
int sym_index = p->symbols[k]->sym_index;
|
||||||
Elf32_Sym *imp_sym = (Elf32_Sym *)pe->s1->dynsymtab_section->data + 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;
|
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;
|
v = pe->thunk->data_offset + rva_base;
|
||||||
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
|
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
|
||||||
put_elf_str(pe->thunk, name);
|
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 {
|
} else {
|
||||||
v = 0; /* last entry is zero */
|
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");
|
tcc_add_library(s1, "gdi32");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pe->type = pe_type;
|
||||||
|
|
||||||
if (start_symbol) {
|
if (start_symbol) {
|
||||||
addr = (unsigned long)tcc_get_symbol_err(s1, start_symbol);
|
addr = (unsigned long)tcc_get_symbol_err(s1, start_symbol);
|
||||||
|
@ -1498,17 +1471,8 @@ ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
|
||||||
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
|
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
|
||||||
text_section->sh_num, "main");
|
text_section->sh_num, "main");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pe) {
|
|
||||||
pe->type = pe_type;
|
|
||||||
pe->start_addr = addr;
|
pe->start_addr = addr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PUB_FN void pe_add_runtime(TCCState *s1)
|
|
||||||
{
|
|
||||||
pe_add_runtime_ex(s1, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
PUB_FN int pe_output_file(TCCState * s1, const char *filename)
|
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);
|
tcc_add_linker_symbols(s1);
|
||||||
|
|
||||||
ret = pe_check_symbols(&pe);
|
ret = pe_check_symbols(&pe);
|
||||||
if (0 == ret) {
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (filename) {
|
||||||
if (PE_DLL == pe.type) {
|
if (PE_DLL == pe.type) {
|
||||||
pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
|
pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
|
||||||
pe.imagebase = 0x10000000;
|
pe.imagebase = 0x10000000;
|
||||||
|
@ -1546,6 +1513,13 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename)
|
||||||
else
|
else
|
||||||
ret = pe_write(&pe);
|
ret = pe_write(&pe);
|
||||||
tcc_free(pe.sec_info);
|
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
|
#ifdef PE_PRINT_SECTIONS
|
||||||
|
|
Loading…
Reference in a new issue