aboutsummaryrefslogtreecommitdiff
path: root/libtcc.c
diff options
context:
space:
mode:
authorgrischka <grischka>2009-07-18 22:07:25 +0200
committergrischka <grischka>2009-07-18 22:07:25 +0200
commit1df662c1b094d250db0501cf31db83dc5f9060e4 (patch)
tree61de457b79e72b5ef5eb5f0b918935e572f49dbc /libtcc.c
parent9fda4f4248f24ee3e9feb9204bd1ef035c4859da (diff)
downloadtinycc-1df662c1b094d250db0501cf31db83dc5f9060e4.tar.gz
tinycc-1df662c1b094d250db0501cf31db83dc5f9060e4.tar.bz2
tccpe: load dll on the fly
Diffstat (limited to 'libtcc.c')
-rw-r--r--libtcc.c213
1 files changed, 127 insertions, 86 deletions
diff --git a/libtcc.c b/libtcc.c
index bfa6839..3494ee2 100644
--- a/libtcc.c
+++ b/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);
/* tccpe.c */
-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);
+int pe_load_file(struct TCCState *s1, const char *filename, int fd);
int pe_output_file(struct TCCState *s1, const char *filename);
/* tccasm.c */
@@ -277,6 +275,7 @@ static int tcc_compile(TCCState *s1);
void expect(const char *msg);
void skip(int c);
static void test_lvalue(void);
+void *resolve_sym(TCCState *s1, const char *sym);
static inline int isid(int c)
{
@@ -303,8 +302,6 @@ static inline int toup(int c)
return c;
}
-void *resolve_sym(TCCState *s1, const char *sym);
-
/********************************************************/
#ifdef TCC_TARGET_I386
@@ -353,6 +350,43 @@ static void asm_global_instr(void)
#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
#define RTLD_LAZY 0x001
@@ -393,7 +427,7 @@ static TCCSyms tcc_syms[] = {
{ NULL, NULL },
};
-void *resolve_sym(TCCState *s1, const char *symbol, int type)
+void *resolve_sym(TCCState *s1, const char *symbol)
{
TCCSyms *p;
p = tcc_syms;
@@ -405,8 +439,10 @@ void *resolve_sym(TCCState *s1, const char *symbol, int type)
return NULL;
}
-#elif !defined(_WIN32)
+#elif defined(_WIN32)
+#define dlclose FreeLibrary
+#else
#include <dlfcn.h>
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;
ElfW(Ehdr) ehdr;
- int fd, ret;
+ int fd, ret, size;
BufferedFile *saved_file;
+ ret = -1;
+
/* find source file type with extension */
ext = tcc_fileextension(filename);
if (ext[0])
@@ -1994,104 +2032,103 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
saved_file = file;
file = tcc_open(s1, filename);
if (!file) {
- if (flags & AFF_PRINT_ERROR) {
+ if (flags & AFF_PRINT_ERROR)
error_noabort("file '%s' not found", filename);
- }
- ret = -1;
- goto fail1;
+ goto the_end;
}
if (flags & AFF_PREPROCESS) {
ret = tcc_preprocess(s1);
- } else if (!ext[0] || !PATHCMP(ext, "c")) {
+ goto the_end;
+ }
+
+ if (!ext[0] || !PATHCMP(ext, "c")) {
/* C file assumed */
ret = tcc_compile(s1);
- } else
+ goto the_end;
+ }
+
#ifdef CONFIG_TCC_ASM
if (!strcmp(ext, "S")) {
/* preprocessed assembler */
ret = tcc_assemble(s1, 1);
- } else if (!strcmp(ext, "s")) {
+ goto the_end;
+ }
+
+ if (!strcmp(ext, "s")) {
/* 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
+ goto the_end;
+ }
#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 &&
- ehdr.e_ident[1] == ELFMAG1 &&
- ehdr.e_ident[2] == ELFMAG2 &&
- ehdr.e_ident[3] == ELFMAG3) {
- file->line_num = 0; /* do not display line number if error */
- if (ehdr.e_type == ET_REL) {
- ret = tcc_load_object_file(s1, fd, 0);
- } else if (ehdr.e_type == ET_DYN) {
- if (s1->output_type == TCC_OUTPUT_MEMORY) {
-#ifdef TCC_TARGET_PE
- ret = -1;
-#else
- void *h;
- h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
- if (h)
- ret = 0;
- else
- ret = -1;
-#endif
- } else {
- ret = tcc_load_dll(s1, fd, filename,
- (flags & AFF_REFERENCED_DLL) != 0);
- }
+ 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[2] == ELFMAG2 &&
+ ehdr.e_ident[3] == ELFMAG3) {
+
+ /* do not display line number if error */
+ file->line_num = 0;
+ if (ehdr.e_type == ET_REL) {
+ ret = tcc_load_object_file(s1, fd, 0);
+ goto the_end;
+
+ }
+#ifndef TCC_TARGET_PE
+ if (ehdr.e_type == ET_DYN) {
+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
+ void *h;
+ h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
+ if (h)
+ ret = 0;
} else {
- error_noabort("unrecognized ELF file");
- goto fail;
+ ret = tcc_load_dll(s1, fd, filename,
+ (flags & AFF_REFERENCED_DLL) != 0);
}
- } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
- file->line_num = 0; /* do not display line number if error */
- ret = tcc_load_archive(s1, fd);
- } else
+ goto the_end;
+ }
+#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 */
+ ret = tcc_load_archive(s1, fd);
+ goto the_end;
+ }
+
#ifdef TCC_TARGET_COFF
- if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
- ret = tcc_load_coff(s1, fd);
- } else
+ if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
+ ret = tcc_load_coff(s1, fd);
+ goto the_end;
+ }
#endif
+
#ifdef TCC_TARGET_PE
- if (pe_test_res_file(&ehdr, ret)) {
- ret = pe_load_res_file(s1, fd);
- } else
+ ret = pe_load_file(s1, filename, fd);
+#else
+ /* as GNU ld, consider it is an ld script if not recognized */
+ ret = tcc_load_ldscript(s1);
#endif
- {
- /* as GNU ld, consider it is an ld script if not recognized */
- try_load_script:
- ret = tcc_load_ldscript(s1);
- if (ret < 0) {
- error_noabort("unrecognized file type");
- goto fail;
- }
- }
- }
- the_end:
- tcc_close(file);
- fail1:
+ if (ret < 0)
+ error_noabort("unrecognized file type");
+
+the_end:
+ if (file)
+ tcc_close(file);
file = saved_file;
return ret;
- fail:
- ret = -1;
- goto the_end;
}
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 */
if (!s->static_link) {
#ifdef TCC_TARGET_PE
- snprintf(buf, sizeof(buf), "%s.def", libraryname);
+ if (pe_add_dll(s, libraryname) == 0)
+ return 0;
#else
snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
-#endif
if (tcc_add_dll(s, buf, 0) == 0)
return 0;
+#endif
}
-
/* then we look for the static library */
for(i = 0; i < s->nb_library_paths; i++) {
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
snprintf(buf, sizeof(buf), "%s/lib", s->tcc_lib_path);
tcc_add_library_path(s, buf);
+#ifdef _WIN32
+ if (GetSystemDirectory(buf, sizeof buf))
+ tcc_add_library_path(s, buf);
+#endif
#endif
return 0;