diff options
| author | grischka <grischka> | 2009-07-18 22:07:25 +0200 |
|---|---|---|
| committer | grischka <grischka> | 2009-07-18 22:07:25 +0200 |
| commit | 1df662c1b094d250db0501cf31db83dc5f9060e4 (patch) | |
| tree | 61de457b79e72b5ef5eb5f0b918935e572f49dbc /tccpe.c | |
| parent | 9fda4f4248f24ee3e9feb9204bd1ef035c4859da (diff) | |
| download | tinycc-1df662c1b094d250db0501cf31db83dc5f9060e4.tar.gz tinycc-1df662c1b094d250db0501cf31db83dc5f9060e4.tar.bz2 | |
tccpe: load dll on the fly
Diffstat (limited to 'tccpe.c')
| -rw-r--r-- | tccpe.c | 141 |
1 files changed, 89 insertions, 52 deletions
@@ -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 |
