From 1df662c1b094d250db0501cf31db83dc5f9060e4 Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 18 Jul 2009 22:07:25 +0200 Subject: [PATCH] tccpe: load dll on the fly --- libtcc.c | 213 +++++++++++++++++++++++++++------------------- tcc.h | 1 - tccelf.c | 2 + tccpe.c | 141 +++++++++++++++++++----------- win32/tools/tiny_impdef.c | 183 ++++++++++++++++++++------------------- 5 files changed, 313 insertions(+), 227 deletions(-) diff --git a/libtcc.c b/libtcc.c index bfa68396..3494ee20 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 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; diff --git a/tcc.h b/tcc.h index 459e64dd..50bbd56a 100644 --- a/tcc.h +++ b/tcc.h @@ -46,7 +46,6 @@ #include /* getcwd */ #define inline __inline #define inp next_inp -#define dlclose FreeLibrary #ifdef _MSC_VER #define __aligned(n) __declspec(align(n)) #endif diff --git a/tccelf.c b/tccelf.c index 69f94c4b..826e8e0e 100644 --- a/tccelf.c +++ b/tccelf.c @@ -2424,6 +2424,7 @@ static int tcc_load_archive(TCCState *s1, int fd) return 0; } +#ifndef TCC_TARGET_PE /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL is referenced by the user (so it should be added as DT_NEEDED in the generated ELF file) */ @@ -2740,3 +2741,4 @@ static int tcc_load_ldscript(TCCState *s1) } return 0; } +#endif diff --git a/tccpe.c b/tccpe.c index 89ff3bdb..fe87919f 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 diff --git a/win32/tools/tiny_impdef.c b/win32/tools/tiny_impdef.c index 53fb255d..b024a900 100644 --- a/win32/tools/tiny_impdef.c +++ b/win32/tools/tiny_impdef.c @@ -20,100 +20,19 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY + #define WIN32_LEAN_AND_MEAN #include #include #include #include "../../config.h" -int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) -{ - fseek(fp, offset, 0); - return len == fread(buffer, 1, len, fp); -} - -char *get_export_names(FILE *fp) -{ - int l, i, n, n0; - char *p; - - 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; - const int MACHINE = 0x8664; -#else - IMAGE_OPTIONAL_HEADER32 oh; - const int MACHINE = 0x014C; -#endif - int pef_hdroffset, opt_hdroffset, sec_hdroffset; - - n = n0 = 0; - p = NULL; - - if (!read_mem(fp, 0, &dh, sizeof dh)) - goto the_end; - if (!read_mem(fp, 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(fp, pef_hdroffset, &ih, sizeof ih)) - goto the_end; - if (MACHINE != ih.Machine) - goto the_end; - opt_hdroffset = pef_hdroffset + sizeof ih; - sec_hdroffset = opt_hdroffset + sizeof oh; - if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh)) - goto the_end; - - if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) - goto the_end; - - addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - //printf("addr: %08x\n", addr); - for (i = 0; i < ih.NumberOfSections; ++i) { - if (!read_mem(fp, 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; - -found: - ref = ish.VirtualAddress - ish.PointerToRawData; - if (!read_mem(fp, addr - ref, &ied, sizeof ied)) - goto the_end; - - namep = ied.AddressOfNames - ref; - for (i = 0; i < ied.NumberOfNames; ++i) { - if (!read_mem(fp, namep, &ptr, sizeof ptr)) - goto the_end; - namep += sizeof ptr; - for (l = 0;;) { - if (n+1 >= n0) - p = realloc(p, n0 = n0 ? n0 * 2 : 256); - if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) { - free(p), p = NULL; - goto the_end; - } - if (p[n++] == 0) - break; - } - } - if (p) - p[n] = 0; -the_end: - return p; -} +char *get_export_names(FILE *fp); +#define tcc_free free +#define tcc_realloc realloc -/* -------------------------------------------------------------- */ /* extract the basename of a file */ - static char *file_basename(const char *name) { const char *p = strchr(name, 0); @@ -125,8 +44,6 @@ static char *file_basename(const char *name) return (char*)p; } -/* -------------------------------------------------------------- */ - int main(int argc, char **argv) { int ret, v, i; @@ -232,3 +149,93 @@ the_end: } /* -------------------------------------------------------------- */ + +int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) +{ + fseek(fp, offset, 0); + return len == fread(buffer, 1, len, fp); +} + +/* -------------------------------------------------------------- */ +#endif + +char *get_export_names(FILE *fp) +{ + int l, i, n, n0; + char *p; + + 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; + const int MACHINE = 0x8664; +#else + IMAGE_OPTIONAL_HEADER32 oh; + const int MACHINE = 0x014C; +#endif + int pef_hdroffset, opt_hdroffset, sec_hdroffset; + + n = n0 = 0; + p = NULL; + + if (!read_mem(fp, 0, &dh, sizeof dh)) + goto the_end; + if (!read_mem(fp, 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(fp, pef_hdroffset, &ih, sizeof ih)) + goto the_end; + if (MACHINE != ih.Machine) + goto the_end; + opt_hdroffset = pef_hdroffset + sizeof ih; + sec_hdroffset = opt_hdroffset + sizeof oh; + if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh)) + goto the_end; + + if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) + goto the_end; + + addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + //printf("addr: %08x\n", addr); + for (i = 0; i < ih.NumberOfSections; ++i) { + if (!read_mem(fp, 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; + +found: + ref = ish.VirtualAddress - ish.PointerToRawData; + if (!read_mem(fp, addr - ref, &ied, sizeof ied)) + goto the_end; + + namep = ied.AddressOfNames - ref; + for (i = 0; i < ied.NumberOfNames; ++i) { + if (!read_mem(fp, 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(fp, ptr - ref + l, p + n, 1) || ++l >= 80) { + tcc_free(p), p = NULL; + goto the_end; + } + if (p[n++] == 0) + break; + } + } + if (p) + p[n] = 0; +the_end: + return p; +} + +/* -------------------------------------------------------------- */ -- 2.11.4.GIT