aboutsummaryrefslogtreecommitdiff
path: root/tccpe.c
diff options
context:
space:
mode:
Diffstat (limited to 'tccpe.c')
-rw-r--r--tccpe.c122
1 files changed, 109 insertions, 13 deletions
diff --git a/tccpe.c b/tccpe.c
index cf2e475..50690df 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -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;
}