aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rw-r--r--lib/Makefile2
-rw-r--r--libtcc.c3
-rw-r--r--tccpe.c25
-rw-r--r--tccrun.c1
-rw-r--r--tests/tests2/Makefile10
-rw-r--r--win32/build-tcc.bat10
-rw-r--r--win32/lib/crt1.c23
-rw-r--r--win32/lib/crt1w.c3
-rw-r--r--win32/lib/wincrt1.c21
-rw-r--r--win32/lib/wincrt1w.c3
11 files changed, 55 insertions, 47 deletions
diff --git a/Changelog b/Changelog
index 6928536..a8928fc 100644
--- a/Changelog
+++ b/Changelog
@@ -17,6 +17,7 @@ Platforms:
- provide a runtime library for ARM (Thomas Preud'homme)
- many x86-64 ABI fixes incl. XMM register passing and tests (James Lyon)
- ABI tests with native compiler using libtcc (James Lyon)
+- UNICODE startup code supports wmain and wWinMain (YX Hao)
Features:
- VLA (variable length array) improved (James Lyon, Pip Cet)
diff --git a/lib/Makefile b/lib/Makefile
index 9596cbb..4cc8093 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -41,7 +41,7 @@ I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
ARM_O = libtcc1.o armeabi.o alloca-arm.o
ARM64_O = lib-arm64.o
-WIN32_O = crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
+WIN32_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o
ifeq "$(TARGET)" "i386-win32"
OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O))
diff --git a/libtcc.c b/libtcc.c
index f1bbc6c..afcaae7 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -744,9 +744,6 @@ LIBTCCAPI TCCState *tcc_new(void)
#ifdef TCC_TARGET_I386
s->seg_size = 32;
#endif
-#ifdef TCC_IS_NATIVE
- s->runtime_main = "main";
-#endif
/* enable this if you want symbols with leading underscore on windows: */
#if 0 /* def TCC_TARGET_PE */
s->leading_underscore = 1;
diff --git a/tccpe.c b/tccpe.c
index 8bb3d85..cf2e475 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -358,6 +358,7 @@ struct pe_info {
int type;
DWORD sizeofheaders;
ADDR3264 imagebase;
+ const char *start_symbol;
DWORD start_addr;
DWORD imp_offs;
DWORD imp_size;
@@ -638,7 +639,6 @@ static int pe_write(struct pe_info *pe)
switch (si->cls) {
case sec_text:
pe_header.opthdr.BaseOfCode = addr;
- pe_header.opthdr.AddressOfEntryPoint = addr + pe->start_addr;
break;
case sec_data:
@@ -700,6 +700,7 @@ static int pe_write(struct pe_info *pe)
//pe_header.filehdr.TimeDateStamp = time(NULL);
pe_header.filehdr.NumberOfSections = pe->sec_count;
+ pe_header.opthdr.AddressOfEntryPoint = pe->start_addr;
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
pe_header.opthdr.ImageBase = pe->imagebase;
pe_header.opthdr.Subsystem = pe->subsystem;
@@ -1309,6 +1310,9 @@ static int pe_check_symbols(struct pe_info *pe)
}
not_found:
+ if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
+ /* STB_WEAK undefined symbols are accepted */
+ continue;
tcc_error_noabort("undefined symbol '%s'", name);
ret = -1;
@@ -1793,8 +1797,9 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
++start_symbol;
/* grab the startup code from libtcc1 */
- /* only (PE_Dll == pe_type) doesn't need it,
- (TCC_OUTPUT_MEMORY == s1->output_type && PE_Dll == pe_type) is illegal */
+#ifdef TCC_IS_NATIVE
+ if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
+#endif
set_elf_sym(symtab_section,
0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
@@ -1817,16 +1822,10 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
}
}
- if (TCC_OUTPUT_MEMORY == s1->output_type) {
+ if (TCC_OUTPUT_MEMORY == s1->output_type)
pe_type = PE_RUN;
-#ifdef TCC_IS_NATIVE
- s1->runtime_main = start_symbol;
-#endif
- } else {
- pe->start_addr = (DWORD)(uintptr_t)tcc_get_symbol_err(s1, start_symbol);
- }
-
pe->type = pe_type;
+ pe->start_symbol = start_symbol;
}
static void pe_set_options(TCCState * s1, struct pe_info *pe)
@@ -1905,6 +1904,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
pe_relocate_rva(&pe, s);
}
}
+ pe.start_addr = (DWORD)
+ ((uintptr_t)tcc_get_symbol_err(s1, pe.start_symbol)
+ - pe.imagebase);
if (s1->nb_errors)
ret = -1;
else
@@ -1914,6 +1916,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
#ifdef TCC_IS_NATIVE
pe.thunk = data_section;
pe_build_imports(&pe);
+ s1->runtime_main = pe.start_symbol;
#endif
}
diff --git a/tccrun.c b/tccrun.c
index 18aed61..950ffb0 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -107,6 +107,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
{
int (*prog_main)(int, char **);
+ s1->runtime_main = "main";
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1;
prog_main = tcc_get_symbol_err(s1, s1->runtime_main);
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index bbcb9ab..ef82d2a 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -28,9 +28,6 @@ endif
ifeq (,$(filter i386 x86-64,$(ARCH)))
SKIP += 85_asm-outside-function.test
endif
-ifeq ($(TARGETOS),Windows)
- SKIP += 76_dollars_in_identifiers.test
-endif
# Some tests might need arguments
ARGS =
@@ -42,7 +39,8 @@ NORUN =
42_function_pointer.test : NORUN = true
# Some tests might need different flags
-76_dollars_in_identifiers.test : TCCFLAGS += -fdollars-in-identifiers
+FLAGS =
+76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers
# Filter source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed 's,$(SRC)/,,g'
@@ -57,9 +55,9 @@ all test: $(filter-out $(SKIP),$(TESTS))
@echo Test: $*...
# test -run
@if test -z "$(NORUN)"; then \
- $(TCC) -run $< $(ARGS) $(FILTER) >$*.output 2>&1 || true; \
+ $(TCC) $(FLAGS) -run $< $(ARGS) $(FILTER) >$*.output 2>&1 || true; \
else \
- $(TCC) $< -o ./$*.exe $(FILTER) >$*.output 2>&1; \
+ $(TCC) $(FLAGS) $< -o ./$*.exe $(FILTER) >$*.output 2>&1; \
./$*.exe $(ARGS) >>$*.output 2>&1 || true; \
fi
@diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output $*.exe
diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat
index 8da1404..daf5a12 100644
--- a/win32/build-tcc.bat
+++ b/win32/build-tcc.bat
@@ -137,12 +137,12 @@ copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
%CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX%
:libtcc1.a
-@set O1=libtcc1.o crt1.o wincrt1.o crt1_w.o wincrt1_w.o dllcrt1.o dllmain.o chkstk.o bcheck.o
+@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o
.\tcc -m32 %D32% -c ../lib/libtcc1.c
.\tcc -m32 %D32% -c lib/crt1.c
-.\tcc -m32 %D32% -c lib/crt1.c -D_UNICODE -DUNICODE -o crt1_w.o
+.\tcc -m32 %D32% -c lib/crt1w.c
.\tcc -m32 %D32% -c lib/wincrt1.c
-.\tcc -m32 %D32% -c lib/wincrt1.c -D_UNICODE -DUNICODE -o wincrt1_w.o
+.\tcc -m32 %D32% -c lib/wincrt1w.c
.\tcc -m32 %D32% -c lib/dllcrt1.c
.\tcc -m32 %D32% -c lib/dllmain.c
.\tcc -m32 %D32% -c lib/chkstk.S
@@ -153,9 +153,9 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
@if errorlevel 1 goto :the_end
.\tcc -m64 %D64% -c ../lib/libtcc1.c
.\tcc -m64 %D64% -c lib/crt1.c
-.\tcc -m64 %D64% -c lib/crt1.c -D_UNICODE -DUNICODE -o crt1_w.o
+.\tcc -m64 %D64% -c lib/crt1w.c
.\tcc -m64 %D64% -c lib/wincrt1.c
-.\tcc -m64 %D64% -c lib/wincrt1.c -D_UNICODE -DUNICODE -o wincrt1_w.o
+.\tcc -m64 %D64% -c lib/wincrt1w.c
.\tcc -m64 %D64% -c lib/dllcrt1.c
.\tcc -m64 %D64% -c lib/dllmain.c
.\tcc -m64 %D64% -c lib/chkstk.S
diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c
index 1e2bd17..a9b1a30 100644
--- a/win32/lib/crt1.c
+++ b/win32/lib/crt1.c
@@ -65,24 +65,23 @@ void _tstart(void)
exit(ret);
}
-void _runtmain(int argc0, /* as tcc passed in */ char **argv0)
+int _runtmain(int argc, /* as tcc passed in */ char **argv)
{
- __TRY__
- int argc, ret;
- _TCHAR **argv;
- _TCHAR **env;
- _startupinfo start_info;
+#ifdef UNICODE
+ int wargc;
+ _TCHAR **wargv, **wenv;
+ _startupinfo start_info = {0};
- __set_app_type(_CONSOLE_APP);
+ __tgetmainargs(&wargc, &wargv, &wenv, _dowildcard, &start_info);
+ if (argc < wargc)
+ wargv += wargc - argc;
+#define argv wargv
+#endif
#ifdef __i386
_controlfp(_PC_53, _MCW_PC);
#endif
-
- start_info.newmode = 0;
- __tgetmainargs( &argc, &argv, &env, _dowildcard, &start_info);
- ret = _tmain(argc0, argv + argc - argc0, env);
- exit(ret);
+ return _tmain(argc, argv, NULL);
}
// =============================================
diff --git a/win32/lib/crt1w.c b/win32/lib/crt1w.c
new file mode 100644
index 0000000..2b8bbc8
--- /dev/null
+++ b/win32/lib/crt1w.c
@@ -0,0 +1,3 @@
+#define _UNICODE 1
+#define UNICODE 1
+#include "crt1.c"
diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c
index 06f42f0..a4197bb 100644
--- a/win32/lib/wincrt1.c
+++ b/win32/lib/wincrt1.c
@@ -68,22 +68,25 @@ int _twinstart(void)
exit(ret);
}
-int _runtwinmain(int argc0, /* as tcc passed in */ char **argv0)
+int _runtwinmain(int argc, /* as tcc passed in */ char **argv)
{
_TCHAR *szCmd, *p;
- int argc;
- _TCHAR **argv;
- _TCHAR **env;
- _startupinfo start_info;
+#ifdef UNICODE
+ int wargc;
+ _TCHAR **wargv, **wenv;
+ _startupinfo start_info = {0};
- start_info.newmode = 0;
- __tgetmainargs(&argc, &argv, &env, 0, &start_info);
+ __tgetmainargs(&wargc, &wargv, &wenv, 0, &start_info);
+ if (argc < wargc)
+ wargv += wargc - argc;
+#define argv wargv
+#endif
p = GetCommandLine();
szCmd = NULL;
- if (argc0 > 1)
- szCmd = _tcsstr(p, argv[argc - argc0 + 1]);
+ if (argc > 1)
+ szCmd = _tcsstr(p, argv[1]);
if (NULL == szCmd)
szCmd = __T("");
else if (szCmd > p && szCmd[-1] == __T('\"'))
diff --git a/win32/lib/wincrt1w.c b/win32/lib/wincrt1w.c
new file mode 100644
index 0000000..a7d349e
--- /dev/null
+++ b/win32/lib/wincrt1w.c
@@ -0,0 +1,3 @@
+#define _UNICODE 1
+#define UNICODE 1
+#include "wincrt1.c"