tccpe: load dll on the fly
This commit is contained in:
parent
9fda4f4248
commit
1df662c1b0
5 changed files with 321 additions and 235 deletions
177
libtcc.c
177
libtcc.c
|
@ -212,9 +212,7 @@ 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 */
|
||||||
int pe_load_def_file(struct TCCState *s1, int fd);
|
int pe_load_file(struct TCCState *s1, const char *filename, int fd);
|
||||||
int pe_test_res_file(void *v, int size);
|
|
||||||
int pe_load_res_file(struct TCCState *s1, int fd);
|
|
||||||
int pe_output_file(struct TCCState *s1, const char *filename);
|
int pe_output_file(struct TCCState *s1, const char *filename);
|
||||||
|
|
||||||
/* tccasm.c */
|
/* tccasm.c */
|
||||||
|
@ -277,6 +275,7 @@ static int tcc_compile(TCCState *s1);
|
||||||
void expect(const char *msg);
|
void expect(const char *msg);
|
||||||
void skip(int c);
|
void skip(int c);
|
||||||
static void test_lvalue(void);
|
static void test_lvalue(void);
|
||||||
|
void *resolve_sym(TCCState *s1, const char *sym);
|
||||||
|
|
||||||
static inline int isid(int c)
|
static inline int isid(int c)
|
||||||
{
|
{
|
||||||
|
@ -303,8 +302,6 @@ static inline int toup(int c)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *resolve_sym(TCCState *s1, const char *sym);
|
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
|
|
||||||
#ifdef TCC_TARGET_I386
|
#ifdef TCC_TARGET_I386
|
||||||
|
@ -352,6 +349,43 @@ static void asm_global_instr(void)
|
||||||
#include "tccpe.c"
|
#include "tccpe.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/********************************************************/
|
||||||
|
#ifdef _WIN32
|
||||||
|
char *normalize_slashes(char *path)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
for (p = path; *p; ++p)
|
||||||
|
if (*p == '\\')
|
||||||
|
*p = '/';
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE tcc_module;
|
||||||
|
|
||||||
|
/* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */
|
||||||
|
void tcc_set_lib_path_w32(TCCState *s)
|
||||||
|
{
|
||||||
|
char path[1024], *p;
|
||||||
|
GetModuleFileNameA(tcc_module, path, sizeof path);
|
||||||
|
p = tcc_basename(normalize_slashes(strlwr(path)));
|
||||||
|
if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
|
||||||
|
p -= 5;
|
||||||
|
else if (p > path)
|
||||||
|
p--;
|
||||||
|
*p = 0;
|
||||||
|
tcc_set_lib_path(s, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LIBTCC_AS_DLL
|
||||||
|
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
if (DLL_PROCESS_ATTACH == dwReason)
|
||||||
|
tcc_module = hDll;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
#ifdef CONFIG_TCC_STATIC
|
#ifdef CONFIG_TCC_STATIC
|
||||||
|
|
||||||
|
@ -393,7 +427,7 @@ static TCCSyms tcc_syms[] = {
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
void *resolve_sym(TCCState *s1, const char *symbol, int type)
|
void *resolve_sym(TCCState *s1, const char *symbol)
|
||||||
{
|
{
|
||||||
TCCSyms *p;
|
TCCSyms *p;
|
||||||
p = tcc_syms;
|
p = tcc_syms;
|
||||||
|
@ -405,8 +439,10 @@ void *resolve_sym(TCCState *s1, const char *symbol, int type)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif !defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
#define dlclose FreeLibrary
|
||||||
|
|
||||||
|
#else
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
void *resolve_sym(TCCState *s1, const char *sym)
|
void *resolve_sym(TCCState *s1, const char *sym)
|
||||||
|
@ -1982,9 +2018,11 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
{
|
{
|
||||||
const char *ext;
|
const char *ext;
|
||||||
ElfW(Ehdr) ehdr;
|
ElfW(Ehdr) ehdr;
|
||||||
int fd, ret;
|
int fd, ret, size;
|
||||||
BufferedFile *saved_file;
|
BufferedFile *saved_file;
|
||||||
|
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
/* find source file type with extension */
|
/* find source file type with extension */
|
||||||
ext = tcc_fileextension(filename);
|
ext = tcc_fileextension(filename);
|
||||||
if (ext[0])
|
if (ext[0])
|
||||||
|
@ -1994,104 +2032,103 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
saved_file = file;
|
saved_file = file;
|
||||||
file = tcc_open(s1, filename);
|
file = tcc_open(s1, filename);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
if (flags & AFF_PRINT_ERROR) {
|
if (flags & AFF_PRINT_ERROR)
|
||||||
error_noabort("file '%s' not found", filename);
|
error_noabort("file '%s' not found", filename);
|
||||||
}
|
goto the_end;
|
||||||
ret = -1;
|
|
||||||
goto fail1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & AFF_PREPROCESS) {
|
if (flags & AFF_PREPROCESS) {
|
||||||
ret = tcc_preprocess(s1);
|
ret = tcc_preprocess(s1);
|
||||||
} else if (!ext[0] || !PATHCMP(ext, "c")) {
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ext[0] || !PATHCMP(ext, "c")) {
|
||||||
/* C file assumed */
|
/* C file assumed */
|
||||||
ret = tcc_compile(s1);
|
ret = tcc_compile(s1);
|
||||||
} else
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
if (!strcmp(ext, "S")) {
|
if (!strcmp(ext, "S")) {
|
||||||
/* preprocessed assembler */
|
/* preprocessed assembler */
|
||||||
ret = tcc_assemble(s1, 1);
|
ret = tcc_assemble(s1, 1);
|
||||||
} else if (!strcmp(ext, "s")) {
|
goto the_end;
|
||||||
/* non preprocessed assembler */
|
|
||||||
ret = tcc_assemble(s1, 0);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (!PATHCMP(ext, "def")) {
|
|
||||||
ret = pe_load_def_file(s1, file->fd);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
fd = file->fd;
|
|
||||||
/* assume executable format: auto guess file type */
|
|
||||||
ret = read(fd, &ehdr, sizeof(ehdr));
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
if (ret <= 0) {
|
|
||||||
error_noabort("could not read header");
|
|
||||||
goto fail;
|
|
||||||
} else if (ret != sizeof(ehdr)) {
|
|
||||||
goto try_load_script;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ehdr.e_ident[0] == ELFMAG0 &&
|
if (!strcmp(ext, "s")) {
|
||||||
|
/* non preprocessed assembler */
|
||||||
|
ret = tcc_assemble(s1, 0);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fd = file->fd;
|
||||||
|
/* assume executable format: auto guess file type */
|
||||||
|
size = read(fd, &ehdr, sizeof(ehdr));
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
if (size <= 0) {
|
||||||
|
error_noabort("could not read header");
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == sizeof(ehdr) &&
|
||||||
|
ehdr.e_ident[0] == ELFMAG0 &&
|
||||||
ehdr.e_ident[1] == ELFMAG1 &&
|
ehdr.e_ident[1] == ELFMAG1 &&
|
||||||
ehdr.e_ident[2] == ELFMAG2 &&
|
ehdr.e_ident[2] == ELFMAG2 &&
|
||||||
ehdr.e_ident[3] == ELFMAG3) {
|
ehdr.e_ident[3] == ELFMAG3) {
|
||||||
file->line_num = 0; /* do not display line number if error */
|
|
||||||
|
/* do not display line number if error */
|
||||||
|
file->line_num = 0;
|
||||||
if (ehdr.e_type == ET_REL) {
|
if (ehdr.e_type == ET_REL) {
|
||||||
ret = tcc_load_object_file(s1, fd, 0);
|
ret = tcc_load_object_file(s1, fd, 0);
|
||||||
} else if (ehdr.e_type == ET_DYN) {
|
goto the_end;
|
||||||
|
|
||||||
|
}
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
if (ehdr.e_type == ET_DYN) {
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
ret = -1;
|
|
||||||
#else
|
|
||||||
void *h;
|
void *h;
|
||||||
h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
|
h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
|
||||||
if (h)
|
if (h)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
else
|
|
||||||
ret = -1;
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
ret = tcc_load_dll(s1, fd, filename,
|
ret = tcc_load_dll(s1, fd, filename,
|
||||||
(flags & AFF_REFERENCED_DLL) != 0);
|
(flags & AFF_REFERENCED_DLL) != 0);
|
||||||
}
|
}
|
||||||
} else {
|
goto the_end;
|
||||||
error_noabort("unrecognized ELF file");
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
} else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
|
#endif
|
||||||
|
error_noabort("unrecognized ELF file");
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
|
||||||
file->line_num = 0; /* do not display line number if error */
|
file->line_num = 0; /* do not display line number if error */
|
||||||
ret = tcc_load_archive(s1, fd);
|
ret = tcc_load_archive(s1, fd);
|
||||||
} else
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_COFF
|
#ifdef TCC_TARGET_COFF
|
||||||
if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
|
if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
|
||||||
ret = tcc_load_coff(s1, fd);
|
ret = tcc_load_coff(s1, fd);
|
||||||
} else
|
goto the_end;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (pe_test_res_file(&ehdr, ret)) {
|
ret = pe_load_file(s1, filename, fd);
|
||||||
ret = pe_load_res_file(s1, fd);
|
#else
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* as GNU ld, consider it is an ld script if not recognized */
|
/* as GNU ld, consider it is an ld script if not recognized */
|
||||||
try_load_script:
|
|
||||||
ret = tcc_load_ldscript(s1);
|
ret = tcc_load_ldscript(s1);
|
||||||
if (ret < 0) {
|
#endif
|
||||||
|
if (ret < 0)
|
||||||
error_noabort("unrecognized file type");
|
error_noabort("unrecognized file type");
|
||||||
goto fail;
|
|
||||||
}
|
the_end:
|
||||||
}
|
if (file)
|
||||||
}
|
|
||||||
the_end:
|
|
||||||
tcc_close(file);
|
tcc_close(file);
|
||||||
fail1:
|
|
||||||
file = saved_file;
|
file = saved_file;
|
||||||
return ret;
|
return ret;
|
||||||
fail:
|
|
||||||
ret = -1;
|
|
||||||
goto the_end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcc_add_file(TCCState *s, const char *filename)
|
int tcc_add_file(TCCState *s, const char *filename)
|
||||||
|
@ -2136,14 +2173,14 @@ int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
/* first we look for the dynamic library if not static linking */
|
/* first we look for the dynamic library if not static linking */
|
||||||
if (!s->static_link) {
|
if (!s->static_link) {
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
snprintf(buf, sizeof(buf), "%s.def", libraryname);
|
if (pe_add_dll(s, libraryname) == 0)
|
||||||
|
return 0;
|
||||||
#else
|
#else
|
||||||
snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
|
snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
|
||||||
#endif
|
|
||||||
if (tcc_add_dll(s, buf, 0) == 0)
|
if (tcc_add_dll(s, buf, 0) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* then we look for the static library */
|
/* then we look for the static library */
|
||||||
for(i = 0; i < s->nb_library_paths; i++) {
|
for(i = 0; i < s->nb_library_paths; i++) {
|
||||||
snprintf(buf, sizeof(buf), "%s/lib%s.a",
|
snprintf(buf, sizeof(buf), "%s/lib%s.a",
|
||||||
|
@ -2225,6 +2262,10 @@ int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
snprintf(buf, sizeof(buf), "%s/lib", s->tcc_lib_path);
|
snprintf(buf, sizeof(buf), "%s/lib", s->tcc_lib_path);
|
||||||
tcc_add_library_path(s, buf);
|
tcc_add_library_path(s, buf);
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (GetSystemDirectory(buf, sizeof buf))
|
||||||
|
tcc_add_library_path(s, buf);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
1
tcc.h
1
tcc.h
|
@ -46,7 +46,6 @@
|
||||||
#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
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define __aligned(n) __declspec(align(n))
|
#define __aligned(n) __declspec(align(n))
|
||||||
#endif
|
#endif
|
||||||
|
|
2
tccelf.c
2
tccelf.c
|
@ -2424,6 +2424,7 @@ static int tcc_load_archive(TCCState *s1, int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
|
/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
|
||||||
is referenced by the user (so it should be added as DT_NEEDED in
|
is referenced by the user (so it should be added as DT_NEEDED in
|
||||||
the generated ELF file) */
|
the generated ELF file) */
|
||||||
|
@ -2740,3 +2741,4 @@ static int tcc_load_ldscript(TCCState *s1)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
143
tccpe.c
143
tccpe.c
|
@ -46,6 +46,19 @@
|
||||||
#define TCC_IS_NATIVE
|
#define TCC_IS_NATIVE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
void dbg_printf (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buffer[4000];
|
||||||
|
va_list arg;
|
||||||
|
int x;
|
||||||
|
va_start(arg, fmt);
|
||||||
|
x = vsprintf (buffer, fmt, arg);
|
||||||
|
strcpy(buffer+x, "\n");
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
#ifndef IMAGE_NT_SIGNATURE
|
#ifndef IMAGE_NT_SIGNATURE
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
|
@ -442,29 +455,12 @@ struct pe_info {
|
||||||
int imp_count;
|
int imp_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#define PE_NUL 0
|
#define PE_NUL 0
|
||||||
#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
|
#define PE_RUN 4
|
||||||
|
|
||||||
void error_noabort(const char *, ...);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
void dbg_printf (const char *fmt, ...)
|
|
||||||
{
|
|
||||||
char buffer[4000];
|
|
||||||
va_list arg;
|
|
||||||
int x;
|
|
||||||
va_start(arg, fmt);
|
|
||||||
x = vsprintf (buffer, fmt, arg);
|
|
||||||
strcpy(buffer+x, "\n");
|
|
||||||
OutputDebugString(buffer);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* --------------------------------------------*/
|
/* --------------------------------------------*/
|
||||||
|
|
||||||
ST_FN const char* get_alt_symbol(char *buffer, const char *symbol)
|
ST_FN const char* get_alt_symbol(char *buffer, const char *symbol)
|
||||||
|
@ -1355,62 +1351,55 @@ ST_FN void pe_print_sections(TCCState *s1, const char *fname)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ST_FN int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||||
|
{
|
||||||
|
fseek(fp, offset, 0);
|
||||||
|
return len == fread(buffer, 1, len, fp);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------
|
/* -------------------------------------------------------------
|
||||||
* This is for compiled windows resources in 'coff' format
|
* This is for compiled windows resources in 'coff' format
|
||||||
* as generated by 'windres.exe -O coff ...'.
|
* as generated by 'windres.exe -O coff ...'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PUB_FN int pe_test_res_file(void *v, int size)
|
ST_FN int pe_load_res(TCCState *s1, FILE *fp)
|
||||||
{
|
|
||||||
struct pe_rsrc_header *p = (struct pe_rsrc_header *)v;
|
|
||||||
return
|
|
||||||
size >= IMAGE_SIZEOF_FILE_HEADER + IMAGE_SIZEOF_SHORT_NAME /* = 28 */
|
|
||||||
&& p->filehdr.Machine == 0x014C
|
|
||||||
&& 1 == p->filehdr.NumberOfSections
|
|
||||||
&& 0 == strcmp(p->sectionhdr.Name, ".rsrc")
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FN int read_n(int fd, void *ptr, unsigned size)
|
|
||||||
{
|
|
||||||
return size == read(fd, ptr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
PUB_FN int pe_load_res_file(TCCState *s1, int fd)
|
|
||||||
{
|
{
|
||||||
struct pe_rsrc_header hdr;
|
struct pe_rsrc_header hdr;
|
||||||
Section *rsrc_section;
|
Section *rsrc_section;
|
||||||
int i, ret = -1;
|
int i, ret = -1;
|
||||||
BYTE *ptr;
|
BYTE *ptr;
|
||||||
|
unsigned offs;
|
||||||
|
|
||||||
lseek (fd, 0, SEEK_SET);
|
if (!read_mem(fp, 0, &hdr, sizeof hdr))
|
||||||
if (!read_n(fd, &hdr, sizeof hdr))
|
|
||||||
goto quit;
|
goto quit;
|
||||||
if (!pe_test_res_file(&hdr, sizeof hdr))
|
|
||||||
|
if (hdr.filehdr.Machine != 0x014C
|
||||||
|
|| hdr.filehdr.NumberOfSections != 1
|
||||||
|
|| strcmp(hdr.sectionhdr.Name, ".rsrc") != 0)
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
|
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
|
||||||
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
|
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
|
||||||
lseek (fd, hdr.sectionhdr.PointerToRawData, SEEK_SET);
|
offs = hdr.sectionhdr.PointerToRawData;
|
||||||
if (!read_n(fd, ptr, hdr.sectionhdr.SizeOfRawData))
|
if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData))
|
||||||
goto quit;
|
goto quit;
|
||||||
|
offs = hdr.sectionhdr.PointerToRelocations;
|
||||||
lseek (fd, hdr.sectionhdr.PointerToRelocations, SEEK_SET);
|
|
||||||
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
|
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
|
||||||
{
|
{
|
||||||
struct pe_rsrc_reloc rel;
|
struct pe_rsrc_reloc rel;
|
||||||
if (!read_n(fd, &rel, sizeof rel))
|
if (!read_mem(fp, offs, &rel, sizeof rel))
|
||||||
goto quit;
|
goto quit;
|
||||||
// printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
|
// printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
|
||||||
if (rel.type != 7) /* DIR32NB */
|
if (rel.type != 7) /* DIR32NB */
|
||||||
goto quit;
|
goto quit;
|
||||||
put_elf_reloc(symtab_section, rsrc_section,
|
put_elf_reloc(symtab_section, rsrc_section,
|
||||||
rel.offset, R_XXX_RELATIVE, 0);
|
rel.offset, R_XXX_RELATIVE, 0);
|
||||||
|
offs += sizeof rel;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
quit:
|
quit:
|
||||||
if (ret)
|
|
||||||
error_noabort("unrecognized resource file format");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1439,15 +1428,11 @@ ST_FN char *get_line(char *line, int size, FILE *fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
PUB_FN int pe_load_def_file(TCCState *s1, int fd)
|
ST_FN int pe_load_def(TCCState *s1, FILE *fp)
|
||||||
{
|
{
|
||||||
DLLReference *dllref;
|
DLLReference *dllref;
|
||||||
int state = 0, ret = -1;
|
int state = 0, ret = -1;
|
||||||
char line[400], dllname[80], *p;
|
char line[400], dllname[80], *p;
|
||||||
FILE *fp = fdopen(dup(fd), "rb");
|
|
||||||
|
|
||||||
if (NULL == fp)
|
|
||||||
goto quit;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
p = get_line(line, sizeof line, fp);
|
p = get_line(line, sizeof line, fp);
|
||||||
|
@ -1485,13 +1470,65 @@ PUB_FN int pe_load_def_file(TCCState *s1, int fd)
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
quit:
|
quit:
|
||||||
if (fp)
|
|
||||||
fclose(fp);
|
|
||||||
if (ret)
|
|
||||||
error_noabort("unrecognized export definition file format");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
||||||
|
#include "win32/tools/tiny_impdef.c"
|
||||||
|
|
||||||
|
ST_FN int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
char *p, *q;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
PUB_FN int pe_load_file(struct TCCState *s1, const char *filename, int fd)
|
||||||
|
{
|
||||||
|
FILE *fp = fdopen(dup(fd), "rb");
|
||||||
|
int ret = -1;
|
||||||
|
char buf[10];
|
||||||
|
if (fp) {
|
||||||
|
if (0 == strcmp(tcc_fileextension(filename), ".def"))
|
||||||
|
ret = pe_load_def(s1, fp);
|
||||||
|
else if (pe_load_res(s1, fp) == 0)
|
||||||
|
ret = 0;
|
||||||
|
else if (read_mem(fp, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
|
||||||
|
ret = pe_load_dll(s1, filename, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pe_add_dll(struct TCCState *s, const char *libraryname)
|
||||||
|
{
|
||||||
|
char buf[MAX_PATH];
|
||||||
|
snprintf(buf, sizeof(buf), "%s.def", libraryname);
|
||||||
|
if (tcc_add_dll(s, buf, 0) == 0)
|
||||||
|
return 0;
|
||||||
|
snprintf(buf, sizeof(buf), "%s.dll", libraryname);
|
||||||
|
if (tcc_add_dll(s, buf, 0) == 0)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
#define PE_STDSYM(n,s) n
|
#define PE_STDSYM(n,s) n
|
||||||
|
|
|
@ -20,100 +20,19 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "../../config.h"
|
#include "../../config.h"
|
||||||
|
|
||||||
int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
char *get_export_names(FILE *fp);
|
||||||
{
|
#define tcc_free free
|
||||||
fseek(fp, offset, 0);
|
#define tcc_realloc realloc
|
||||||
return len == fread(buffer, 1, len, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *get_export_names(FILE *fp)
|
|
||||||
{
|
|
||||||
int l, i, n, n0;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
IMAGE_SECTION_HEADER ish;
|
|
||||||
IMAGE_EXPORT_DIRECTORY ied;
|
|
||||||
IMAGE_DOS_HEADER dh;
|
|
||||||
IMAGE_FILE_HEADER ih;
|
|
||||||
DWORD sig, ref, addr, ptr, namep;
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
IMAGE_OPTIONAL_HEADER64 oh;
|
|
||||||
const int MACHINE = 0x8664;
|
|
||||||
#else
|
|
||||||
IMAGE_OPTIONAL_HEADER32 oh;
|
|
||||||
const int MACHINE = 0x014C;
|
|
||||||
#endif
|
|
||||||
int pef_hdroffset, opt_hdroffset, sec_hdroffset;
|
|
||||||
|
|
||||||
n = n0 = 0;
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
if (!read_mem(fp, 0, &dh, sizeof dh))
|
|
||||||
goto the_end;
|
|
||||||
if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig))
|
|
||||||
goto the_end;
|
|
||||||
if (sig != 0x00004550)
|
|
||||||
goto the_end;
|
|
||||||
pef_hdroffset = dh.e_lfanew + sizeof sig;
|
|
||||||
if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih))
|
|
||||||
goto the_end;
|
|
||||||
if (MACHINE != ih.Machine)
|
|
||||||
goto the_end;
|
|
||||||
opt_hdroffset = pef_hdroffset + sizeof ih;
|
|
||||||
sec_hdroffset = opt_hdroffset + sizeof oh;
|
|
||||||
if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh))
|
|
||||||
goto the_end;
|
|
||||||
|
|
||||||
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
|
|
||||||
goto the_end;
|
|
||||||
|
|
||||||
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
|
||||||
//printf("addr: %08x\n", addr);
|
|
||||||
for (i = 0; i < ih.NumberOfSections; ++i) {
|
|
||||||
if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
|
|
||||||
goto the_end;
|
|
||||||
//printf("vaddr: %08x\n", ish.VirtualAddress);
|
|
||||||
if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
goto the_end;
|
|
||||||
|
|
||||||
found:
|
|
||||||
ref = ish.VirtualAddress - ish.PointerToRawData;
|
|
||||||
if (!read_mem(fp, addr - ref, &ied, sizeof ied))
|
|
||||||
goto the_end;
|
|
||||||
|
|
||||||
namep = ied.AddressOfNames - ref;
|
|
||||||
for (i = 0; i < ied.NumberOfNames; ++i) {
|
|
||||||
if (!read_mem(fp, namep, &ptr, sizeof ptr))
|
|
||||||
goto the_end;
|
|
||||||
namep += sizeof ptr;
|
|
||||||
for (l = 0;;) {
|
|
||||||
if (n+1 >= n0)
|
|
||||||
p = realloc(p, n0 = n0 ? n0 * 2 : 256);
|
|
||||||
if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) {
|
|
||||||
free(p), p = NULL;
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
if (p[n++] == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p)
|
|
||||||
p[n] = 0;
|
|
||||||
the_end:
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
|
||||||
/* extract the basename of a file */
|
/* extract the basename of a file */
|
||||||
|
|
||||||
static char *file_basename(const char *name)
|
static char *file_basename(const char *name)
|
||||||
{
|
{
|
||||||
const char *p = strchr(name, 0);
|
const char *p = strchr(name, 0);
|
||||||
|
@ -125,8 +44,6 @@ static char *file_basename(const char *name)
|
||||||
return (char*)p;
|
return (char*)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ret, v, i;
|
int ret, v, i;
|
||||||
|
@ -232,3 +149,93 @@ the_end:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||||
|
{
|
||||||
|
fseek(fp, offset, 0);
|
||||||
|
return len == fread(buffer, 1, len, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *get_export_names(FILE *fp)
|
||||||
|
{
|
||||||
|
int l, i, n, n0;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
IMAGE_SECTION_HEADER ish;
|
||||||
|
IMAGE_EXPORT_DIRECTORY ied;
|
||||||
|
IMAGE_DOS_HEADER dh;
|
||||||
|
IMAGE_FILE_HEADER ih;
|
||||||
|
DWORD sig, ref, addr, ptr, namep;
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
IMAGE_OPTIONAL_HEADER64 oh;
|
||||||
|
const int MACHINE = 0x8664;
|
||||||
|
#else
|
||||||
|
IMAGE_OPTIONAL_HEADER32 oh;
|
||||||
|
const int MACHINE = 0x014C;
|
||||||
|
#endif
|
||||||
|
int pef_hdroffset, opt_hdroffset, sec_hdroffset;
|
||||||
|
|
||||||
|
n = n0 = 0;
|
||||||
|
p = NULL;
|
||||||
|
|
||||||
|
if (!read_mem(fp, 0, &dh, sizeof dh))
|
||||||
|
goto the_end;
|
||||||
|
if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig))
|
||||||
|
goto the_end;
|
||||||
|
if (sig != 0x00004550)
|
||||||
|
goto the_end;
|
||||||
|
pef_hdroffset = dh.e_lfanew + sizeof sig;
|
||||||
|
if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih))
|
||||||
|
goto the_end;
|
||||||
|
if (MACHINE != ih.Machine)
|
||||||
|
goto the_end;
|
||||||
|
opt_hdroffset = pef_hdroffset + sizeof ih;
|
||||||
|
sec_hdroffset = opt_hdroffset + sizeof oh;
|
||||||
|
if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh))
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
|
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
|
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||||
|
//printf("addr: %08x\n", addr);
|
||||||
|
for (i = 0; i < ih.NumberOfSections; ++i) {
|
||||||
|
if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
|
||||||
|
goto the_end;
|
||||||
|
//printf("vaddr: %08x\n", ish.VirtualAddress);
|
||||||
|
if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
|
found:
|
||||||
|
ref = ish.VirtualAddress - ish.PointerToRawData;
|
||||||
|
if (!read_mem(fp, addr - ref, &ied, sizeof ied))
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
|
namep = ied.AddressOfNames - ref;
|
||||||
|
for (i = 0; i < ied.NumberOfNames; ++i) {
|
||||||
|
if (!read_mem(fp, namep, &ptr, sizeof ptr))
|
||||||
|
goto the_end;
|
||||||
|
namep += sizeof ptr;
|
||||||
|
for (l = 0;;) {
|
||||||
|
if (n+1 >= n0)
|
||||||
|
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
|
||||||
|
if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) {
|
||||||
|
tcc_free(p), p = NULL;
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
if (p[n++] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p)
|
||||||
|
p[n] = 0;
|
||||||
|
the_end:
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
|
Loading…
Reference in a new issue