diff options
Diffstat (limited to 'tccpe.c')
| -rw-r--r-- | tccpe.c | 122 |
1 files changed, 109 insertions, 13 deletions
@@ -962,7 +962,7 @@ static void pe_build_exports(struct pe_info *pe) } else { fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); if (pe->s1->verbose) - printf("<- %s (%d symbols)\n", buf, sym_count); + printf("<- %s (%d symbol%s)\n", buf, sym_count, "s" + (sym_count < 2)); } #endif @@ -1543,6 +1543,102 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) return len == read(fd, buffer, len); } +/* ------------------------------------------------------------- */ + +PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) +{ + int l, i, n, n0, ret; + char *p; + int fd; + + 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; +#else + IMAGE_OPTIONAL_HEADER32 oh; +#endif + int pef_hdroffset, opt_hdroffset, sec_hdroffset; + + n = n0 = 0; + p = NULL; + ret = -1; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + goto the_end_1; + ret = 1; + + if (!read_mem(fd, 0, &dh, sizeof dh)) + goto the_end; + if (!read_mem(fd, 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(fd, pef_hdroffset, &ih, sizeof ih)) + goto the_end; + if (IMAGE_FILE_MACHINE != ih.Machine) { + if (ih.Machine == 0x014C) + ret = 32; + else if (ih.Machine == 0x8664) + ret = 64; + goto the_end; + } + opt_hdroffset = pef_hdroffset + sizeof ih; + sec_hdroffset = opt_hdroffset + sizeof oh; + if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) + goto the_end; + + if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) + goto the_end_0; + + addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + //printf("addr: %08x\n", addr); + for (i = 0; i < ih.NumberOfSections; ++i) { + if (!read_mem(fd, 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_0; + +found: + ref = ish.VirtualAddress - ish.PointerToRawData; + if (!read_mem(fd, addr - ref, &ied, sizeof ied)) + goto the_end; + + namep = ied.AddressOfNames - ref; + for (i = 0; i < ied.NumberOfNames; ++i) { + if (!read_mem(fd, 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(fd, ptr - ref + l++, p + n, 1)) { + tcc_free(p), p = NULL; + goto the_end; + } + if (p[n++] == 0) + break; + } + } + if (p) + p[n] = 0; +the_end_0: + ret = 0; +the_end: + close(fd); +the_end_1: + *pp = p; + return ret; +} + /* ------------------------------------------------------------- * This is for compiled windows resources in 'coff' format * as generated by 'windres.exe -O coff ...'. @@ -1660,20 +1756,20 @@ quit: } /* ------------------------------------------------------------- */ -#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY -#include "win32/tools/tiny_impdef.c" - -static int pe_load_dll(TCCState *s1, const char *dllname, int fd) +static int pe_load_dll(TCCState *s1, const char *filename) { char *p, *q; - int index; - p = get_export_names(fd); - if (!p) + int index, ret; + + ret = tcc_get_dllexports(filename, &p); + if (ret) { return -1; - index = add_dllref(s1, dllname); - for (q = p; *q; q += 1 + strlen(q)) - pe_putimport(s1, index, q, 0); - tcc_free(p); + } else if (p) { + index = add_dllref(s1, tcc_basename(filename)); + for (q = p; *q; q += 1 + strlen(q)) + pe_putimport(s1, index, q, 0); + tcc_free(p); + } return 0; } @@ -1687,7 +1783,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd) else if (pe_load_res(s1, fd) == 0) ret = 0; else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4)) - ret = pe_load_dll(s1, tcc_basename(filename), fd); + ret = pe_load_dll(s1, filename); return ret; } |
