aboutsummaryrefslogtreecommitdiff
path: root/tccpe.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 /tccpe.c
parent9fda4f4248f24ee3e9feb9204bd1ef035c4859da (diff)
downloadtinycc-1df662c1b094d250db0501cf31db83dc5f9060e4.tar.gz
tinycc-1df662c1b094d250db0501cf31db83dc5f9060e4.tar.bz2
tccpe: load dll on the fly
Diffstat (limited to 'tccpe.c')
-rw-r--r--tccpe.c141
1 files changed, 89 insertions, 52 deletions
diff --git a/tccpe.c b/tccpe.c
index 89ff3bd..fe87919 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -46,6 +46,19 @@
#define TCC_IS_NATIVE
#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
/* ----------------------------------------------------------- */
@@ -442,29 +455,12 @@ struct pe_info {
int imp_count;
};
-/* ------------------------------------------------------------- */
-
#define PE_NUL 0
#define PE_DLL 1
#define PE_GUI 2
#define PE_EXE 3
#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)
@@ -1355,62 +1351,55 @@ ST_FN void pe_print_sections(TCCState *s1, const char *fname)
}
#endif
-/* -------------------------------------------------------------
- * This is for compiled windows resources in 'coff' format
- * as generated by 'windres.exe -O coff ...'.
- */
+/* ------------------------------------------------------------- */
-PUB_FN int pe_test_res_file(void *v, int size)
+ST_FN int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
{
- 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")
- ;
+ fseek(fp, offset, 0);
+ return len == fread(buffer, 1, len, fp);
}
-ST_FN int read_n(int fd, void *ptr, unsigned size)
-{
- return size == read(fd, ptr, size);
-}
+/* -------------------------------------------------------------
+ * This is for compiled windows resources in 'coff' format
+ * as generated by 'windres.exe -O coff ...'.
+ */
-PUB_FN int pe_load_res_file(TCCState *s1, int fd)
+ST_FN int pe_load_res(TCCState *s1, FILE *fp)
{
struct pe_rsrc_header hdr;
Section *rsrc_section;
int i, ret = -1;
BYTE *ptr;
+ unsigned offs;
- lseek (fd, 0, SEEK_SET);
- if (!read_n(fd, &hdr, sizeof hdr))
+ if (!read_mem(fp, 0, &hdr, sizeof hdr))
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;
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
- lseek (fd, hdr.sectionhdr.PointerToRawData, SEEK_SET);
- if (!read_n(fd, ptr, hdr.sectionhdr.SizeOfRawData))
+ offs = hdr.sectionhdr.PointerToRawData;
+ if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData))
goto quit;
-
- lseek (fd, hdr.sectionhdr.PointerToRelocations, SEEK_SET);
+ offs = hdr.sectionhdr.PointerToRelocations;
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
{
struct pe_rsrc_reloc rel;
- if (!read_n(fd, &rel, sizeof rel))
+ if (!read_mem(fp, offs, &rel, sizeof rel))
goto quit;
// printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
if (rel.type != 7) /* DIR32NB */
goto quit;
put_elf_reloc(symtab_section, rsrc_section,
rel.offset, R_XXX_RELATIVE, 0);
+ offs += sizeof rel;
}
ret = 0;
quit:
- if (ret)
- error_noabort("unrecognized resource file format");
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;
int state = 0, ret = -1;
char line[400], dllname[80], *p;
- FILE *fp = fdopen(dup(fd), "rb");
-
- if (NULL == fp)
- goto quit;
for (;;) {
p = get_line(line, sizeof line, fp);
@@ -1485,13 +1470,65 @@ PUB_FN int pe_load_def_file(TCCState *s1, int fd)
}
ret = 0;
quit:
- if (fp)
+ 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);
- if (ret)
- error_noabort("unrecognized export definition file format");
+ }
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
#define PE_STDSYM(n,s) n