Unified · Split
| @@ -212,9 +212,7 @@ static int tcc_add_file_internal(TCCState *s, const char *filename, int flags); · 211 unmodified lines | ||
| 212 | 212 | int tcc_output_coff(TCCState *s1, FILE *f); |
| 213 | 213 | |
| 214 | 214 | /* tccpe.c */ |
| 215 | −int pe_load_def_file(struct TCCState *s1, int fd); | |
| 216 | −int pe_test_res_file(void *v, int size); | |
| 217 | −int pe_load_res_file(struct TCCState *s1, int fd); | |
| 215 | +int pe_load_file(struct TCCState *s1, const char *filename, int fd); | |
| 218 | 216 | int pe_output_file(struct TCCState *s1, const char *filename); |
| 219 | 217 | |
| 220 | 218 | /* tccasm.c */ |
| @@ -277,6 +275,7 @@ static int tcc_compile(TCCState *s1); · 56 unmodified lines | ||
| 277 | 275 | void expect(const char *msg); |
| 278 | 276 | void skip(int c); |
| 279 | 277 | static void test_lvalue(void); |
| 278 | +void *resolve_sym(TCCState *s1, const char *sym); | |
| 280 | 279 | |
| 281 | 280 | static inline int isid(int c) |
| 282 | 281 | { |
| @@ -303,8 +302,6 @@ static inline int toup(int c) · 20 unmodified lines | ||
| 303 | 302 | return c; |
| 304 | 303 | } |
| 305 | 304 | |
| 306 | −void *resolve_sym(TCCState *s1, const char *sym); | |
| 307 | − | |
| 308 | 305 | /********************************************************/ |
| 309 | 306 | |
| 310 | 307 | #ifdef TCC_TARGET_I386 |
| @@ -352,6 +349,43 @@ static void asm_global_instr(void) · 41 unmodified lines | ||
| 352 | 349 | #include "tccpe.c" |
| 353 | 350 | #endif |
| 354 | 351 | |
| 352 | +/********************************************************/ | |
| 353 | +#ifdef _WIN32 | |
| 354 | +char *normalize_slashes(char *path) | |
| 355 | +{ | |
| 356 | + char *p; | |
| 357 | + for (p = path; *p; ++p) | |
| 358 | + if (*p == '\\') | |
| 359 | + *p = '/'; | |
| 360 | + return path; | |
| 361 | +} | |
| 362 | + | |
| 363 | +HMODULE tcc_module; | |
| 364 | + | |
| 365 | +/* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */ | |
| 366 | +void tcc_set_lib_path_w32(TCCState *s) | |
| 367 | +{ | |
| 368 | + char path[1024], *p; | |
| 369 | + GetModuleFileNameA(tcc_module, path, sizeof path); | |
| 370 | + p = tcc_basename(normalize_slashes(strlwr(path))); | |
| 371 | + if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) | |
| 372 | + p -= 5; | |
| 373 | + else if (p > path) | |
| 374 | + p--; | |
| 375 | + *p = 0; | |
| 376 | + tcc_set_lib_path(s, path); | |
| 377 | +} | |
| 378 | + | |
| 379 | +#ifdef LIBTCC_AS_DLL | |
| 380 | +BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) | |
| 381 | +{ | |
| 382 | + if (DLL_PROCESS_ATTACH == dwReason) | |
| 383 | + tcc_module = hDll; | |
| 384 | + return TRUE; | |
| 385 | +} | |
| 386 | +#endif | |
| 387 | +#endif | |
| 388 | + | |
| 355 | 389 | /********************************************************/ |
| 356 | 390 | #ifdef CONFIG_TCC_STATIC |
| 357 | 391 | |
| @@ -393,7 +427,7 @@ static TCCSyms tcc_syms[] = { · 35 unmodified lines | ||
| 393 | 427 | { NULL, NULL }, |
| 394 | 428 | }; |
| 395 | 429 | |
| 396 | −void *resolve_sym(TCCState *s1, const char *symbol, int type) | |
| 430 | +void *resolve_sym(TCCState *s1, const char *symbol) | |
| 397 | 431 | { |
| 398 | 432 | TCCSyms *p; |
| 399 | 433 | p = tcc_syms; |
| @@ -405,8 +439,10 @@ void *resolve_sym(TCCState *s1, const char *symbol, int type) · 5 unmodified lines | ||
| 405 | 439 | return NULL; |
| 406 | 440 | } |
| 407 | 441 | |
| 408 | −#elif !defined(_WIN32) | |
| 442 | +#elif defined(_WIN32) | |
| 443 | +#define dlclose FreeLibrary | |
| 409 | 444 | |
| 445 | +#else | |
| 410 | 446 | #include <dlfcn.h> |
| 411 | 447 | |
| 412 | 448 | 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) · 1569 unmodified lines | ||
| 1982 | 2018 | { |
| 1983 | 2019 | const char *ext; |
| 1984 | 2020 | ElfW(Ehdr) ehdr; |
| 1985 | − int fd, ret; | |
| 2021 | + int fd, ret, size; | |
| 1986 | 2022 | BufferedFile *saved_file; |
| 1987 | 2023 | |
| 2024 | + ret = -1; | |
| 2025 | + | |
| 1988 | 2026 | /* find source file type with extension */ |
| 1989 | 2027 | ext = tcc_fileextension(filename); |
| 1990 | 2028 | if (ext[0]) |
| @@ -1994,104 +2032,103 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 3 unmodified lines | ||
| 1994 | 2032 | saved_file = file; |
| 1995 | 2033 | file = tcc_open(s1, filename); |
| 1996 | 2034 | if (!file) { |
| 1997 | − if (flags & AFF_PRINT_ERROR) { | |
| 2035 | + if (flags & AFF_PRINT_ERROR) | |
| 1998 | 2036 | error_noabort("file '%s' not found", filename); |
| 1999 | − } | |
| 2000 | − ret = -1; | |
| 2001 | − goto fail1; | |
| 2037 | + goto the_end; | |
| 2002 | 2038 | } |
| 2003 | 2039 | |
| 2004 | 2040 | if (flags & AFF_PREPROCESS) { |
| 2005 | 2041 | ret = tcc_preprocess(s1); |
| 2006 | − } else if (!ext[0] || !PATHCMP(ext, "c")) { | |
| 2042 | + goto the_end; | |
| 2043 | + } | |
| 2044 | + | |
| 2045 | + if (!ext[0] || !PATHCMP(ext, "c")) { | |
| 2007 | 2046 | /* C file assumed */ |
| 2008 | 2047 | ret = tcc_compile(s1); |
| 2009 | − } else | |
| 2048 | + goto the_end; | |
| 2049 | + } | |
| 2050 | + | |
| 2010 | 2051 | #ifdef CONFIG_TCC_ASM |
| 2011 | 2052 | if (!strcmp(ext, "S")) { |
| 2012 | 2053 | /* preprocessed assembler */ |
| 2013 | 2054 | ret = tcc_assemble(s1, 1); |
| 2014 | − } else if (!strcmp(ext, "s")) { | |
| 2055 | + goto the_end; | |
| 2056 | + } | |
| 2057 | + | |
| 2058 | + if (!strcmp(ext, "s")) { | |
| 2015 | 2059 | /* non preprocessed assembler */ |
| 2016 | 2060 | ret = tcc_assemble(s1, 0); |
| 2017 | − } else | |
| 2018 | −#endif | |
| 2019 | −#ifdef TCC_TARGET_PE | |
| 2020 | − if (!PATHCMP(ext, "def")) { | |
| 2021 | − ret = pe_load_def_file(s1, file->fd); | |
| 2022 | − } else | |
| 2061 | + goto the_end; | |
| 2062 | + } | |
| 2023 | 2063 | #endif |
| 2024 | − { | |
| 2025 | − fd = file->fd; | |
| 2026 | − /* assume executable format: auto guess file type */ | |
| 2027 | − ret = read(fd, &ehdr, sizeof(ehdr)); | |
| 2028 | − lseek(fd, 0, SEEK_SET); | |
| 2029 | − if (ret <= 0) { | |
| 2030 | − error_noabort("could not read header"); | |
| 2031 | − goto fail; | |
| 2032 | − } else if (ret != sizeof(ehdr)) { | |
| 2033 | − goto try_load_script; | |
| 2034 | − } | |
| 2035 | 2064 | |
| 2036 | − if (ehdr.e_ident[0] == ELFMAG0 && | |
| 2037 | − ehdr.e_ident[1] == ELFMAG1 && | |
| 2038 | − ehdr.e_ident[2] == ELFMAG2 && | |
| 2039 | − ehdr.e_ident[3] == ELFMAG3) { | |
| 2040 | − file->line_num = 0; /* do not display line number if error */ | |
| 2041 | − if (ehdr.e_type == ET_REL) { | |
| 2042 | − ret = tcc_load_object_file(s1, fd, 0); | |
| 2043 | − } else if (ehdr.e_type == ET_DYN) { | |
| 2044 | − if (s1->output_type == TCC_OUTPUT_MEMORY) { | |
| 2045 | −#ifdef TCC_TARGET_PE | |
| 2046 | − ret = -1; | |
| 2047 | −#else | |
| 2048 | − void *h; | |
| 2049 | − h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); | |
| 2050 | − if (h) | |
| 2051 | − ret = 0; | |
| 2052 | − else | |
| 2053 | − ret = -1; | |
| 2054 | −#endif | |
| 2055 | − } else { | |
| 2056 | − ret = tcc_load_dll(s1, fd, filename, | |
| 2057 | − (flags & AFF_REFERENCED_DLL) != 0); | |
| 2058 | − } | |
| 2065 | + fd = file->fd; | |
| 2066 | + /* assume executable format: auto guess file type */ | |
| 2067 | + size = read(fd, &ehdr, sizeof(ehdr)); | |
| 2068 | + lseek(fd, 0, SEEK_SET); | |
| 2069 | + if (size <= 0) { | |
| 2070 | + error_noabort("could not read header"); | |
| 2071 | + goto the_end; | |
| 2072 | + } | |
| 2073 | + | |
| 2074 | + if (size == sizeof(ehdr) && | |
| 2075 | + ehdr.e_ident[0] == ELFMAG0 && | |
| 2076 | + ehdr.e_ident[1] == ELFMAG1 && | |
| 2077 | + ehdr.e_ident[2] == ELFMAG2 && | |
| 2078 | + ehdr.e_ident[3] == ELFMAG3) { | |
| 2079 | + | |
| 2080 | + /* do not display line number if error */ | |
| 2081 | + file->line_num = 0; | |
| 2082 | + if (ehdr.e_type == ET_REL) { | |
| 2083 | + ret = tcc_load_object_file(s1, fd, 0); | |
| 2084 | + goto the_end; | |
| 2085 | + | |
| 2086 | + } | |
| 2087 | +#ifndef TCC_TARGET_PE | |
| 2088 | + if (ehdr.e_type == ET_DYN) { | |
| 2089 | + if (s1->output_type == TCC_OUTPUT_MEMORY) { | |
| 2090 | + void *h; | |
| 2091 | + h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); | |
| 2092 | + if (h) | |
| 2093 | + ret = 0; | |
| 2059 | 2094 | } else { |
| 2060 | − error_noabort("unrecognized ELF file"); | |
| 2061 | − goto fail; | |
| 2095 | + ret = tcc_load_dll(s1, fd, filename, | |
| 2096 | + (flags & AFF_REFERENCED_DLL) != 0); | |
| 2062 | 2097 | } |
| 2063 | − } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { | |
| 2064 | − file->line_num = 0; /* do not display line number if error */ | |
| 2065 | − ret = tcc_load_archive(s1, fd); | |
| 2066 | − } else | |
| 2098 | + goto the_end; | |
| 2099 | + } | |
| 2100 | +#endif | |
| 2101 | + error_noabort("unrecognized ELF file"); | |
| 2102 | + goto the_end; | |
| 2103 | + } | |
| 2104 | + | |
| 2105 | + if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { | |
| 2106 | + file->line_num = 0; /* do not display line number if error */ | |
| 2107 | + ret = tcc_load_archive(s1, fd); | |
| 2108 | + goto the_end; | |
| 2109 | + } | |
| 2110 | + | |
| 2067 | 2111 | #ifdef TCC_TARGET_COFF |
| 2068 | − if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { | |
| 2069 | − ret = tcc_load_coff(s1, fd); | |
| 2070 | − } else | |
| 2112 | + if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { | |
| 2113 | + ret = tcc_load_coff(s1, fd); | |
| 2114 | + goto the_end; | |
| 2115 | + } | |
| 2071 | 2116 | #endif |
| 2117 | + | |
| 2072 | 2118 | #ifdef TCC_TARGET_PE |
| 2073 | − if (pe_test_res_file(&ehdr, ret)) { | |
| 2074 | − ret = pe_load_res_file(s1, fd); | |
| 2075 | − } else | |
| 2119 | + ret = pe_load_file(s1, filename, fd); | |
| 2120 | +#else | |
| 2121 | + /* as GNU ld, consider it is an ld script if not recognized */ | |
| 2122 | + ret = tcc_load_ldscript(s1); | |
| 2076 | 2123 | #endif |
| 2077 | − { | |
| 2078 | − /* as GNU ld, consider it is an ld script if not recognized */ | |
| 2079 | − try_load_script: | |
| 2080 | − ret = tcc_load_ldscript(s1); | |
| 2081 | − if (ret < 0) { | |
| 2082 | − error_noabort("unrecognized file type"); | |
| 2083 | − goto fail; | |
| 2084 | − } | |
| 2085 | − } | |
| 2086 | − } | |
| 2087 | − the_end: | |
| 2088 | − tcc_close(file); | |
| 2089 | − fail1: | |
| 2124 | + if (ret < 0) | |
| 2125 | + error_noabort("unrecognized file type"); | |
| 2126 | + | |
| 2127 | +the_end: | |
| 2128 | + if (file) | |
| 2129 | + tcc_close(file); | |
| 2090 | 2130 | file = saved_file; |
| 2091 | 2131 | return ret; |
| 2092 | − fail: | |
| 2093 | − ret = -1; | |
| 2094 | − goto the_end; | |
| 2095 | 2132 | } |
| 2096 | 2133 | |
| 2097 | 2134 | int tcc_add_file(TCCState *s, const char *filename) |
| @@ -2136,14 +2173,14 @@ int tcc_add_library(TCCState *s, const char *libraryname) · 38 unmodified lines | ||
| 2136 | 2173 | /* first we look for the dynamic library if not static linking */ |
| 2137 | 2174 | if (!s->static_link) { |
| 2138 | 2175 | #ifdef TCC_TARGET_PE |
| 2139 | − snprintf(buf, sizeof(buf), "%s.def", libraryname); | |
| 2176 | + if (pe_add_dll(s, libraryname) == 0) | |
| 2177 | + return 0; | |
| 2140 | 2178 | #else |
| 2141 | 2179 | snprintf(buf, sizeof(buf), "lib%s.so", libraryname); |
| 2142 | −#endif | |
| 2143 | 2180 | if (tcc_add_dll(s, buf, 0) == 0) |
| 2144 | 2181 | return 0; |
| 2182 | +#endif | |
| 2145 | 2183 | } |
| 2146 | − | |
| 2147 | 2184 | /* then we look for the static library */ |
| 2148 | 2185 | for(i = 0; i < s->nb_library_paths; i++) { |
| 2149 | 2186 | snprintf(buf, sizeof(buf), "%s/lib%s.a", |
| @@ -2225,6 +2262,10 @@ int tcc_set_output_type(TCCState *s, int output_type) · 75 unmodified lines | ||
| 2225 | 2262 | #ifdef TCC_TARGET_PE |
| 2226 | 2263 | snprintf(buf, sizeof(buf), "%s/lib", s->tcc_lib_path); |
| 2227 | 2264 | tcc_add_library_path(s, buf); |
| 2265 | +#ifdef _WIN32 | |
| 2266 | + if (GetSystemDirectory(buf, sizeof buf)) | |
| 2267 | + tcc_add_library_path(s, buf); | |
| 2268 | +#endif | |
| 2228 | 2269 | #endif |
| 2229 | 2270 | |
| 2230 | 2271 | return 0; |
| @@ -46,7 +46,6 @@ · 45 unmodified lines | ||
| 46 | 46 | #include <direct.h> /* getcwd */ |
| 47 | 47 | #define inline __inline |
| 48 | 48 | #define inp next_inp |
| 49 | −#define dlclose FreeLibrary | |
| 50 | 49 | #ifdef _MSC_VER |
| 51 | 50 | #define __aligned(n) __declspec(align(n)) |
| 52 | 51 | #endif |
| @@ -2424,6 +2424,7 @@ static int tcc_load_archive(TCCState *s1, int fd) · 2423 unmodified lines | ||
| 2424 | 2424 | return 0; |
| 2425 | 2425 | } |
| 2426 | 2426 | |
| 2427 | +#ifndef TCC_TARGET_PE | |
| 2427 | 2428 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL |
| 2428 | 2429 | is referenced by the user (so it should be added as DT_NEEDED in |
| 2429 | 2430 | the generated ELF file) */ |
| @@ -2740,3 +2741,4 @@ static int tcc_load_ldscript(TCCState *s1) · 310 unmodified lines | ||
| 2740 | 2741 | } |
| 2741 | 2742 | return 0; |
| 2742 | 2743 | } |
| 2744 | +#endif | |
| @@ -46,6 +46,19 @@ · 45 unmodified lines | ||
| 46 | 46 | #define TCC_IS_NATIVE |
| 47 | 47 | #endif |
| 48 | 48 | |
| 49 | +#ifdef _WIN32 | |
| 50 | +void dbg_printf (const char *fmt, ...) | |
| 51 | +{ | |
| 52 | + char buffer[4000]; | |
| 53 | + va_list arg; | |
| 54 | + int x; | |
| 55 | + va_start(arg, fmt); | |
| 56 | + x = vsprintf (buffer, fmt, arg); | |
| 57 | + strcpy(buffer+x, "\n"); | |
| 58 | + OutputDebugString(buffer); | |
| 59 | +} | |
| 60 | +#endif | |
| 61 | + | |
| 49 | 62 | /* ----------------------------------------------------------- */ |
| 50 | 63 | #ifndef IMAGE_NT_SIGNATURE |
| 51 | 64 | /* ----------------------------------------------------------- */ |
| @@ -442,29 +455,12 @@ struct pe_info { · 390 unmodified lines | ||
| 442 | 455 | int imp_count; |
| 443 | 456 | }; |
| 444 | 457 | |
| 445 | −/* ------------------------------------------------------------- */ | |
| 446 | − | |
| 447 | 458 | #define PE_NUL 0 |
| 448 | 459 | #define PE_DLL 1 |
| 449 | 460 | #define PE_GUI 2 |
| 450 | 461 | #define PE_EXE 3 |
| 451 | 462 | #define PE_RUN 4 |
| 452 | 463 | |
| 453 | −void error_noabort(const char *, ...); | |
| 454 | − | |
| 455 | −#ifdef _WIN32 | |
| 456 | −void dbg_printf (const char *fmt, ...) | |
| 457 | −{ | |
| 458 | − char buffer[4000]; | |
| 459 | − va_list arg; | |
| 460 | − int x; | |
| 461 | − va_start(arg, fmt); | |
| 462 | − x = vsprintf (buffer, fmt, arg); | |
| 463 | − strcpy(buffer+x, "\n"); | |
| 464 | − OutputDebugString(buffer); | |
| 465 | −} | |
| 466 | −#endif | |
| 467 | − | |
| 468 | 464 | /* --------------------------------------------*/ |
| 469 | 465 | |
| 470 | 466 | 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) · 884 unmodified lines | ||
| 1355 | 1351 | } |
| 1356 | 1352 | #endif |
| 1357 | 1353 | |
| 1358 | −/* ------------------------------------------------------------- | |
| 1359 | − * This is for compiled windows resources in 'coff' format | |
| 1360 | − * as generated by 'windres.exe -O coff ...'. | |
| 1361 | − */ | |
| 1354 | +/* ------------------------------------------------------------- */ | |
| 1362 | 1355 | |
| 1363 | −PUB_FN int pe_test_res_file(void *v, int size) | |
| 1356 | +ST_FN int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) | |
| 1364 | 1357 | { |
| 1365 | − struct pe_rsrc_header *p = (struct pe_rsrc_header *)v; | |
| 1366 | − return | |
| 1367 | − size >= IMAGE_SIZEOF_FILE_HEADER + IMAGE_SIZEOF_SHORT_NAME /* = 28 */ | |
| 1368 | − && p->filehdr.Machine == 0x014C | |
| 1369 | − && 1 == p->filehdr.NumberOfSections | |
| 1370 | − && 0 == strcmp(p->sectionhdr.Name, ".rsrc") | |
| 1371 | − ; | |
| 1358 | + fseek(fp, offset, 0); | |
| 1359 | + return len == fread(buffer, 1, len, fp); | |
| 1372 | 1360 | } |
| 1373 | 1361 | |
| 1374 | −ST_FN int read_n(int fd, void *ptr, unsigned size) | |
| 1375 | −{ | |
| 1376 | − return size == read(fd, ptr, size); | |
| 1377 | −} | |
| 1362 | +/* ------------------------------------------------------------- | |
| 1363 | + * This is for compiled windows resources in 'coff' format | |
| 1364 | + * as generated by 'windres.exe -O coff ...'. | |
| 1365 | + */ | |
| 1378 | 1366 | |
| 1379 | −PUB_FN int pe_load_res_file(TCCState *s1, int fd) | |
| 1367 | +ST_FN int pe_load_res(TCCState *s1, FILE *fp) | |
| 1380 | 1368 | { |
| 1381 | 1369 | struct pe_rsrc_header hdr; |
| 1382 | 1370 | Section *rsrc_section; |
| 1383 | 1371 | int i, ret = -1; |
| 1384 | 1372 | BYTE *ptr; |
| 1373 | + unsigned offs; | |
| 1385 | 1374 | |
| 1386 | − lseek (fd, 0, SEEK_SET); | |
| 1387 | − if (!read_n(fd, &hdr, sizeof hdr)) | |
| 1375 | + if (!read_mem(fp, 0, &hdr, sizeof hdr)) | |
| 1388 | 1376 | goto quit; |
| 1389 | − if (!pe_test_res_file(&hdr, sizeof hdr)) | |
| 1377 | + | |
| 1378 | + if (hdr.filehdr.Machine != 0x014C | |
| 1379 | + || hdr.filehdr.NumberOfSections != 1 | |
| 1380 | + || strcmp(hdr.sectionhdr.Name, ".rsrc") != 0) | |
| 1390 | 1381 | goto quit; |
| 1391 | 1382 | |
| 1392 | 1383 | rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC); |
| 1393 | 1384 | ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData); |
| 1394 | − lseek (fd, hdr.sectionhdr.PointerToRawData, SEEK_SET); | |
| 1395 | − if (!read_n(fd, ptr, hdr.sectionhdr.SizeOfRawData)) | |
| 1385 | + offs = hdr.sectionhdr.PointerToRawData; | |
| 1386 | + if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData)) | |
| 1396 | 1387 | goto quit; |
| 1397 | − | |
| 1398 | − lseek (fd, hdr.sectionhdr.PointerToRelocations, SEEK_SET); | |
| 1388 | + offs = hdr.sectionhdr.PointerToRelocations; | |
| 1399 | 1389 | for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) |
| 1400 | 1390 | { |
| 1401 | 1391 | struct pe_rsrc_reloc rel; |
| 1402 | − if (!read_n(fd, &rel, sizeof rel)) | |
| 1392 | + if (!read_mem(fp, offs, &rel, sizeof rel)) | |
| 1403 | 1393 | goto quit; |
| 1404 | 1394 | // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type); |
| 1405 | 1395 | if (rel.type != 7) /* DIR32NB */ |
| 1406 | 1396 | goto quit; |
| 1407 | 1397 | put_elf_reloc(symtab_section, rsrc_section, |
| 1408 | 1398 | rel.offset, R_XXX_RELATIVE, 0); |
| 1399 | + offs += sizeof rel; | |
| 1409 | 1400 | } |
| 1410 | 1401 | ret = 0; |
| 1411 | 1402 | quit: |
| 1412 | − if (ret) | |
| 1413 | − error_noabort("unrecognized resource file format"); | |
| 1414 | 1403 | return ret; |
| 1415 | 1404 | } |
| 1416 | 1405 | |
| @@ -1439,15 +1428,11 @@ ST_FN char *get_line(char *line, int size, FILE *fp) · 22 unmodified lines | ||
| 1439 | 1428 | } |
| 1440 | 1429 | |
| 1441 | 1430 | /* ------------------------------------------------------------- */ |
| 1442 | −PUB_FN int pe_load_def_file(TCCState *s1, int fd) | |
| 1431 | +ST_FN int pe_load_def(TCCState *s1, FILE *fp) | |
| 1443 | 1432 | { |
| 1444 | 1433 | DLLReference *dllref; |
| 1445 | 1434 | int state = 0, ret = -1; |
| 1446 | 1435 | char line[400], dllname[80], *p; |
| 1447 | − FILE *fp = fdopen(dup(fd), "rb"); | |
| 1448 | − | |
| 1449 | − if (NULL == fp) | |
| 1450 | − goto quit; | |
| 1451 | 1436 | |
| 1452 | 1437 | for (;;) { |
| 1453 | 1438 | p = get_line(line, sizeof line, fp); |
| @@ -1485,13 +1470,65 @@ PUB_FN int pe_load_def_file(TCCState *s1, int fd) · 31 unmodified lines | ||
| 1485 | 1470 | } |
| 1486 | 1471 | ret = 0; |
| 1487 | 1472 | quit: |
| 1488 | − if (fp) | |
| 1473 | + return ret; | |
| 1474 | +} | |
| 1475 | + | |
| 1476 | +/* ------------------------------------------------------------- */ | |
| 1477 | +#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY | |
| 1478 | +#include "win32/tools/tiny_impdef.c" | |
| 1479 | + | |
| 1480 | +ST_FN int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp) | |
| 1481 | +{ | |
| 1482 | + int i = 0; | |
| 1483 | + char *p, *q; | |
| 1484 | + p = get_export_names(fp); | |
| 1485 | + if (p) { | |
| 1486 | + DLLReference *dllref; | |
| 1487 | + dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); | |
| 1488 | + strcpy(dllref->name, dllname); | |
| 1489 | + dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); | |
| 1490 | + for (q = p, i = 0; *q; ++i) { | |
| 1491 | + add_elf_sym(s1->dynsymtab_section, | |
| 1492 | + s1->nb_loaded_dlls, 0, | |
| 1493 | + ELFW_ST_INFO(STB_GLOBAL, STT_FUNC), 0, | |
| 1494 | + text_section->sh_num, q); | |
| 1495 | + q += 1 + strlen(q); | |
| 1496 | + } | |
| 1497 | + tcc_free(p); | |
| 1498 | + } | |
| 1499 | + return i ? 0 : -1; | |
| 1500 | +} | |
| 1501 | + | |
| 1502 | +/* ------------------------------------------------------------- */ | |
| 1503 | +PUB_FN int pe_load_file(struct TCCState *s1, const char *filename, int fd) | |
| 1504 | +{ | |
| 1505 | + FILE *fp = fdopen(dup(fd), "rb"); | |
| 1506 | + int ret = -1; | |
| 1507 | + char buf[10]; | |
| 1508 | + if (fp) { | |
| 1509 | + if (0 == strcmp(tcc_fileextension(filename), ".def")) | |
| 1510 | + ret = pe_load_def(s1, fp); | |
| 1511 | + else if (pe_load_res(s1, fp) == 0) | |
| 1512 | + ret = 0; | |
| 1513 | + else if (read_mem(fp, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2)) | |
| 1514 | + ret = pe_load_dll(s1, filename, fp); | |
| 1489 | 1515 | fclose(fp); |
| 1490 | − if (ret) | |
| 1491 | − error_noabort("unrecognized export definition file format"); | |
| 1516 | + } | |
| 1492 | 1517 | return ret; |
| 1493 | 1518 | } |
| 1494 | 1519 | |
| 1520 | +int pe_add_dll(struct TCCState *s, const char *libraryname) | |
| 1521 | +{ | |
| 1522 | + char buf[MAX_PATH]; | |
| 1523 | + snprintf(buf, sizeof(buf), "%s.def", libraryname); | |
| 1524 | + if (tcc_add_dll(s, buf, 0) == 0) | |
| 1525 | + return 0; | |
| 1526 | + snprintf(buf, sizeof(buf), "%s.dll", libraryname); | |
| 1527 | + if (tcc_add_dll(s, buf, 0) == 0) | |
| 1528 | + return 0; | |
| 1529 | + return -1; | |
| 1530 | +} | |
| 1531 | + | |
| 1495 | 1532 | /* ------------------------------------------------------------- */ |
| 1496 | 1533 | #ifdef TCC_TARGET_X86_64 |
| 1497 | 1534 | #define PE_STDSYM(n,s) n |
| @@ -20,100 +20,19 @@ · 19 unmodified lines | ||
| 20 | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 21 | 21 | */ |
| 22 | 22 | |
| 23 | +#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY | |
| 24 | + | |
| 23 | 25 | #define WIN32_LEAN_AND_MEAN |
| 24 | 26 | #include <windows.h> |
| 25 | 27 | #include <stdio.h> |
| 26 | 28 | #include <malloc.h> |
| 27 | 29 | #include "../../config.h" |
| 28 | 30 | |
| 29 | −int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) | |
| 30 | −{ | |
| 31 | − fseek(fp, offset, 0); | |
| 32 | − return len == fread(buffer, 1, len, fp); | |
| 33 | −} | |
| 34 | − | |
| 35 | −char *get_export_names(FILE *fp) | |
| 36 | −{ | |
| 37 | − int l, i, n, n0; | |
| 38 | − char *p; | |
| 39 | − | |
| 40 | − IMAGE_SECTION_HEADER ish; | |
| 41 | − IMAGE_EXPORT_DIRECTORY ied; | |
| 42 | − IMAGE_DOS_HEADER dh; | |
| 43 | − IMAGE_FILE_HEADER ih; | |
| 44 | − DWORD sig, ref, addr, ptr, namep; | |
| 45 | −#ifdef TCC_TARGET_X86_64 | |
| 46 | − IMAGE_OPTIONAL_HEADER64 oh; | |
| 47 | − const int MACHINE = 0x8664; | |
| 48 | −#else | |
| 49 | − IMAGE_OPTIONAL_HEADER32 oh; | |
| 50 | − const int MACHINE = 0x014C; | |
| 51 | −#endif | |
| 52 | − int pef_hdroffset, opt_hdroffset, sec_hdroffset; | |
| 53 | − | |
| 54 | − n = n0 = 0; | |
| 55 | − p = NULL; | |
| 56 | − | |
| 57 | − if (!read_mem(fp, 0, &dh, sizeof dh)) | |
| 58 | − goto the_end; | |
| 59 | − if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig)) | |
| 60 | − goto the_end; | |
| 61 | − if (sig != 0x00004550) | |
| 62 | − goto the_end; | |
| 63 | − pef_hdroffset = dh.e_lfanew + sizeof sig; | |
| 64 | − if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih)) | |
| 65 | − goto the_end; | |
| 66 | − if (MACHINE != ih.Machine) | |
| 67 | − goto the_end; | |
| 68 | − opt_hdroffset = pef_hdroffset + sizeof ih; | |
| 69 | − sec_hdroffset = opt_hdroffset + sizeof oh; | |
| 70 | − if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh)) | |
| 71 | − goto the_end; | |
| 72 | − | |
| 73 | − if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | |
| 74 | − goto the_end; | |
| 75 | − | |
| 76 | − addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
| 77 | − //printf("addr: %08x\n", addr); | |
| 78 | − for (i = 0; i < ih.NumberOfSections; ++i) { | |
| 79 | − if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) | |
| 80 | − goto the_end; | |
| 81 | − //printf("vaddr: %08x\n", ish.VirtualAddress); | |
| 82 | − if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) | |
| 83 | − goto found; | |
| 84 | − } | |
| 85 | − goto the_end; | |
| 86 | − | |
| 87 | −found: | |
| 88 | − ref = ish.VirtualAddress - ish.PointerToRawData; | |
| 89 | − if (!read_mem(fp, addr - ref, &ied, sizeof ied)) | |
| 90 | − goto the_end; | |
| 91 | − | |
| 92 | − namep = ied.AddressOfNames - ref; | |
| 93 | − for (i = 0; i < ied.NumberOfNames; ++i) { | |
| 94 | − if (!read_mem(fp, namep, &ptr, sizeof ptr)) | |
| 95 | − goto the_end; | |
| 96 | − namep += sizeof ptr; | |
| 97 | − for (l = 0;;) { | |
| 98 | − if (n+1 >= n0) | |
| 99 | − p = realloc(p, n0 = n0 ? n0 * 2 : 256); | |
| 100 | − if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) { | |
| 101 | − free(p), p = NULL; | |
| 102 | − goto the_end; | |
| 103 | − } | |
| 104 | − if (p[n++] == 0) | |
| 105 | − break; | |
| 106 | − } | |
| 107 | − } | |
| 108 | − if (p) | |
| 109 | − p[n] = 0; | |
| 110 | −the_end: | |
| 111 | − return p; | |
| 112 | −} | |
| 31 | +char *get_export_names(FILE *fp); | |
| 32 | +#define tcc_free free | |
| 33 | +#define tcc_realloc realloc | |
| 113 | 34 | |
| 114 | −/* -------------------------------------------------------------- */ | |
| 115 | 35 | /* extract the basename of a file */ |
| 116 | − | |
| 117 | 36 | static char *file_basename(const char *name) |
| 118 | 37 | { |
| 119 | 38 | const char *p = strchr(name, 0); |
| @@ -125,8 +44,6 @@ static char *file_basename(const char *name) · 5 unmodified lines | ||
| 125 | 44 | return (char*)p; |
| 126 | 45 | } |
| 127 | 46 | |
| 128 | −/* -------------------------------------------------------------- */ | |
| 129 | − | |
| 130 | 47 | int main(int argc, char **argv) |
| 131 | 48 | { |
| 132 | 49 | int ret, v, i; |
| @@ -232,3 +149,93 @@ the_end: · 99 unmodified lines | ||
| 232 | 149 | } |
| 233 | 150 | |
| 234 | 151 | /* -------------------------------------------------------------- */ |
| 152 | + | |
| 153 | +int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len) | |
| 154 | +{ | |
| 155 | + fseek(fp, offset, 0); | |
| 156 | + return len == fread(buffer, 1, len, fp); | |
| 157 | +} | |
| 158 | + | |
| 159 | +/* -------------------------------------------------------------- */ | |
| 160 | +#endif | |
| 161 | + | |
| 162 | +char *get_export_names(FILE *fp) | |
| 163 | +{ | |
| 164 | + int l, i, n, n0; | |
| 165 | + char *p; | |
| 166 | + | |
| 167 | + IMAGE_SECTION_HEADER ish; | |
| 168 | + IMAGE_EXPORT_DIRECTORY ied; | |
| 169 | + IMAGE_DOS_HEADER dh; | |
| 170 | + IMAGE_FILE_HEADER ih; | |
| 171 | + DWORD sig, ref, addr, ptr, namep; | |
| 172 | +#ifdef TCC_TARGET_X86_64 | |
| 173 | + IMAGE_OPTIONAL_HEADER64 oh; | |
| 174 | + const int MACHINE = 0x8664; | |
| 175 | +#else | |
| 176 | + IMAGE_OPTIONAL_HEADER32 oh; | |
| 177 | + const int MACHINE = 0x014C; | |
| 178 | +#endif | |
| 179 | + int pef_hdroffset, opt_hdroffset, sec_hdroffset; | |
| 180 | + | |
| 181 | + n = n0 = 0; | |
| 182 | + p = NULL; | |
| 183 | + | |
| 184 | + if (!read_mem(fp, 0, &dh, sizeof dh)) | |
| 185 | + goto the_end; | |
| 186 | + if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig)) | |
| 187 | + goto the_end; | |
| 188 | + if (sig != 0x00004550) | |
| 189 | + goto the_end; | |
| 190 | + pef_hdroffset = dh.e_lfanew + sizeof sig; | |
| 191 | + if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih)) | |
| 192 | + goto the_end; | |
| 193 | + if (MACHINE != ih.Machine) | |
| 194 | + goto the_end; | |
| 195 | + opt_hdroffset = pef_hdroffset + sizeof ih; | |
| 196 | + sec_hdroffset = opt_hdroffset + sizeof oh; | |
| 197 | + if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh)) | |
| 198 | + goto the_end; | |
| 199 | + | |
| 200 | + if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | |
| 201 | + goto the_end; | |
| 202 | + | |
| 203 | + addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
| 204 | + //printf("addr: %08x\n", addr); | |
| 205 | + for (i = 0; i < ih.NumberOfSections; ++i) { | |
| 206 | + if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) | |
| 207 | + goto the_end; | |
| 208 | + //printf("vaddr: %08x\n", ish.VirtualAddress); | |
| 209 | + if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) | |
| 210 | + goto found; | |
| 211 | + } | |
| 212 | + goto the_end; | |
| 213 | + | |
| 214 | +found: | |
| 215 | + ref = ish.VirtualAddress - ish.PointerToRawData; | |
| 216 | + if (!read_mem(fp, addr - ref, &ied, sizeof ied)) | |
| 217 | + goto the_end; | |
| 218 | + | |
| 219 | + namep = ied.AddressOfNames - ref; | |
| 220 | + for (i = 0; i < ied.NumberOfNames; ++i) { | |
| 221 | + if (!read_mem(fp, namep, &ptr, sizeof ptr)) | |
| 222 | + goto the_end; | |
| 223 | + namep += sizeof ptr; | |
| 224 | + for (l = 0;;) { | |
| 225 | + if (n+1 >= n0) | |
| 226 | + p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); | |
| 227 | + if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) { | |
| 228 | + tcc_free(p), p = NULL; | |
| 229 | + goto the_end; | |
| 230 | + } | |
| 231 | + if (p[n++] == 0) | |
| 232 | + break; | |
| 233 | + } | |
| 234 | + } | |
| 235 | + if (p) | |
| 236 | + p[n] = 0; | |
| 237 | +the_end: | |
| 238 | + return p; | |
| 239 | +} | |
| 240 | + | |
| 241 | +/* -------------------------------------------------------------- */ | |