win32 merge (grischka)

tcc-xref
bellard 2005-04-17 13:15:54 +00:00
parent 09f4ce9857
commit fe9b1f60ce
4 changed files with 186 additions and 145 deletions

31
tcc.c
View File

@ -711,9 +711,12 @@ int __stdcall FreeConsole(void);
#define snprintf _snprintf #define snprintf _snprintf
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#ifndef __GNUC__
#define strtold (long double)strtod
#define strtof (float)strtod
#define strtoll (long long)strtol
#endif #endif
#elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
#if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
/* currently incorrect */ /* currently incorrect */
long double strtold(const char *nptr, char **endptr) 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(push,1) // push & set
#pragma pack(pop) // restore previous #pragma pack(pop) // restore previous
*/ */
next();
skip('('); skip('(');
if (tok == TOK_ASM_pop) { if (tok == TOK_ASM_pop) {
next(); next();
@ -10514,8 +10518,10 @@ int main(int argc, char **argv)
GetModuleFileNameA(NULL, path, sizeof path); GetModuleFileNameA(NULL, path, sizeof path);
p = d = strlwr(path); p = d = strlwr(path);
while (*d) while (*d)
if (*d++ == '\\') {
(p = d)[-1] = '/'; if (*d == '\\') *d = '/', p = d;
++d;
}
*p = '\0'; *p = '\0';
tcc_lib_path = path; tcc_lib_path = path;
} }
@ -10555,23 +10561,28 @@ int main(int argc, char **argv)
error("cannot specify libraries with -c"); error("cannot specify libraries with -c");
} }
if (output_type != TCC_OUTPUT_MEMORY) {
if (!outfile) {
/* compute default outfile name */ /* 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, pstrcpy(objfilename, sizeof(objfilename) - 1,
/* strip path */
tcc_basename(files[0])); tcc_basename(files[0]));
/* add .o extension */ #ifdef TCC_TARGET_PE
ext = strrchr(objfilename, '.'); pe_guess_outfile(objfilename, output_type);
#else
if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
char *ext = strrchr(objfilename, '.');
if (!ext) if (!ext)
goto default_outfile; goto default_outfile;
/* add .o extension */
strcpy(ext + 1, "o"); strcpy(ext + 1, "o");
} else { } else {
default_outfile: default_outfile:
pstrcpy(objfilename, sizeof(objfilename), "a.out"); pstrcpy(objfilename, sizeof(objfilename), "a.out");
} }
#endif
outfile = objfilename; outfile = objfilename;
}
} }
if (do_bench) { if (do_bench) {

View File

@ -2095,7 +2095,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
{ {
Elf32_Ehdr ehdr; Elf32_Ehdr ehdr;
Elf32_Shdr *shdr, *sh, *sh1; 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_Sym *sym, *dynsym;
Elf32_Dyn *dt, *dynamic; Elf32_Dyn *dt, *dynamic;
unsigned char *dynstr; 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) if (sym_bind == STB_LOCAL)
continue; continue;
name = dynstr + sym->st_name; 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, 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 */ /* load all referenced DLLs */

85
tccpe.c
View File

@ -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) ST void pe_build_exports(struct pe_info *pe)
{ {
Elf32_Sym *sym; Elf32_Sym *sym;
DWORD func_offset; DWORD func_offset, voffset;
DWORD voffset = pe->thunk->sh_addr - pe->imagebase;
struct pe_export_header *hdr; 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 simplicity only functions are exported
for_sym_in_symtab(sym) for_sym_in_symtab(sym)
if (sym->st_shndx != text_section->sh_num) {
sym->st_other &= ~1; if ((sym->st_other & 1)
else if (sym->st_other & 1) && sym->st_shndx == text_section->sh_num)
++sym_count; dynarray_add((void***)&sorted, &sym_count, (void*)n);
++n;
}
if (0 == sym_count) if (0 == sym_count)
return; return;
qsort (sorted, sym_count, sizeof sorted[0], sym_cmp);
pe_align_section(pe->thunk, 16); pe_align_section(pe->thunk, 16);
pe->exp_offs = pe->thunk->data_offset; 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->NumberOfFunctions = sym_count;
hdr->NumberOfNames = sym_count; hdr->NumberOfNames = sym_count;
hdr->AddressOfFunctions = func_offset + voffset; hdr->AddressOfFunctions = func_offset + voffset;
hdr->AddressOfNames = hdr->AddressOfNames = hdr->AddressOfFunctions + sym_count * sizeof(DWORD);
hdr->AddressOfFunctions + sym_count * sizeof(DWORD); hdr->AddressOfNameOrdinals = hdr->AddressOfNames + sym_count * sizeof(DWORD);
hdr->AddressOfNameOrdinals =
hdr->AddressOfNames + sym_count * sizeof(DWORD);
hdr->Name = pe->thunk->data_offset + voffset; hdr->Name = pe->thunk->data_offset + voffset;
put_elf_str(pe->thunk, tcc_basename(pe->filename)); put_elf_str(pe->thunk, tcc_basename(pe->filename));
for_sym_in_symtab(sym) for (ord = 0; ord < sym_count; ++ord)
if (sym->st_other & 1) { {
char *name = symtab_section->link->data + sym->st_name; char *name; DWORD *p, *pfunc, *pname; WORD *pord;
DWORD *p = (DWORD *) (pe->thunk->data + func_offset); sym = (Elf32_Sym *)symtab_section->data + sorted[ord];
DWORD *pfunc = p + ordinal; name = symtab_section->link->data + sym->st_name;
DWORD *pname = p + sym_count + ordinal; p = (DWORD*)(pe->thunk->data + func_offset);
WORD *pord = (WORD *) (p + 2 * sym_count) + ordinal; pfunc = p + ord;
*pfunc = pname = p + sym_count + ord;
sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pord = (WORD *)(p + 2*sym_count) + ord;
pe->imagebase; *pfunc = sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pe->imagebase;
*pname = pe->thunk->data_offset + voffset; *pname = pe->thunk->data_offset + voffset;
*pord = ordinal; *pord = ord;
put_elf_str(pe->thunk, name); put_elf_str(pe->thunk, name);
/* printf("export: %s\n", name); */ /* printf("export: %s\n", name); */
++ordinal;
} }
pe->exp_size = pe->thunk->data_offset - pe->exp_offs; pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
tcc_free(sorted);
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -1119,6 +1131,24 @@ int pe_load_def_file(TCCState * s1, FILE * fp)
return 0; return 0;
} }
/* ------------------------------------------------------------- */
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) unsigned long pe_add_runtime(TCCState * s1)
{ {
@ -1127,6 +1157,13 @@ unsigned long pe_add_runtime(TCCState * s1)
if (find_elf_sym(symtab_section, "WinMain")) if (find_elf_sym(symtab_section, "WinMain"))
pe_type = PE_GUI; 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 = start_symbol =
TCC_OUTPUT_MEMORY == s1->output_type TCC_OUTPUT_MEMORY == s1->output_type
@ -1192,7 +1229,7 @@ int tcc_output_pe(TCCState * s1, const char *filename)
{ {
Section *s; Section *s;
FILE *f; FILE *f;
f = fopen("tccpe.log", "wb"); f = fopen("tccpe.log", "wt");
for (i = 1; i < s1->nb_sections; ++i) { for (i = 1; i < s1->nb_sections; ++i) {
s = s1->sections[i]; s = s1->sections[i];
pe_print_section(f, s); pe_print_section(f, s);

View File

@ -1,102 +1,102 @@
TinyCC-PE TinyCC-PE
--------- ---------
TinyCC (aka TCC) is a small but hyperfast C compiler, TinyCC (aka TCC) is a small but hyperfast C compiler,
written by Fabrice Bellard, written by Fabrice Bellard,
TinyCC-PE is the TinyCC compiler with an extension to TinyCC-PE is the TinyCC compiler with an extension to
write PE executables for MS-Windows. write PE executables for MS-Windows.
Features: Features:
--------- ---------
TinyCC-PE can produce console applications, native windows TinyCC-PE can produce console applications, native windows
GUI programs and DLL's. GUI programs and DLL's.
Most of the features pointed out by Fabrice Bellard for the Most of the features pointed out by Fabrice Bellard for the
original version are still valid, i.e: original version are still valid, i.e:
- SMALL! The package with ~400kb includes a complete C-compiler - SMALL! The package with ~400kb includes a complete C-compiler
with header files for console and GUI applications. with header files for console and GUI applications.
- With the -run switch you can run C-sources without any - With the -run switch you can run C-sources without any
linking directly from the command line. linking directly from the command line.
- TCC can of course compile itself. - TCC can of course compile itself.
Installation: Installation:
------------- -------------
Just unzip the package to a directory anywhere on your computer. Just unzip the package to a directory anywhere on your computer.
Examples: Examples:
--------- ---------
For the 'Fibonacci' console example type from the command line: For the 'Fibonacci' console example type from the command line:
tcc examples\fib.c tcc examples\fib.c
For the 'Hello Windows' GUI example: For the 'Hello Windows' GUI example:
tcc examples\hello_win.c tcc examples\hello_win.c
For the 'Hello DLL' example: For the 'Hello DLL' example:
tcc -shared examples\dll.c tcc -shared examples\dll.c
tcc examples\hello_dll.c examples\dll.def tcc examples\hello_dll.c examples\dll.def
Import Definitions: Import Definitions:
------------------- -------------------
TinyCC-PE searches and reads import definition files similar TinyCC-PE searches and reads import definition files similar
to libraries. to libraries.
The included 'tiny_impdef' program may be used to make .def files The included 'tiny_impdef' program may be used to make .def files
for any DLL, e.g for an 'opengl32.def': for any DLL, e.g for an 'opengl32.def':
tiny_impdef.exe opengl32.dll tiny_impdef.exe opengl32.dll
or to the same effect: or to the same effect:
tcc -lkernel32 -run tiny_impdef.c opengl32.dll tcc -lkernel32 -run tiny_impdef.c opengl32.dll
Header Files: Header Files:
------------- -------------
The system header files, except '_mingw.h', are from the The system header files, except '_mingw.h', are from the
2.0 mingw distribution. See also: http://www.mingw.org/ 2.0 mingw distribution. See also: http://www.mingw.org/
Compile TCC: Compile TCC:
------------ ------------
With TCC itself just say: With TCC itself just say:
tcc src\tcc.c -lkernel32 -o tcc.new.exe tcc src\tcc.c -lkernel32 -o tcc.new.exe
Other compilers like mingw-gcc or msvc work as well. Other compilers like mingw-gcc or msvc work as well.
To make libtcc1.a, you need 'ar' from the mingw binutils. To make libtcc1.a, you need 'ar' from the mingw binutils.
Documentation and License: Documentation and License:
-------------------------- --------------------------
TCC is distributed under the GNU Lesser General Public License TCC is distributed under the GNU Lesser General Public License
(see COPYING file). (see COPYING file).
Please read the original tcc-doc.html to have all the features Please read the original tcc-doc.html to have all the features
of TCC. Also visit: http://fabrice.bellard.free.fr/tcc/ of TCC. Also visit: http://fabrice.bellard.free.fr/tcc/
-------------------------------------------- --------------------------------------------
09.Apr.2005 - grischka@users.sourceforge.net 09.Apr.2005 - grischka@users.sourceforge.net