From fe9b1f60ce2ff21c248799ad0ea73fb7c70ef0d1 Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 17 Apr 2005 13:15:54 +0000 Subject: [PATCH] win32 merge (grischka) --- tcc.c | 31 ++++++--- tccelf.c | 11 +-- tccpe.c | 85 ++++++++++++++++------- win32/readme.txt | 204 +++++++++++++++++++++++++++---------------------------- 4 files changed, 186 insertions(+), 145 deletions(-) diff --git a/tcc.c b/tcc.c index 85bf5037..2a59808b 100644 --- a/tcc.c +++ b/tcc.c @@ -711,9 +711,12 @@ int __stdcall FreeConsole(void); #define snprintf _snprintf #define vsnprintf _vsnprintf +#ifndef __GNUC__ + #define strtold (long double)strtod + #define strtof (float)strtod + #define strtoll (long long)strtol #endif - -#if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__) +#elif defined(TCC_UCLIBC) || defined(__FreeBSD__) /* currently incorrect */ long double strtold(const char *nptr, char **endptr) { @@ -2730,6 +2733,7 @@ static void pragma_parse(TCCState *s1) #pragma pack(push,1) // push & set #pragma pack(pop) // restore previous */ + next(); skip('('); if (tok == TOK_ASM_pop) { next(); @@ -10514,8 +10518,10 @@ int main(int argc, char **argv) GetModuleFileNameA(NULL, path, sizeof path); p = d = strlwr(path); while (*d) - if (*d++ == '\\') - (p = d)[-1] = '/'; + { + if (*d == '\\') *d = '/', p = d; + ++d; + } *p = '\0'; tcc_lib_path = path; } @@ -10555,23 +10561,28 @@ int main(int argc, char **argv) error("cannot specify libraries with -c"); } + if (output_type != TCC_OUTPUT_MEMORY) { + if (!outfile) { /* compute default outfile name */ - if (output_type != TCC_OUTPUT_MEMORY && !outfile) { - if (output_type == TCC_OUTPUT_OBJ && !reloc_output) { - char *ext; - /* strip path */ pstrcpy(objfilename, sizeof(objfilename) - 1, + /* strip path */ tcc_basename(files[0])); - /* add .o extension */ - ext = strrchr(objfilename, '.'); +#ifdef TCC_TARGET_PE + pe_guess_outfile(objfilename, output_type); +#else + if (output_type == TCC_OUTPUT_OBJ && !reloc_output) { + char *ext = strrchr(objfilename, '.'); if (!ext) goto default_outfile; + /* add .o extension */ strcpy(ext + 1, "o"); } else { default_outfile: pstrcpy(objfilename, sizeof(objfilename), "a.out"); } +#endif outfile = objfilename; + } } if (do_bench) { diff --git a/tccelf.c b/tccelf.c index e1ca9013..0e521854 100644 --- a/tccelf.c +++ b/tccelf.c @@ -2095,7 +2095,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) { Elf32_Ehdr ehdr; Elf32_Shdr *shdr, *sh, *sh1; - int i, nb_syms, nb_dts, sym_bind, ret, other; + int i, nb_syms, nb_dts, sym_bind, ret; Elf32_Sym *sym, *dynsym; Elf32_Dyn *dt, *dynamic; unsigned char *dynstr; @@ -2175,15 +2175,8 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) if (sym_bind == STB_LOCAL) continue; name = dynstr + sym->st_name; -#ifdef TCC_TARGET_PE - /* in the PE format we need to know the DLL from which the - symbol comes. XXX: add a new array for that ? */ - other = s1->nb_loaded_dlls - 1; -#else - other = sym->st_other; -#endif add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, - sym->st_info, other, sym->st_shndx, name); + sym->st_info, sym->st_other, sym->st_shndx, name); } /* load all referenced DLLs */ diff --git a/tccpe.c b/tccpe.c index 611019e5..5911296c 100644 --- a/tccpe.c +++ b/tccpe.c @@ -742,24 +742,38 @@ ST void pe_build_imports(struct pe_info *pe) } /* ------------------------------------------------------------- */ +ST int sym_cmp(const void *va, const void *vb) +{ + Elf32_Sym *sa = (Elf32_Sym *)symtab_section->data + *(int*)va; + Elf32_Sym *sb = (Elf32_Sym *)symtab_section->data + *(int*)vb; + const char *ca = symtab_section->link->data + sa->st_name; + const char *cb = symtab_section->link->data + sb->st_name; + return strcmp(ca, cb); +} + ST void pe_build_exports(struct pe_info *pe) { Elf32_Sym *sym; - DWORD func_offset; - DWORD voffset = pe->thunk->sh_addr - pe->imagebase; + DWORD func_offset, voffset; struct pe_export_header *hdr; - int sym_count = 0, ordinal = 0; + int sym_count, n, ord, *sorted; + + voffset = pe->thunk->sh_addr - pe->imagebase; + sym_count = 0, n = 1, sorted = NULL; // for simplicity only functions are exported for_sym_in_symtab(sym) - if (sym->st_shndx != text_section->sh_num) - sym->st_other &= ~1; - else if (sym->st_other & 1) - ++sym_count; + { + if ((sym->st_other & 1) + && sym->st_shndx == text_section->sh_num) + dynarray_add((void***)&sorted, &sym_count, (void*)n); + ++n; + } if (0 == sym_count) return; + qsort (sorted, sym_count, sizeof sorted[0], sym_cmp); pe_align_section(pe->thunk, 16); pe->exp_offs = pe->thunk->data_offset; @@ -774,30 +788,28 @@ ST void pe_build_exports(struct pe_info *pe) hdr->NumberOfFunctions = sym_count; hdr->NumberOfNames = sym_count; hdr->AddressOfFunctions = func_offset + voffset; - hdr->AddressOfNames = - hdr->AddressOfFunctions + sym_count * sizeof(DWORD); - hdr->AddressOfNameOrdinals = - hdr->AddressOfNames + sym_count * sizeof(DWORD); + hdr->AddressOfNames = hdr->AddressOfFunctions + sym_count * sizeof(DWORD); + hdr->AddressOfNameOrdinals = hdr->AddressOfNames + sym_count * sizeof(DWORD); hdr->Name = pe->thunk->data_offset + voffset; put_elf_str(pe->thunk, tcc_basename(pe->filename)); - for_sym_in_symtab(sym) - if (sym->st_other & 1) { - char *name = symtab_section->link->data + sym->st_name; - DWORD *p = (DWORD *) (pe->thunk->data + func_offset); - DWORD *pfunc = p + ordinal; - DWORD *pname = p + sym_count + ordinal; - WORD *pord = (WORD *) (p + 2 * sym_count) + ordinal; - *pfunc = - sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - - pe->imagebase; + for (ord = 0; ord < sym_count; ++ord) + { + char *name; DWORD *p, *pfunc, *pname; WORD *pord; + sym = (Elf32_Sym *)symtab_section->data + sorted[ord]; + name = symtab_section->link->data + sym->st_name; + p = (DWORD*)(pe->thunk->data + func_offset); + pfunc = p + ord; + pname = p + sym_count + ord; + pord = (WORD *)(p + 2*sym_count) + ord; + *pfunc = sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pe->imagebase; *pname = pe->thunk->data_offset + voffset; - *pord = ordinal; + *pord = ord; put_elf_str(pe->thunk, name); /* printf("export: %s\n", name); */ - ++ordinal; } pe->exp_size = pe->thunk->data_offset - pe->exp_offs; + tcc_free(sorted); } /* ------------------------------------------------------------- */ @@ -1120,6 +1132,24 @@ int pe_load_def_file(TCCState * s1, FILE * fp) } /* ------------------------------------------------------------- */ +void pe_guess_outfile(char *objfilename, int output_type) +{ + char *ext = strrchr(objfilename, '.'); + if (NULL == ext) + ext = strchr(objfilename, 0); + if (output_type == TCC_OUTPUT_DLL) + strcpy(ext, ".dll"); + else + if (output_type == TCC_OUTPUT_EXE) + strcpy(ext, ".exe"); + else + if (output_type == TCC_OUTPUT_OBJ && strcmp(ext, ".o")) + strcpy(ext, ".o"); + else + error("no outputfile given"); +} + +/* ------------------------------------------------------------- */ unsigned long pe_add_runtime(TCCState * s1) { const char *start_symbol; @@ -1127,6 +1157,13 @@ unsigned long pe_add_runtime(TCCState * s1) if (find_elf_sym(symtab_section, "WinMain")) pe_type = PE_GUI; + else + if (TCC_OUTPUT_DLL == s1->output_type) + { + pe_type = PE_DLL; + // need this for 'tccelf.c:relocate_section()' + s1->output_type = TCC_OUTPUT_EXE; + } start_symbol = TCC_OUTPUT_MEMORY == s1->output_type @@ -1192,7 +1229,7 @@ int tcc_output_pe(TCCState * s1, const char *filename) { Section *s; FILE *f; - f = fopen("tccpe.log", "wb"); + f = fopen("tccpe.log", "wt"); for (i = 1; i < s1->nb_sections; ++i) { s = s1->sections[i]; pe_print_section(f, s); diff --git a/win32/readme.txt b/win32/readme.txt index 69416968..e4db70b2 100644 --- a/win32/readme.txt +++ b/win32/readme.txt @@ -1,102 +1,102 @@ - - TinyCC-PE - --------- - - TinyCC (aka TCC) is a small but hyperfast C compiler, - written by Fabrice Bellard, - - - TinyCC-PE is the TinyCC compiler with an extension to - write PE executables for MS-Windows. - - - Features: - --------- - - TinyCC-PE can produce console applications, native windows - GUI programs and DLL's. - - Most of the features pointed out by Fabrice Bellard for the - original version are still valid, i.e: - - - SMALL! The package with ~400kb includes a complete C-compiler - with header files for console and GUI applications. - - - With the -run switch you can run C-sources without any - linking directly from the command line. - - - TCC can of course compile itself. - - - Installation: - ------------- - - Just unzip the package to a directory anywhere on your computer. - - - Examples: - --------- - - For the 'Fibonacci' console example type from the command line: - - tcc examples\fib.c - - - For the 'Hello Windows' GUI example: - - tcc examples\hello_win.c - - - For the 'Hello DLL' example: - - tcc -shared examples\dll.c - tcc examples\hello_dll.c examples\dll.def - - - Import Definitions: - ------------------- - - TinyCC-PE searches and reads import definition files similar - to libraries. - - The included 'tiny_impdef' program may be used to make .def files - for any DLL, e.g for an 'opengl32.def': - - tiny_impdef.exe opengl32.dll - - or to the same effect: - - tcc -lkernel32 -run tiny_impdef.c opengl32.dll - - - Header Files: - ------------- - - The system header files, except '_mingw.h', are from the - 2.0 mingw distribution. See also: http://www.mingw.org/ - - - Compile TCC: - ------------ - - With TCC itself just say: - - tcc src\tcc.c -lkernel32 -o tcc.new.exe - - Other compilers like mingw-gcc or msvc work as well. - To make libtcc1.a, you need 'ar' from the mingw binutils. - - - Documentation and License: - -------------------------- - - TCC is distributed under the GNU Lesser General Public License - (see COPYING file). - - Please read the original tcc-doc.html to have all the features - of TCC. Also visit: http://fabrice.bellard.free.fr/tcc/ - - - -------------------------------------------- - 09.Apr.2005 - grischka@users.sourceforge.net - + + TinyCC-PE + --------- + + TinyCC (aka TCC) is a small but hyperfast C compiler, + written by Fabrice Bellard, + + + TinyCC-PE is the TinyCC compiler with an extension to + write PE executables for MS-Windows. + + + Features: + --------- + + TinyCC-PE can produce console applications, native windows + GUI programs and DLL's. + + Most of the features pointed out by Fabrice Bellard for the + original version are still valid, i.e: + + - SMALL! The package with ~400kb includes a complete C-compiler + with header files for console and GUI applications. + + - With the -run switch you can run C-sources without any + linking directly from the command line. + + - TCC can of course compile itself. + + + Installation: + ------------- + + Just unzip the package to a directory anywhere on your computer. + + + Examples: + --------- + + For the 'Fibonacci' console example type from the command line: + + tcc examples\fib.c + + + For the 'Hello Windows' GUI example: + + tcc examples\hello_win.c + + + For the 'Hello DLL' example: + + tcc -shared examples\dll.c + tcc examples\hello_dll.c examples\dll.def + + + Import Definitions: + ------------------- + + TinyCC-PE searches and reads import definition files similar + to libraries. + + The included 'tiny_impdef' program may be used to make .def files + for any DLL, e.g for an 'opengl32.def': + + tiny_impdef.exe opengl32.dll + + or to the same effect: + + tcc -lkernel32 -run tiny_impdef.c opengl32.dll + + + Header Files: + ------------- + + The system header files, except '_mingw.h', are from the + 2.0 mingw distribution. See also: http://www.mingw.org/ + + + Compile TCC: + ------------ + + With TCC itself just say: + + tcc src\tcc.c -lkernel32 -o tcc.new.exe + + Other compilers like mingw-gcc or msvc work as well. + To make libtcc1.a, you need 'ar' from the mingw binutils. + + + Documentation and License: + -------------------------- + + TCC is distributed under the GNU Lesser General Public License + (see COPYING file). + + Please read the original tcc-doc.html to have all the features + of TCC. Also visit: http://fabrice.bellard.free.fr/tcc/ + + + -------------------------------------------- + 09.Apr.2005 - grischka@users.sourceforge.net + -- 2.11.4.GIT