mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
tcctools.c: integrate tiny_libmaker/_impdef
usage: tcc -ar [rcsv] lib files... tcc -impdef lib.dll [-v] [-o lib.def] also: - support more files with -c: tcc -c f1.c f2.c ... - fix a bug which caused tcc f1.c f2.S to produce no asm - allow tcc -ar @listfile too - change prototype: _void_ tcc_set_options(...) - apply -Wl,-whole-archive when a librariy is given as libxxx.a also (not just for -lxxx)
This commit is contained in:
parent
f34b1feaca
commit
2d3b9559bf
@ -7,6 +7,7 @@ User interface:
|
|||||||
- -mms-bitfields option (David Mertens)
|
- -mms-bitfields option (David Mertens)
|
||||||
- -include <file> option (Michael Matz)
|
- -include <file> option (Michael Matz)
|
||||||
- @listfile support (Vlad Vissoultchev)
|
- @listfile support (Vlad Vissoultchev)
|
||||||
|
- tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka)
|
||||||
- CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support
|
- CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support
|
||||||
(Andrew Aladjev, Urs Janssen)
|
(Andrew Aladjev, Urs Janssen)
|
||||||
|
|
||||||
|
20
Makefile
20
Makefile
@ -28,6 +28,7 @@ LIBS =
|
|||||||
ifdef CONFIG_WIN32
|
ifdef CONFIG_WIN32
|
||||||
ifneq ($(DISABLE_STATIC),no)
|
ifneq ($(DISABLE_STATIC),no)
|
||||||
LIBTCC = libtcc.dll
|
LIBTCC = libtcc.dll
|
||||||
|
LIBTCCDEF = libtcc.def
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
LIBS=-lm
|
LIBS=-lm
|
||||||
@ -82,7 +83,7 @@ ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CRO
|
|||||||
ARM64_CROSS = arm64-tcc$(EXESUF)
|
ARM64_CROSS = arm64-tcc$(EXESUF)
|
||||||
C67_CROSS = c67-tcc$(EXESUF)
|
C67_CROSS = c67-tcc$(EXESUF)
|
||||||
|
|
||||||
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
||||||
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
||||||
I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
|
I386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h
|
||||||
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
|
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
|
||||||
@ -94,7 +95,6 @@ ARM64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
|
|||||||
C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
|
C67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
|
||||||
|
|
||||||
ifdef CONFIG_WIN32
|
ifdef CONFIG_WIN32
|
||||||
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
|
|
||||||
ifeq ($(ARCH),x86-64)
|
ifeq ($(ARCH),x86-64)
|
||||||
NATIVE_FILES=$(WIN64_FILES)
|
NATIVE_FILES=$(WIN64_FILES)
|
||||||
PROGS_CROSS=$(WIN32_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS)
|
PROGS_CROSS=$(WIN32_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS)
|
||||||
@ -124,11 +124,7 @@ NATIVE_FILES=$(ARM64_FILES)
|
|||||||
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS)
|
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGETOS),Darwin)
|
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
|
||||||
PROGS += tiny_libmaker$(EXESUF)
|
|
||||||
endif
|
|
||||||
|
|
||||||
TCCLIBS = $(LIBTCC1) $(LIBTCC)
|
|
||||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||||
|
|
||||||
ifdef CONFIG_CROSS
|
ifdef CONFIG_CROSS
|
||||||
@ -179,7 +175,7 @@ $(ARM64_CROSS): $(ARM64_FILES)
|
|||||||
|
|
||||||
# libtcc generation and test
|
# libtcc generation and test
|
||||||
ifndef ONE_SOURCE
|
ifndef ONE_SOURCE
|
||||||
LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
|
LIBTCC_OBJ = $(filter-out tcc.o tcctools.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
|
||||||
LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))
|
LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))
|
||||||
else
|
else
|
||||||
LIBTCC_OBJ = libtcc.o
|
LIBTCC_OBJ = libtcc.o
|
||||||
@ -187,6 +183,8 @@ LIBTCC_INC = $(NATIVE_FILES)
|
|||||||
libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
|
libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
tcc.o : tcctools.c
|
||||||
|
|
||||||
$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC)
|
$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC)
|
||||||
$(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS)
|
$(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS)
|
||||||
|
|
||||||
@ -199,9 +197,11 @@ libtcc.so: $(LIBTCC_OBJ)
|
|||||||
libtcc.so: CFLAGS+=-fPIC
|
libtcc.so: CFLAGS+=-fPIC
|
||||||
|
|
||||||
# windows : libtcc.dll
|
# windows : libtcc.dll
|
||||||
libtcc.dll : $(LIBTCC_OBJ) tiny_impdef$(EXESUF)
|
libtcc.dll : $(LIBTCC_OBJ)
|
||||||
$(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS)
|
$(CC) -shared $(LIBTCC_OBJ) -o $@ $(LDFLAGS)
|
||||||
./tiny_impdef $@
|
|
||||||
|
libtcc.def : libtcc.dll tcc$(EXESUF)
|
||||||
|
./tcc$(EXESUF) -impdef $< -o $@
|
||||||
|
|
||||||
libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL
|
libtcc.dll : NATIVE_DEFINES += -DLIBTCC_AS_DLL
|
||||||
|
|
||||||
|
1
TODO
1
TODO
@ -2,6 +2,7 @@ TODO list:
|
|||||||
|
|
||||||
Bugs:
|
Bugs:
|
||||||
|
|
||||||
|
- i386 fastcall is mostly wrong
|
||||||
- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
|
- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
|
||||||
optimized gcc/msc code
|
optimized gcc/msc code
|
||||||
- see transparent union pb in /urs/include/sys/socket.h
|
- see transparent union pb in /urs/include/sys/socket.h
|
||||||
|
22
conftest.c
22
conftest.c
@ -1,9 +1,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* Define architecture */
|
/* Define architecture */
|
||||||
#if defined(__i386__)
|
#if defined(__i386__) || defined _M_IX86
|
||||||
# define TRIPLET_ARCH "i386"
|
# define TRIPLET_ARCH "i386"
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__) || defined _M_AMD64
|
||||||
# define TRIPLET_ARCH "x86_64"
|
# define TRIPLET_ARCH "x86_64"
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
# define TRIPLET_ARCH "arm"
|
# define TRIPLET_ARCH "arm"
|
||||||
@ -18,6 +18,8 @@
|
|||||||
# define TRIPLET_OS "linux"
|
# define TRIPLET_OS "linux"
|
||||||
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||||
# define TRIPLET_OS "kfreebsd"
|
# define TRIPLET_OS "kfreebsd"
|
||||||
|
#elif defined _WIN32
|
||||||
|
# define TRIPLET_OS "win32"
|
||||||
#elif !defined (__GNU__)
|
#elif !defined (__GNU__)
|
||||||
# define TRIPLET_OS "unknown"
|
# define TRIPLET_OS "unknown"
|
||||||
#endif
|
#endif
|
||||||
@ -33,7 +35,9 @@
|
|||||||
# define TRIPLET_ABI "gnu"
|
# define TRIPLET_ABI "gnu"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNU__
|
#if defined _WIN32
|
||||||
|
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS
|
||||||
|
#elif defined __GNU__
|
||||||
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
|
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
|
||||||
#else
|
#else
|
||||||
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
|
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
|
||||||
@ -59,6 +63,13 @@ int main(int argc, char *argv[])
|
|||||||
case 'v':
|
case 'v':
|
||||||
printf("%d\n", __GNUC__);
|
printf("%d\n", __GNUC__);
|
||||||
break;
|
break;
|
||||||
|
#elif defined __TINYC__
|
||||||
|
case 'v':
|
||||||
|
puts("0");
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
printf("%d\n", __TINYC__);
|
||||||
|
break;
|
||||||
#else
|
#else
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -68,9 +79,8 @@ int main(int argc, char *argv[])
|
|||||||
case 't':
|
case 't':
|
||||||
puts(TRIPLET);
|
puts(TRIPLET);
|
||||||
break;
|
break;
|
||||||
case -1:
|
|
||||||
/* to test -Wno-unused-result */
|
default:
|
||||||
fread(NULL, 1, 1, NULL);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
30
lib/Makefile
30
lib/Makefile
@ -20,9 +20,6 @@ ifndef TARGET
|
|||||||
TARGET = x86_64
|
TARGET = x86_64
|
||||||
else ifeq ($(ARCH),arm)
|
else ifeq ($(ARCH),arm)
|
||||||
TARGET = arm
|
TARGET = arm
|
||||||
# using gcc, need asm
|
|
||||||
XCC = $(CC)
|
|
||||||
XFLAGS = $(CFLAGS) -fPIC
|
|
||||||
else ifeq ($(ARCH),arm64)
|
else ifeq ($(ARCH),arm64)
|
||||||
TARGET = arm64
|
TARGET = arm64
|
||||||
endif
|
endif
|
||||||
@ -37,6 +34,9 @@ cross : $(DIR)/libtcc1.a
|
|||||||
native : TCC = $(TOP)/tcc$(EXESUF)
|
native : TCC = $(TOP)/tcc$(EXESUF)
|
||||||
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
|
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
|
||||||
|
|
||||||
|
XCC = $(TCC) -B$(TOPSRC)
|
||||||
|
XAR = $(TCC) -ar
|
||||||
|
|
||||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
|
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)
|
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
|
||||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o
|
ARM_O = libtcc1.o armeabi.o alloca-arm.o
|
||||||
@ -47,53 +47,43 @@ ifeq "$(TARGET)" "i386-win32"
|
|||||||
OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O))
|
OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O))
|
||||||
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
|
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
|
||||||
XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
||||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
|
||||||
else ifeq "$(TARGET)" "x86_64-win32"
|
else ifeq "$(TARGET)" "x86_64-win32"
|
||||||
OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O))
|
OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O))
|
||||||
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
|
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
|
||||||
XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
|
||||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
|
||||||
else ifeq "$(TARGET)" "i386"
|
else ifeq "$(TARGET)" "i386"
|
||||||
OBJ = $(addprefix $(DIR)/,$(I386_O))
|
OBJ = $(addprefix $(DIR)/,$(I386_O))
|
||||||
TGT = -DTCC_TARGET_I386
|
TGT = -DTCC_TARGET_I386
|
||||||
XCC ?= $(TCC) -B$(TOPSRC)
|
|
||||||
else ifeq "$(TARGET)" "x86_64"
|
else ifeq "$(TARGET)" "x86_64"
|
||||||
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
|
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
|
||||||
TGT = -DTCC_TARGET_X86_64
|
TGT = -DTCC_TARGET_X86_64
|
||||||
XCC ?= $(TCC) -B$(TOPSRC)
|
|
||||||
else ifeq "$(TARGET)" "arm"
|
else ifeq "$(TARGET)" "arm"
|
||||||
OBJ = $(addprefix $(DIR)/,$(ARM_O))
|
OBJ = $(addprefix $(DIR)/,$(ARM_O))
|
||||||
TGT = -DTCC_TARGET_ARM
|
TGT = -DTCC_TARGET_ARM
|
||||||
XCC ?= $(TCC) -B$(TOPSRC)
|
# using gcc, need asm
|
||||||
|
XCC = $(CC)
|
||||||
|
XFLAGS = $(CFLAGS) -fPIC
|
||||||
|
XAR = $(AR)
|
||||||
else ifeq "$(TARGET)" "arm64"
|
else ifeq "$(TARGET)" "arm64"
|
||||||
OBJ = $(addprefix $(DIR)/,$(ARM64_O))
|
OBJ = $(addprefix $(DIR)/,$(ARM64_O))
|
||||||
TGT = -DTCC_TARGET_ARM64
|
TGT = -DTCC_TARGET_ARM64
|
||||||
XCC ?= $(TCC) -B$(TOPSRC)
|
|
||||||
else
|
else
|
||||||
$(error libtcc1.a not supported on target '$(TARGET)')
|
$(error libtcc1.a not supported on target '$(TARGET)')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGETOS),Darwin)
|
ifeq ($(TARGETOS),Darwin)
|
||||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
|
||||||
XFLAGS += -D_ANSI_SOURCE
|
XFLAGS += -D_ANSI_SOURCE
|
||||||
BCHECK_O =
|
BCHECK_O =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef XAR
|
$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ)
|
||||||
AR = $(XAR)
|
$(XAR) rcs $@ $(OBJ)
|
||||||
endif
|
|
||||||
|
|
||||||
$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
|
|
||||||
$(AR) rcs $@ $(OBJ)
|
|
||||||
$(DIR)/%.o : %.c
|
$(DIR)/%.o : %.c
|
||||||
$(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
|
$(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
|
||||||
$(DIR)/%.o : %.S
|
$(DIR)/%.o : %.S
|
||||||
$(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
|
$(XCC) -c $< -o $@ $(TGT) $(XFLAGS)
|
||||||
# windows : utilities
|
|
||||||
$(DIR)/tiny_%$(EXESUF) : $(TOPSRC)/win32/tools/tiny_%.c
|
|
||||||
$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(TGT)
|
|
||||||
|
|
||||||
$(OBJ) $(XAR) : $(DIR)/exists
|
$(OBJ) : $(DIR)/exists
|
||||||
|
|
||||||
%/exists :
|
%/exists :
|
||||||
mkdir -p $(DIR)
|
mkdir -p $(DIR)
|
||||||
|
212
libtcc.c
212
libtcc.c
@ -239,7 +239,7 @@ PUB_FUNC char *tcc_strdup(const char *str)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC void tcc_memstats(int bench)
|
PUB_FUNC void tcc_memcheck(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC void tcc_memstats(int bench)
|
PUB_FUNC void tcc_memcheck(void)
|
||||||
{
|
{
|
||||||
if (mem_cur_size) {
|
if (mem_cur_size) {
|
||||||
mem_debug_header_t *header = mem_debug_chain;
|
mem_debug_header_t *header = mem_debug_chain;
|
||||||
@ -393,8 +393,7 @@ PUB_FUNC void tcc_memstats(int bench)
|
|||||||
#if MEM_DEBUG-0 == 2
|
#if MEM_DEBUG-0 == 2
|
||||||
exit(2);
|
exit(2);
|
||||||
#endif
|
#endif
|
||||||
} else if (bench)
|
}
|
||||||
fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size);
|
|
||||||
}
|
}
|
||||||
#endif /* MEM_DEBUG */
|
#endif /* MEM_DEBUG */
|
||||||
|
|
||||||
@ -435,7 +434,7 @@ ST_FUNC void dynarray_reset(void *pp, int *n)
|
|||||||
*(void**)pp = NULL;
|
*(void**)pp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char *in)
|
static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
do {
|
do {
|
||||||
@ -878,18 +877,14 @@ LIBTCCAPI TCCState *tcc_new(void)
|
|||||||
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
|
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
|
||||||
"name proto __asm__ (#alias) __THROW");
|
"name proto __asm__ (#alias) __THROW");
|
||||||
# endif
|
# endif
|
||||||
#endif /* ndef TCC_TARGET_PE */
|
|
||||||
|
|
||||||
/* Some GCC builtins that are simple to express as macros. */
|
/* Some GCC builtins that are simple to express as macros. */
|
||||||
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
|
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
|
||||||
|
#endif /* ndef TCC_TARGET_PE */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI void tcc_delete(TCCState *s1)
|
LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||||
{
|
{
|
||||||
int bench = s1->do_bench;
|
|
||||||
|
|
||||||
tcc_cleanup();
|
tcc_cleanup();
|
||||||
|
|
||||||
/* free sections */
|
/* free sections */
|
||||||
@ -915,6 +910,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
|||||||
dynarray_reset(&s1->files, &s1->nb_files);
|
dynarray_reset(&s1->files, &s1->nb_files);
|
||||||
dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
|
dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
|
||||||
dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
|
dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
|
||||||
|
dynarray_reset(&s1->argv, &s1->argc);
|
||||||
|
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
/* free runtime memory */
|
/* free runtime memory */
|
||||||
@ -923,7 +919,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
|||||||
|
|
||||||
tcc_free(s1);
|
tcc_free(s1);
|
||||||
if (0 == --nb_states)
|
if (0 == --nb_states)
|
||||||
tcc_memstats(bench);
|
tcc_memcheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
@ -965,7 +961,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
|||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
/* paths for crt objects */
|
/* paths for crt objects */
|
||||||
tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||||
/* add libc crt1/crti objects */
|
/* add libc crt1/crti objects */
|
||||||
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
|
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
|
||||||
!s->nostdlib) {
|
!s->nostdlib) {
|
||||||
@ -979,13 +975,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
|||||||
|
|
||||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
|
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
|
||||||
{
|
{
|
||||||
tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);
|
tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
||||||
{
|
{
|
||||||
tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
|
tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1106,7 +1102,7 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
|
|||||||
|
|
||||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
|
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
|
||||||
{
|
{
|
||||||
tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);
|
tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1440,6 +1436,7 @@ typedef struct TCCOption {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCC_OPTION_HELP,
|
TCC_OPTION_HELP,
|
||||||
|
TCC_OPTION_v,
|
||||||
TCC_OPTION_I,
|
TCC_OPTION_I,
|
||||||
TCC_OPTION_D,
|
TCC_OPTION_D,
|
||||||
TCC_OPTION_U,
|
TCC_OPTION_U,
|
||||||
@ -1480,13 +1477,14 @@ enum {
|
|||||||
TCC_OPTION_pedantic,
|
TCC_OPTION_pedantic,
|
||||||
TCC_OPTION_pthread,
|
TCC_OPTION_pthread,
|
||||||
TCC_OPTION_run,
|
TCC_OPTION_run,
|
||||||
TCC_OPTION_v,
|
|
||||||
TCC_OPTION_w,
|
TCC_OPTION_w,
|
||||||
TCC_OPTION_pipe,
|
TCC_OPTION_pipe,
|
||||||
TCC_OPTION_E,
|
TCC_OPTION_E,
|
||||||
TCC_OPTION_MD,
|
TCC_OPTION_MD,
|
||||||
TCC_OPTION_MF,
|
TCC_OPTION_MF,
|
||||||
TCC_OPTION_x
|
TCC_OPTION_x,
|
||||||
|
TCC_OPTION_ar,
|
||||||
|
TCC_OPTION_impdef
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TCC_OPTION_HAS_ARG 0x0001
|
#define TCC_OPTION_HAS_ARG 0x0001
|
||||||
@ -1496,6 +1494,7 @@ static const TCCOption tcc_options[] = {
|
|||||||
{ "h", TCC_OPTION_HELP, 0 },
|
{ "h", TCC_OPTION_HELP, 0 },
|
||||||
{ "-help", TCC_OPTION_HELP, 0 },
|
{ "-help", TCC_OPTION_HELP, 0 },
|
||||||
{ "?", TCC_OPTION_HELP, 0 },
|
{ "?", TCC_OPTION_HELP, 0 },
|
||||||
|
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||||
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
|
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
|
||||||
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
|
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
|
||||||
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
|
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
|
||||||
@ -1542,13 +1541,16 @@ static const TCCOption tcc_options[] = {
|
|||||||
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
||||||
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
||||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
||||||
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "w", TCC_OPTION_w, 0 },
|
{ "w", TCC_OPTION_w, 0 },
|
||||||
{ "pipe", TCC_OPTION_pipe, 0},
|
{ "pipe", TCC_OPTION_pipe, 0},
|
||||||
{ "E", TCC_OPTION_E, 0},
|
{ "E", TCC_OPTION_E, 0},
|
||||||
{ "MD", TCC_OPTION_MD, 0},
|
{ "MD", TCC_OPTION_MD, 0},
|
||||||
{ "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
|
{ "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
|
||||||
{ "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
|
{ "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
|
||||||
|
{ "ar", TCC_OPTION_ar, 0},
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
{ "impdef", TCC_OPTION_impdef, 0},
|
||||||
|
#endif
|
||||||
{ NULL, 0, 0 },
|
{ NULL, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1595,58 +1597,106 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype
|
|||||||
{
|
{
|
||||||
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
|
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
|
||||||
f->type = filetype;
|
f->type = filetype;
|
||||||
|
f->alacarte = s->alacarte_link;
|
||||||
strcpy(f->name, filename);
|
strcpy(f->name, filename);
|
||||||
dynarray_add(&s->files, &s->nb_files, f);
|
dynarray_add(&s->files, &s->nb_files, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read list file */
|
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
|
||||||
static void args_parser_listfile(TCCState *s, const char *filename)
|
|
||||||
{
|
{
|
||||||
int fd;
|
int ret = 0, q, c;
|
||||||
|
CString str;
|
||||||
|
for(;;) {
|
||||||
|
while (c = (unsigned char)*r, c && c <= ' ')
|
||||||
|
++r;
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
q = 0;
|
||||||
|
cstr_new(&str);
|
||||||
|
while (c = (unsigned char)*r, c) {
|
||||||
|
++r;
|
||||||
|
if (c == '\\' && (*r == '"' || *r == '\\')) {
|
||||||
|
c = *r++;
|
||||||
|
} else if (c == '"') {
|
||||||
|
q = !q;
|
||||||
|
continue;
|
||||||
|
} else if (q == 0 && c <= ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cstr_ccat(&str, c);
|
||||||
|
}
|
||||||
|
cstr_ccat(&str, 0);
|
||||||
|
//printf("<%s>\n", str.data), fflush(stdout);
|
||||||
|
dynarray_add(argv, argc, tcc_strdup(str.data));
|
||||||
|
cstr_free(&str);
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read list file */
|
||||||
|
static void args_parser_listfile(TCCState *s,
|
||||||
|
const char *filename, int optind, int *pargc, char ***pargv)
|
||||||
|
{
|
||||||
|
int fd, i;
|
||||||
size_t len;
|
size_t len;
|
||||||
char *p;
|
char *p;
|
||||||
|
int argc = 0;
|
||||||
|
char **argv = NULL;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY | O_BINARY);
|
fd = open(filename, O_RDONLY | O_BINARY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
tcc_error("file '%s' not found", filename);
|
tcc_error("listfile '%s' not found", filename);
|
||||||
|
|
||||||
len = lseek(fd, 0, SEEK_END);
|
len = lseek(fd, 0, SEEK_END);
|
||||||
p = tcc_malloc(len + 1), p[len] = 0;
|
p = tcc_malloc(len + 1), p[len] = 0;
|
||||||
lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd);
|
lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd);
|
||||||
tcc_set_options(s, p);
|
|
||||||
|
for (i = 0; i < *pargc; ++i)
|
||||||
|
if (i == optind)
|
||||||
|
args_parser_make_argv(p, &argc, &argv);
|
||||||
|
else
|
||||||
|
dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i]));
|
||||||
|
|
||||||
tcc_free(p);
|
tcc_free(p);
|
||||||
|
dynarray_reset(&s->argv, &s->argc);
|
||||||
|
*pargc = s->argc = argc, *pargv = s->argv = argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
||||||
{
|
{
|
||||||
const TCCOption *popt;
|
const TCCOption *popt;
|
||||||
const char *optarg, *r;
|
const char *optarg, *r;
|
||||||
const char *run = NULL;
|
const char *run = NULL;
|
||||||
int optind = 0;
|
|
||||||
int x;
|
|
||||||
int last_o = -1;
|
int last_o = -1;
|
||||||
|
int x;
|
||||||
CString linker_arg; /* collect -Wl options */
|
CString linker_arg; /* collect -Wl options */
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
int tool = 0, arg_start = 0, noaction = optind;
|
||||||
|
char **argv = *pargv;
|
||||||
|
int argc = *pargc;
|
||||||
|
|
||||||
cstr_new(&linker_arg);
|
cstr_new(&linker_arg);
|
||||||
|
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
|
r = argv[optind];
|
||||||
r = argv[optind++];
|
|
||||||
|
|
||||||
reparse:
|
|
||||||
if (r[0] == '@' && r[1] != '\0') {
|
if (r[0] == '@' && r[1] != '\0') {
|
||||||
args_parser_listfile(s, r + 1);
|
args_parser_listfile(s, r + 1, optind, &argc, &argv);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
optind++;
|
||||||
|
if (tool) {
|
||||||
|
if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
|
||||||
|
++s->verbose;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
reparse:
|
||||||
if (r[0] != '-' || r[1] == '\0') {
|
if (r[0] != '-' || r[1] == '\0') {
|
||||||
if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */
|
if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */
|
||||||
args_parser_add_file(s, r, s->filetype);
|
args_parser_add_file(s, r, s->filetype);
|
||||||
if (run) {
|
if (run) {
|
||||||
tcc_set_options(s, run);
|
tcc_set_options(s, run);
|
||||||
optind--;
|
arg_start = optind - 1;
|
||||||
/* argv[0] will be this file */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -1675,7 +1725,7 @@ reparse:
|
|||||||
|
|
||||||
switch(popt->index) {
|
switch(popt->index) {
|
||||||
case TCC_OPTION_HELP:
|
case TCC_OPTION_HELP:
|
||||||
return 0;
|
return OPT_HELP;
|
||||||
case TCC_OPTION_I:
|
case TCC_OPTION_I:
|
||||||
tcc_add_include_path(s, optarg);
|
tcc_add_include_path(s, optarg);
|
||||||
break;
|
break;
|
||||||
@ -1693,7 +1743,7 @@ reparse:
|
|||||||
tcc_set_lib_path(s, optarg);
|
tcc_set_lib_path(s, optarg);
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_l:
|
case TCC_OPTION_l:
|
||||||
args_parser_add_file(s, optarg, AFF_TYPE_LIBWH - s->alacarte_link);
|
args_parser_add_file(s, optarg, AFF_TYPE_LIB);
|
||||||
s->nb_libraries++;
|
s->nb_libraries++;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_pthread:
|
case TCC_OPTION_pthread:
|
||||||
@ -1774,9 +1824,6 @@ reparse:
|
|||||||
case TCC_OPTION_nostdlib:
|
case TCC_OPTION_nostdlib:
|
||||||
s->nostdlib = 1;
|
s->nostdlib = 1;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_print_search_dirs:
|
|
||||||
s->print_search_dirs = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_run:
|
case TCC_OPTION_run:
|
||||||
#ifndef TCC_IS_NATIVE
|
#ifndef TCC_IS_NATIVE
|
||||||
tcc_error("-run is not available in a cross compiler");
|
tcc_error("-run is not available in a cross compiler");
|
||||||
@ -1786,6 +1833,7 @@ reparse:
|
|||||||
goto set_output_type;
|
goto set_output_type;
|
||||||
case TCC_OPTION_v:
|
case TCC_OPTION_v:
|
||||||
do ++s->verbose; while (*optarg++ == 'v');
|
do ++s->verbose; while (*optarg++ == 'v');
|
||||||
|
++noaction;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_f:
|
case TCC_OPTION_f:
|
||||||
if (set_flag(s, options_f, optarg) < 0)
|
if (set_flag(s, options_f, optarg) < 0)
|
||||||
@ -1804,12 +1852,13 @@ reparse:
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case TCC_OPTION_m:
|
case TCC_OPTION_m:
|
||||||
if (set_flag(s, options_m, optarg) == 0)
|
if (set_flag(s, options_m, optarg) < 0) {
|
||||||
break;
|
if (x = atoi(optarg), x != 32 && x != 64)
|
||||||
else if (x = atoi(optarg), x == 32 || x == 64)
|
goto unsupported_option;
|
||||||
s->cross_target = x;
|
if (PTR_SIZE != x/8)
|
||||||
else
|
return x;
|
||||||
goto unsupported_option;
|
++noaction;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_W:
|
case TCC_OPTION_W:
|
||||||
if (set_flag(s, options_W, optarg) < 0)
|
if (set_flag(s, options_W, optarg) < 0)
|
||||||
@ -1860,6 +1909,20 @@ reparse:
|
|||||||
case TCC_OPTION_O:
|
case TCC_OPTION_O:
|
||||||
last_o = atoi(optarg);
|
last_o = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case TCC_OPTION_print_search_dirs:
|
||||||
|
x = OPT_PRINT_DIRS;
|
||||||
|
goto extra_action;
|
||||||
|
case TCC_OPTION_impdef:
|
||||||
|
x = OPT_IMPDEF;
|
||||||
|
goto extra_action;
|
||||||
|
case TCC_OPTION_ar:
|
||||||
|
x = OPT_AR;
|
||||||
|
extra_action:
|
||||||
|
arg_start = optind - 1;
|
||||||
|
if (arg_start != noaction)
|
||||||
|
tcc_error("cannot parse %s here", r);
|
||||||
|
tool = x;
|
||||||
|
break;
|
||||||
case TCC_OPTION_traditional:
|
case TCC_OPTION_traditional:
|
||||||
case TCC_OPTION_pedantic:
|
case TCC_OPTION_pedantic:
|
||||||
case TCC_OPTION_pipe:
|
case TCC_OPTION_pipe:
|
||||||
@ -1873,53 +1936,32 @@ unsupported_option:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_o > 0)
|
if (last_o > 0)
|
||||||
tcc_define_symbol(s, "__OPTIMIZE__", NULL);
|
tcc_define_symbol(s, "__OPTIMIZE__", NULL);
|
||||||
|
|
||||||
if (linker_arg.size) {
|
if (linker_arg.size) {
|
||||||
r = linker_arg.data;
|
r = linker_arg.data;
|
||||||
goto arg_err;
|
goto arg_err;
|
||||||
}
|
}
|
||||||
|
*pargc = argc - arg_start;
|
||||||
return optind;
|
*pargv = argv + arg_start;
|
||||||
|
if (tool)
|
||||||
|
return tool;
|
||||||
|
if (optind != noaction)
|
||||||
|
return 0;
|
||||||
|
if (s->verbose == 2)
|
||||||
|
return OPT_PRINT_DIRS;
|
||||||
|
if (s->verbose)
|
||||||
|
return OPT_V;
|
||||||
|
return OPT_HELP;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
|
LIBTCCAPI void tcc_set_options(TCCState *s, const char *r)
|
||||||
{
|
{
|
||||||
char **argv;
|
char **argv = NULL;
|
||||||
int argc;
|
int argc = 0;
|
||||||
int ret, q, c;
|
args_parser_make_argv(r, &argc, &argv);
|
||||||
CString str;
|
tcc_parse_args(s, &argc, &argv, 0);
|
||||||
|
|
||||||
argc = 0, argv = NULL;
|
|
||||||
for(;;) {
|
|
||||||
while (c = (unsigned char)*r, c && c <= ' ')
|
|
||||||
++r;
|
|
||||||
if (c == 0)
|
|
||||||
break;
|
|
||||||
q = 0;
|
|
||||||
cstr_new(&str);
|
|
||||||
while (c = (unsigned char)*r, c) {
|
|
||||||
++r;
|
|
||||||
if (c == '\\' && (*r == '"' || *r == '\\')) {
|
|
||||||
c = *r++;
|
|
||||||
} else if (c == '"') {
|
|
||||||
q = !q;
|
|
||||||
continue;
|
|
||||||
} else if (q == 0 && c <= ' ') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cstr_ccat(&str, c);
|
|
||||||
}
|
|
||||||
cstr_ccat(&str, 0);
|
|
||||||
//printf("<%s>\n", str.data), fflush(stdout);
|
|
||||||
dynarray_add(&argv, &argc, tcc_strdup(str.data));
|
|
||||||
cstr_free(&str);
|
|
||||||
}
|
|
||||||
ret = tcc_parse_args(s, argc, argv);
|
|
||||||
dynarray_reset(&argv, &argc);
|
dynarray_reset(&argv, &argc);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
|
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
|
||||||
@ -1928,11 +1970,15 @@ PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time)
|
|||||||
total_time = 1;
|
total_time = 1;
|
||||||
if (total_bytes < 1)
|
if (total_bytes < 1)
|
||||||
total_bytes = 1;
|
total_bytes = 1;
|
||||||
fprintf(stderr, "%d idents, %d lines, %d bytes, %0.3f s, %u lines/s, %0.1f MB/s\n",
|
fprintf(stderr, "* %d idents, %d lines, %d bytes\n"
|
||||||
|
"* %0.3f s, %u lines/s, %0.1f MB/s\n",
|
||||||
tok_ident - TOK_IDENT, total_lines, total_bytes,
|
tok_ident - TOK_IDENT, total_lines, total_bytes,
|
||||||
(double)total_time/1000,
|
(double)total_time/1000,
|
||||||
(unsigned)total_lines*1000/total_time,
|
(unsigned)total_lines*1000/total_time,
|
||||||
(double)total_bytes/1000/total_time);
|
(double)total_bytes/1000/total_time);
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
fprintf(stderr, "* %d bytes memory used\n", mem_max_size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC void tcc_set_environment(TCCState *s)
|
PUB_FUNC void tcc_set_environment(TCCState *s)
|
||||||
|
2
libtcc.h
2
libtcc.h
@ -27,7 +27,7 @@ LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
|
|||||||
void (*error_func)(void *opaque, const char *msg));
|
void (*error_func)(void *opaque, const char *msg));
|
||||||
|
|
||||||
/* set options as from command line (multiple supported) */
|
/* set options as from command line (multiple supported) */
|
||||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* preprocessor */
|
/* preprocessor */
|
||||||
|
341
tcc.c
341
tcc.c
@ -23,69 +23,7 @@
|
|||||||
#else
|
#else
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "tcctools.c"
|
||||||
static void print_paths(const char *msg, char **paths, int nb_paths)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
|
||||||
for(i = 0; i < nb_paths; i++)
|
|
||||||
printf(" %s\n", paths[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void display_info(TCCState *s, int what)
|
|
||||||
{
|
|
||||||
switch (what) {
|
|
||||||
case 0:
|
|
||||||
printf("tcc version %s ("
|
|
||||||
#ifdef TCC_TARGET_I386
|
|
||||||
"i386"
|
|
||||||
#elif defined TCC_TARGET_X86_64
|
|
||||||
"x86-64"
|
|
||||||
#elif defined TCC_TARGET_C67
|
|
||||||
"C67"
|
|
||||||
#elif defined TCC_TARGET_ARM
|
|
||||||
"ARM"
|
|
||||||
# ifdef TCC_ARM_HARDFLOAT
|
|
||||||
" Hard Float"
|
|
||||||
# endif
|
|
||||||
#elif defined TCC_TARGET_ARM64
|
|
||||||
"AArch64"
|
|
||||||
# ifdef TCC_ARM_HARDFLOAT
|
|
||||||
" Hard Float"
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
" Windows"
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
/* Current Apple OS name as of 2016 */
|
|
||||||
" macOS"
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
||||||
" FreeBSD"
|
|
||||||
#elif defined(__DragonFly__)
|
|
||||||
" DragonFly BSD"
|
|
||||||
#elif defined(__NetBSD__)
|
|
||||||
" NetBSD"
|
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
" OpenBSD"
|
|
||||||
#elif defined(__linux__)
|
|
||||||
" Linux"
|
|
||||||
#else
|
|
||||||
" Unidentified system"
|
|
||||||
#endif
|
|
||||||
")\n", TCC_VERSION);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
printf("install: %s\n", s->tcc_lib_path);
|
|
||||||
/* print_paths("programs", NULL, 0); */
|
|
||||||
print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
|
||||||
print_paths("libraries", s->library_paths, s->nb_library_paths);
|
|
||||||
#ifndef TCC_TARGET_PE
|
|
||||||
print_paths("crt", s->crt_paths, s->nb_crt_paths);
|
|
||||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void help(void)
|
static void help(void)
|
||||||
{
|
{
|
||||||
@ -100,7 +38,8 @@ static void help(void)
|
|||||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
|
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
|
||||||
" -w disable all warnings\n"
|
" -w disable all warnings\n"
|
||||||
" -v show version\n"
|
" -v show version\n"
|
||||||
" -vv show included files (as sole argument: show search paths)\n"
|
" -vv show included files (as sole argument show search paths)\n"
|
||||||
|
" -h show this help\n"
|
||||||
" -bench show compilation statistics\n"
|
" -bench show compilation statistics\n"
|
||||||
"Preprocessor options:\n"
|
"Preprocessor options:\n"
|
||||||
" -Idir add include path 'dir'\n"
|
" -Idir add include path 'dir'\n"
|
||||||
@ -146,115 +85,75 @@ static void help(void)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
" -mno-sse disable floats on x86-64\n"
|
" -mno-sse disable floats on x86-64\n"
|
||||||
|
#endif
|
||||||
|
"Tools:\n"
|
||||||
|
" create library : tcc -ar [rcsv] lib.a files\n"
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
" create .def file : tcc -impdef lib.dll [-v] [-o lib.def]\n"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
static char *str_replace(const char *str, const char *p, const char *r)
|
static void version(void)
|
||||||
{
|
{
|
||||||
const char *s, *s0;
|
printf("tcc version %s ("
|
||||||
char *d, *d0;
|
|
||||||
int sl, pl, rl;
|
|
||||||
|
|
||||||
sl = strlen(str);
|
|
||||||
pl = strlen(p);
|
|
||||||
rl = strlen(r);
|
|
||||||
for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
|
|
||||||
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
|
|
||||||
if (d) {
|
|
||||||
memcpy(d, s0, sl = s - s0), d += sl;
|
|
||||||
memcpy(d, r, rl), d += rl;
|
|
||||||
} else
|
|
||||||
sl += rl - pl;
|
|
||||||
}
|
|
||||||
if (d) {
|
|
||||||
strcpy(d, s0);
|
|
||||||
return d0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int execvp_win32(const char *prog, char **argv)
|
|
||||||
{
|
|
||||||
int ret; char **p;
|
|
||||||
/* replace all " by \" */
|
|
||||||
for (p = argv; *p; ++p)
|
|
||||||
if (strchr(*p, '"'))
|
|
||||||
*p = str_replace(*p, "\"", "\\\"");
|
|
||||||
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
|
||||||
if (-1 == ret)
|
|
||||||
return ret;
|
|
||||||
cwait(&ret, ret, WAIT_CHILD);
|
|
||||||
exit(ret);
|
|
||||||
}
|
|
||||||
#define execvp execvp_win32
|
|
||||||
#endif
|
|
||||||
static void exec_other_tcc(TCCState *s, char **argv, int option)
|
|
||||||
{
|
|
||||||
char child_path[4096], *a0 = argv[0]; const char *target;
|
|
||||||
int l;
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_I386
|
#ifdef TCC_TARGET_I386
|
||||||
case 32: break;
|
"i386"
|
||||||
case 64: target = "x86_64";
|
#elif defined TCC_TARGET_X86_64
|
||||||
#else
|
"x86-64"
|
||||||
case 64: break;
|
#elif defined TCC_TARGET_C67
|
||||||
case 32: target = "i386";
|
"C67"
|
||||||
|
#elif defined TCC_TARGET_ARM
|
||||||
|
"ARM"
|
||||||
|
# ifdef TCC_ARM_HARDFLOAT
|
||||||
|
" Hard Float"
|
||||||
|
# endif
|
||||||
|
#elif defined TCC_TARGET_ARM64
|
||||||
|
"AArch64"
|
||||||
|
# ifdef TCC_ARM_HARDFLOAT
|
||||||
|
" Hard Float"
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
l = tcc_basename(a0) - a0;
|
|
||||||
snprintf(child_path, sizeof child_path,
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
"%.*s%s-win32-tcc"
|
" Windows"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
/* Current Apple OS name as of 2016 */
|
||||||
|
" macOS"
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
" FreeBSD"
|
||||||
|
#elif defined(__DragonFly__)
|
||||||
|
" DragonFly BSD"
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
" NetBSD"
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
" OpenBSD"
|
||||||
|
#elif defined(__linux__)
|
||||||
|
" Linux"
|
||||||
#else
|
#else
|
||||||
"%.*s%s-tcc"
|
" Unidentified system"
|
||||||
#endif
|
#endif
|
||||||
, l, a0, target);
|
")\n", TCC_VERSION);
|
||||||
if (strcmp(a0, child_path)) {
|
|
||||||
if (s->verbose > 0)
|
|
||||||
printf("tcc: using '%s'\n", child_path + l), fflush(stdout);
|
|
||||||
execvp(argv[0] = child_path, argv);
|
|
||||||
}
|
|
||||||
tcc_error("'%s' not found", child_path + l);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define exec_other_tcc(s, argv, option)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
static void print_dirs(const char *msg, char **paths, int nb_paths)
|
||||||
{
|
{
|
||||||
FILE *depout;
|
|
||||||
char buf[1024];
|
|
||||||
int i;
|
int i;
|
||||||
|
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
||||||
|
for(i = 0; i < nb_paths; i++)
|
||||||
|
printf(" %s\n", paths[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!filename) {
|
static void print_search_dirs(TCCState *s)
|
||||||
/* compute filename automatically: dir/file.o -> dir/file.d */
|
{
|
||||||
snprintf(buf, sizeof buf, "%.*s.d",
|
printf("install: %s\n", s->tcc_lib_path);
|
||||||
(int)(tcc_fileextension(target) - target), target);
|
/* print_dirs("programs", NULL, 0); */
|
||||||
filename = buf;
|
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||||
}
|
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
if (s->verbose)
|
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
||||||
printf("<- %s\n", filename);
|
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
||||||
|
#endif
|
||||||
/* XXX return err codes instead of error() ? */
|
|
||||||
depout = fopen(filename, "w");
|
|
||||||
if (!depout)
|
|
||||||
tcc_error("could not open '%s'", filename);
|
|
||||||
|
|
||||||
fprintf(depout, "%s: \\\n", target);
|
|
||||||
for (i=0; i<s->nb_target_deps; ++i)
|
|
||||||
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
|
||||||
fprintf(depout, "\n");
|
|
||||||
fclose(depout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *default_outputfile(TCCState *s, const char *first_file)
|
static char *default_outputfile(TCCState *s, const char *first_file)
|
||||||
@ -296,109 +195,113 @@ static unsigned getclock_ms(void)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
TCCState *s;
|
TCCState *s;
|
||||||
int ret, optind, i;
|
int ret, opt, n = 0;
|
||||||
unsigned start_time = 0;
|
unsigned start_time = 0;
|
||||||
const char *first_file = NULL;
|
const char *first_file;
|
||||||
|
|
||||||
|
redo:
|
||||||
s = tcc_new();
|
s = tcc_new();
|
||||||
|
opt = tcc_parse_args(s, &argc, &argv, 1);
|
||||||
|
|
||||||
optind = tcc_parse_args(s, argc - 1, argv + 1);
|
if (n == 0) {
|
||||||
|
if (opt == OPT_HELP)
|
||||||
|
return help(), 1;
|
||||||
|
if (opt == OPT_M32 || opt == OPT_M64)
|
||||||
|
tcc_tool_cross(s, argv, opt); /* never returns */
|
||||||
|
if (s->verbose)
|
||||||
|
version();
|
||||||
|
if (opt == OPT_AR)
|
||||||
|
return tcc_tool_ar(s, argc, argv);
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
if (opt == OPT_IMPDEF)
|
||||||
|
return tcc_tool_impdef(s, argc, argv);
|
||||||
|
#endif
|
||||||
|
if (opt == OPT_V)
|
||||||
|
return 0;
|
||||||
|
|
||||||
tcc_set_environment(s);
|
tcc_set_environment(s);
|
||||||
|
|
||||||
if (optind == 0) {
|
if (opt == OPT_PRINT_DIRS) {
|
||||||
help();
|
/* initialize search dirs */
|
||||||
return 1;
|
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||||
}
|
print_search_dirs(s);
|
||||||
|
return 0;
|
||||||
if (s->cross_target)
|
|
||||||
exec_other_tcc(s, argv, s->cross_target);
|
|
||||||
|
|
||||||
if (s->verbose)
|
|
||||||
display_info(s, 0);
|
|
||||||
|
|
||||||
if (s->nb_files == 0) {
|
|
||||||
if (optind == 1) {
|
|
||||||
if (s->print_search_dirs || s->verbose == 2) {
|
|
||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
|
||||||
display_info(s, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (s->verbose)
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
tcc_error("no input files\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check -c consistency : only single file handled. XXX: checks file type */
|
n = s->nb_files;
|
||||||
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
if (n == 0)
|
||||||
if (s->nb_libraries != 0)
|
tcc_error("no input files\n");
|
||||||
tcc_error("cannot specify libraries with -c");
|
|
||||||
/* accepts only a single input file */
|
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
if (s->nb_files != 1)
|
if (!s->outfile) {
|
||||||
tcc_error("cannot specify multiple files with -c");
|
s->ppfp = stdout;
|
||||||
|
} else {
|
||||||
|
s->ppfp = fopen(s->outfile, "w");
|
||||||
|
if (!s->ppfp)
|
||||||
|
tcc_error("could not write '%s'", s->outfile);
|
||||||
|
}
|
||||||
|
} else if (s->output_type == TCC_OUTPUT_OBJ) {
|
||||||
|
if (s->nb_libraries != 0 && !s->option_r)
|
||||||
|
tcc_error("cannot specify libraries with -c");
|
||||||
|
if (n > 1 && s->outfile)
|
||||||
|
tcc_error("cannot specify output file with -c many files");
|
||||||
|
} else {
|
||||||
|
if (s->option_pthread)
|
||||||
|
tcc_set_options(s, "-lpthread");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->do_bench)
|
||||||
|
start_time = getclock_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->output_type == 0)
|
if (s->output_type == 0)
|
||||||
s->output_type = TCC_OUTPUT_EXE;
|
s->output_type = TCC_OUTPUT_EXE;
|
||||||
tcc_set_output_type(s, s->output_type);
|
tcc_set_output_type(s, s->output_type);
|
||||||
|
|
||||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
|
||||||
if (!s->outfile) {
|
|
||||||
s->ppfp = stdout;
|
|
||||||
} else {
|
|
||||||
s->ppfp = fopen(s->outfile, "w");
|
|
||||||
if (!s->ppfp)
|
|
||||||
tcc_error("could not write '%s'", s->outfile);
|
|
||||||
}
|
|
||||||
} else if (s->output_type != TCC_OUTPUT_OBJ) {
|
|
||||||
if (s->option_pthread)
|
|
||||||
tcc_set_options(s, "-lpthread");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->do_bench)
|
|
||||||
start_time = getclock_ms();
|
|
||||||
|
|
||||||
/* compile or add each files or library */
|
/* compile or add each files or library */
|
||||||
for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
|
for (first_file = NULL, ret = 0;;) {
|
||||||
struct filespec *f = s->files[i];
|
struct filespec *f = s->files[s->nb_files - n];
|
||||||
if (f->type >= AFF_TYPE_LIB) {
|
s->filetype = f->type;
|
||||||
s->alacarte_link = f->type == AFF_TYPE_LIB;
|
s->alacarte_link = f->alacarte;
|
||||||
|
if (f->type == AFF_TYPE_LIB) {
|
||||||
if (tcc_add_library_err(s, f->name) < 0)
|
if (tcc_add_library_err(s, f->name) < 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
if (1 == s->verbose)
|
if (1 == s->verbose)
|
||||||
printf("-> %s\n", f->name);
|
printf("-> %s\n", f->name);
|
||||||
s->filetype = f->type;
|
|
||||||
if (tcc_add_file(s, f->name) < 0)
|
|
||||||
ret = 1;
|
|
||||||
if (!first_file)
|
if (!first_file)
|
||||||
first_file = f->name;
|
first_file = f->name;
|
||||||
|
if (tcc_add_file(s, f->name) < 0)
|
||||||
|
ret = 1;
|
||||||
}
|
}
|
||||||
s->filetype = AFF_TYPE_NONE;
|
s->filetype = 0;
|
||||||
s->alacarte_link = 1;
|
s->alacarte_link = 1;
|
||||||
|
if (ret || --n == 0 || s->output_type == TCC_OUTPUT_OBJ)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
if (s->outfile)
|
if (s->outfile)
|
||||||
fclose(s->ppfp);
|
fclose(s->ppfp);
|
||||||
|
|
||||||
} else if (0 == ret) {
|
} else if (0 == ret) {
|
||||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
|
ret = tcc_run(s, argc, argv);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!s->outfile)
|
if (!s->outfile)
|
||||||
s->outfile = default_outputfile(s, first_file);
|
s->outfile = default_outputfile(s, first_file);
|
||||||
ret = !!tcc_output_file(s, s->outfile);
|
if (tcc_output_file(s, s->outfile))
|
||||||
if (s->gen_deps && !ret)
|
ret = 1;
|
||||||
|
else if (s->gen_deps)
|
||||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->do_bench)
|
if (s->do_bench && ret == 0 && n == 0)
|
||||||
tcc_print_stats(s, getclock_ms() - start_time);
|
tcc_print_stats(s, getclock_ms() - start_time);
|
||||||
tcc_delete(s);
|
tcc_delete(s);
|
||||||
|
if (ret == 0 && n)
|
||||||
|
goto redo; /* compile more files with -c */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
34
tcc.h
34
tcc.h
@ -767,17 +767,19 @@ struct TCCState {
|
|||||||
int nb_libraries; /* number of libs thereof */
|
int nb_libraries; /* number of libs thereof */
|
||||||
int filetype;
|
int filetype;
|
||||||
char *outfile; /* output filename */
|
char *outfile; /* output filename */
|
||||||
int cross_target; /* -m32/-m64 */
|
|
||||||
int print_search_dirs; /* option */
|
|
||||||
int option_r; /* option -r */
|
int option_r; /* option -r */
|
||||||
int do_bench; /* option -bench */
|
int do_bench; /* option -bench */
|
||||||
int gen_deps; /* option -MD */
|
int gen_deps; /* option -MD */
|
||||||
char *deps_outfile; /* option -MF */
|
char *deps_outfile; /* option -MF */
|
||||||
int option_pthread; /* -pthread option */
|
int option_pthread; /* -pthread option */
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filespec {
|
struct filespec {
|
||||||
char type, name[1];
|
char type;
|
||||||
|
char alacarte;
|
||||||
|
char name[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The current value can be: */
|
/* The current value can be: */
|
||||||
@ -1091,7 +1093,7 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
|
|||||||
#define realloc(p, s) use_tcc_realloc(p, s)
|
#define realloc(p, s) use_tcc_realloc(p, s)
|
||||||
#undef strdup
|
#undef strdup
|
||||||
#define strdup(s) use_tcc_strdup(s)
|
#define strdup(s) use_tcc_strdup(s)
|
||||||
PUB_FUNC void tcc_memstats(int bench);
|
PUB_FUNC void tcc_memcheck(void);
|
||||||
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
|
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
|
||||||
PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
|
PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
|
||||||
PUB_FUNC void tcc_warning(const char *fmt, ...);
|
PUB_FUNC void tcc_warning(const char *fmt, ...);
|
||||||
@ -1131,14 +1133,12 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
#define AFF_TYPE_ASMPP 3
|
#define AFF_TYPE_ASMPP 3
|
||||||
#define AFF_TYPE_BIN 4
|
#define AFF_TYPE_BIN 4
|
||||||
#define AFF_TYPE_LIB 5
|
#define AFF_TYPE_LIB 5
|
||||||
#define AFF_TYPE_LIBWH 6
|
|
||||||
/* values from tcc_object_type(...) */
|
/* values from tcc_object_type(...) */
|
||||||
#define AFF_BINTYPE_REL 1
|
#define AFF_BINTYPE_REL 1
|
||||||
#define AFF_BINTYPE_DYN 2
|
#define AFF_BINTYPE_DYN 2
|
||||||
#define AFF_BINTYPE_AR 3
|
#define AFF_BINTYPE_AR 3
|
||||||
#define AFF_BINTYPE_C67 4
|
#define AFF_BINTYPE_C67 4
|
||||||
|
|
||||||
|
|
||||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
||||||
|
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
@ -1149,12 +1149,21 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
|
|||||||
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
||||||
|
|
||||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
||||||
PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
|
PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
|
||||||
PUB_FUNC void tcc_set_environment(TCCState *s);
|
PUB_FUNC void tcc_set_environment(TCCState *s);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ST_FUNC char *normalize_slashes(char *path);
|
ST_FUNC char *normalize_slashes(char *path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* tcc_parse_args return codes: */
|
||||||
|
#define OPT_HELP 1
|
||||||
|
#define OPT_V 3
|
||||||
|
#define OPT_PRINT_DIRS 4
|
||||||
|
#define OPT_AR 5
|
||||||
|
#define OPT_IMPDEF 6
|
||||||
|
#define OPT_M32 32
|
||||||
|
#define OPT_M64 64
|
||||||
|
|
||||||
/* ------------ tccpp.c ------------ */
|
/* ------------ tccpp.c ------------ */
|
||||||
|
|
||||||
ST_DATA struct BufferedFile *file;
|
ST_DATA struct BufferedFile *file;
|
||||||
@ -1567,6 +1576,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
|
|||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
|
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
|
||||||
#endif
|
#endif
|
||||||
|
PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
|
||||||
/* symbol properties stored in Elf32_Sym->st_other */
|
/* symbol properties stored in Elf32_Sym->st_other */
|
||||||
# define ST_PE_EXPORT 0x10
|
# define ST_PE_EXPORT 0x10
|
||||||
# define ST_PE_IMPORT 0x20
|
# define ST_PE_IMPORT 0x20
|
||||||
@ -1595,6 +1605,16 @@ ST_FUNC void tcc_set_num_callers(int n);
|
|||||||
ST_FUNC void tcc_run_free(TCCState *s1);
|
ST_FUNC void tcc_run_free(TCCState *s1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ------------ tcctools.c ----------------- */
|
||||||
|
#if 0 /* included in tcc.c */
|
||||||
|
ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
|
||||||
|
#endif
|
||||||
|
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option);
|
||||||
|
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
#undef ST_DATA
|
#undef ST_DATA
|
||||||
#ifdef ONE_SOURCE
|
#ifdef ONE_SOURCE
|
||||||
|
1
tccasm.c
1
tccasm.c
@ -1005,6 +1005,7 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
|||||||
/* default section is text */
|
/* default section is text */
|
||||||
cur_text_section = text_section;
|
cur_text_section = text_section;
|
||||||
ind = cur_text_section->data_offset;
|
ind = cur_text_section->data_offset;
|
||||||
|
nocode_wanted = 0;
|
||||||
|
|
||||||
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
||||||
symbols can be safely used */
|
symbols can be safely used */
|
||||||
|
122
tccpe.c
122
tccpe.c
@ -962,7 +962,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
} else {
|
} else {
|
||||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
|
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
|
||||||
if (pe->s1->verbose)
|
if (pe->s1->verbose)
|
||||||
printf("<- %s (%d symbols)\n", buf, sym_count);
|
printf("<- %s (%d symbol%s)\n", buf, sym_count, "s" + (sym_count < 2));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1543,6 +1543,102 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
|||||||
return len == read(fd, buffer, len);
|
return len == read(fd, buffer, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
|
PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
|
||||||
|
{
|
||||||
|
int l, i, n, n0, ret;
|
||||||
|
char *p;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
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;
|
||||||
|
#else
|
||||||
|
IMAGE_OPTIONAL_HEADER32 oh;
|
||||||
|
#endif
|
||||||
|
int pef_hdroffset, opt_hdroffset, sec_hdroffset;
|
||||||
|
|
||||||
|
n = n0 = 0;
|
||||||
|
p = NULL;
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY | O_BINARY);
|
||||||
|
if (fd < 0)
|
||||||
|
goto the_end_1;
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
if (!read_mem(fd, 0, &dh, sizeof dh))
|
||||||
|
goto the_end;
|
||||||
|
if (!read_mem(fd, 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(fd, pef_hdroffset, &ih, sizeof ih))
|
||||||
|
goto the_end;
|
||||||
|
if (IMAGE_FILE_MACHINE != ih.Machine) {
|
||||||
|
if (ih.Machine == 0x014C)
|
||||||
|
ret = 32;
|
||||||
|
else if (ih.Machine == 0x8664)
|
||||||
|
ret = 64;
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
opt_hdroffset = pef_hdroffset + sizeof ih;
|
||||||
|
sec_hdroffset = opt_hdroffset + sizeof oh;
|
||||||
|
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
|
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
|
||||||
|
goto the_end_0;
|
||||||
|
|
||||||
|
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||||
|
//printf("addr: %08x\n", addr);
|
||||||
|
for (i = 0; i < ih.NumberOfSections; ++i) {
|
||||||
|
if (!read_mem(fd, 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_0;
|
||||||
|
|
||||||
|
found:
|
||||||
|
ref = ish.VirtualAddress - ish.PointerToRawData;
|
||||||
|
if (!read_mem(fd, addr - ref, &ied, sizeof ied))
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
|
namep = ied.AddressOfNames - ref;
|
||||||
|
for (i = 0; i < ied.NumberOfNames; ++i) {
|
||||||
|
if (!read_mem(fd, 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(fd, ptr - ref + l++, p + n, 1)) {
|
||||||
|
tcc_free(p), p = NULL;
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
if (p[n++] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p)
|
||||||
|
p[n] = 0;
|
||||||
|
the_end_0:
|
||||||
|
ret = 0;
|
||||||
|
the_end:
|
||||||
|
close(fd);
|
||||||
|
the_end_1:
|
||||||
|
*pp = p;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------
|
/* -------------------------------------------------------------
|
||||||
* This is for compiled windows resources in 'coff' format
|
* This is for compiled windows resources in 'coff' format
|
||||||
* as generated by 'windres.exe -O coff ...'.
|
* as generated by 'windres.exe -O coff ...'.
|
||||||
@ -1660,20 +1756,20 @@ quit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
static int pe_load_dll(TCCState *s1, const char *filename)
|
||||||
#include "win32/tools/tiny_impdef.c"
|
|
||||||
|
|
||||||
static int pe_load_dll(TCCState *s1, const char *dllname, int fd)
|
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int index;
|
int index, ret;
|
||||||
p = get_export_names(fd);
|
|
||||||
if (!p)
|
ret = tcc_get_dllexports(filename, &p);
|
||||||
|
if (ret) {
|
||||||
return -1;
|
return -1;
|
||||||
index = add_dllref(s1, dllname);
|
} else if (p) {
|
||||||
for (q = p; *q; q += 1 + strlen(q))
|
index = add_dllref(s1, tcc_basename(filename));
|
||||||
pe_putimport(s1, index, q, 0);
|
for (q = p; *q; q += 1 + strlen(q))
|
||||||
tcc_free(p);
|
pe_putimport(s1, index, q, 0);
|
||||||
|
tcc_free(p);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1687,7 +1783,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
|
|||||||
else if (pe_load_res(s1, fd) == 0)
|
else if (pe_load_res(s1, fd) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4))
|
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4))
|
||||||
ret = pe_load_dll(s1, tcc_basename(filename), fd);
|
ret = pe_load_dll(s1, filename);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
547
tcctools.c
Normal file
547
tcctools.c
Normal file
@ -0,0 +1,547 @@
|
|||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
* TCC - Tiny C Compiler
|
||||||
|
*
|
||||||
|
* tcctools.c - extra tools and and -m32/64 support
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
* This program is for making libtcc1.a without ar
|
||||||
|
* tiny_libmaker - tiny elf lib maker
|
||||||
|
* usage: tiny_libmaker [lib] files...
|
||||||
|
* Copyright (c) 2007 Timppa
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tcc.h"
|
||||||
|
|
||||||
|
//#define ARMAG "!<arch>\n"
|
||||||
|
#define ARFMAG "`\n"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char ar_name[16];
|
||||||
|
char ar_date[12];
|
||||||
|
char ar_uid[6];
|
||||||
|
char ar_gid[6];
|
||||||
|
char ar_mode[8];
|
||||||
|
char ar_size[10];
|
||||||
|
char ar_fmag[2];
|
||||||
|
} ArHdr;
|
||||||
|
|
||||||
|
static unsigned long le2belong(unsigned long ul) {
|
||||||
|
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
|
||||||
|
((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns 1 if s contains any of the chars of list, else 0 */
|
||||||
|
static int contains_any(const char *s, const char *list) {
|
||||||
|
const char *l;
|
||||||
|
for (; *s; s++) {
|
||||||
|
for (l = list; *l; l++) {
|
||||||
|
if (*s == *l)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ar_usage(int ret) {
|
||||||
|
fprintf(stderr, "usage: tcc -ar [rcsv] lib file...\n");
|
||||||
|
fprintf(stderr, "create library ([abdioptxN] not supported).\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
||||||
|
{
|
||||||
|
static ArHdr arhdr = {
|
||||||
|
"/ ",
|
||||||
|
" ",
|
||||||
|
"0 ",
|
||||||
|
"0 ",
|
||||||
|
"0 ",
|
||||||
|
" ",
|
||||||
|
ARFMAG
|
||||||
|
};
|
||||||
|
|
||||||
|
static ArHdr arhdro = {
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"0 ",
|
||||||
|
"0 ",
|
||||||
|
"0 ",
|
||||||
|
" ",
|
||||||
|
ARFMAG
|
||||||
|
};
|
||||||
|
|
||||||
|
FILE *fi, *fh = NULL, *fo = NULL;
|
||||||
|
ElfW(Ehdr) *ehdr;
|
||||||
|
ElfW(Shdr) *shdr;
|
||||||
|
ElfW(Sym) *sym;
|
||||||
|
int i, fsize, i_lib, i_obj;
|
||||||
|
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
||||||
|
int symtabsize = 0;//, strtabsize = 0;
|
||||||
|
char *anames = NULL;
|
||||||
|
int *afpos = NULL;
|
||||||
|
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
||||||
|
char tfile[260], stmp[20];
|
||||||
|
char *file, *name;
|
||||||
|
int ret = 2;
|
||||||
|
char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
|
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
const char *a = argv[i];
|
||||||
|
if (*a == '-' && strstr(a, "."))
|
||||||
|
ret = 1; // -x.y is always invalid (same as gnu ar)
|
||||||
|
if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
|
||||||
|
if (contains_any(a, ops_conflict))
|
||||||
|
ret = 1;
|
||||||
|
if (strstr(a, "v"))
|
||||||
|
verbose = 1;
|
||||||
|
} else { // lib or obj files: don't abort - keep validating all args.
|
||||||
|
if (!i_lib) // first file is the lib
|
||||||
|
i_lib = i;
|
||||||
|
else if (!i_obj) // second file is the first obj
|
||||||
|
i_obj = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i_obj) // i_obj implies also i_lib. we require both.
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
if (ret == 1)
|
||||||
|
return ar_usage(ret);
|
||||||
|
|
||||||
|
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
||||||
|
if ((fo = fopen(tfile, "wb+")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "tcc: ar: can't create temporary file %s\n", tfile);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcmax = 250;
|
||||||
|
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
||||||
|
memcpy(&arhdro.ar_mode, "100666", 6);
|
||||||
|
|
||||||
|
// i_obj = first input object file
|
||||||
|
while (i_obj < argc)
|
||||||
|
{
|
||||||
|
if (*argv[i_obj] == '-') { // by now, all options start with '-'
|
||||||
|
i_obj++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((fi = fopen(argv[i_obj], "rb")) == NULL) {
|
||||||
|
fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_obj]);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
printf("a - %s\n", argv[i_obj]);
|
||||||
|
|
||||||
|
fseek(fi, 0, SEEK_END);
|
||||||
|
fsize = ftell(fi);
|
||||||
|
fseek(fi, 0, SEEK_SET);
|
||||||
|
buf = tcc_malloc(fsize + 1);
|
||||||
|
fread(buf, fsize, 1, fi);
|
||||||
|
fclose(fi);
|
||||||
|
|
||||||
|
// elf header
|
||||||
|
ehdr = (ElfW(Ehdr) *)buf;
|
||||||
|
if (ehdr->e_ident[4] != ELFCLASSW)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "tcc: ar: Unsupported Elf Class: %s\n", argv[i_obj]);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
|
||||||
|
shstr = (char *)(buf + shdr->sh_offset);
|
||||||
|
for (i = 0; i < ehdr->e_shnum; i++)
|
||||||
|
{
|
||||||
|
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
|
||||||
|
if (!shdr->sh_offset)
|
||||||
|
continue;
|
||||||
|
if (shdr->sh_type == SHT_SYMTAB)
|
||||||
|
{
|
||||||
|
symtab = (char *)(buf + shdr->sh_offset);
|
||||||
|
symtabsize = shdr->sh_size;
|
||||||
|
}
|
||||||
|
if (shdr->sh_type == SHT_STRTAB)
|
||||||
|
{
|
||||||
|
if (!strcmp(shstr + shdr->sh_name, ".strtab"))
|
||||||
|
{
|
||||||
|
strtab = (char *)(buf + shdr->sh_offset);
|
||||||
|
//strtabsize = shdr->sh_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symtab && symtabsize)
|
||||||
|
{
|
||||||
|
int nsym = symtabsize / sizeof(ElfW(Sym));
|
||||||
|
//printf("symtab: info size shndx name\n");
|
||||||
|
for (i = 1; i < nsym; i++)
|
||||||
|
{
|
||||||
|
sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
|
||||||
|
if (sym->st_shndx &&
|
||||||
|
(sym->st_info == 0x10
|
||||||
|
|| sym->st_info == 0x11
|
||||||
|
|| sym->st_info == 0x12
|
||||||
|
)) {
|
||||||
|
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
||||||
|
istrlen = strlen(strtab + sym->st_name)+1;
|
||||||
|
anames = tcc_realloc(anames, strpos+istrlen);
|
||||||
|
strcpy(anames + strpos, strtab + sym->st_name);
|
||||||
|
strpos += istrlen;
|
||||||
|
if (++funccnt >= funcmax) {
|
||||||
|
funcmax += 250;
|
||||||
|
afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
|
||||||
|
}
|
||||||
|
afpos[funccnt] = fpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file = argv[i_obj];
|
||||||
|
for (name = strchr(file, 0);
|
||||||
|
name > file && name[-1] != '/' && name[-1] != '\\';
|
||||||
|
--name);
|
||||||
|
istrlen = strlen(name);
|
||||||
|
if (istrlen >= sizeof(arhdro.ar_name))
|
||||||
|
istrlen = sizeof(arhdro.ar_name) - 1;
|
||||||
|
memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
|
||||||
|
memcpy(arhdro.ar_name, name, istrlen);
|
||||||
|
arhdro.ar_name[istrlen] = '/';
|
||||||
|
sprintf(stmp, "%-10d", fsize);
|
||||||
|
memcpy(&arhdro.ar_size, stmp, 10);
|
||||||
|
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
||||||
|
fwrite(buf, fsize, 1, fo);
|
||||||
|
tcc_free(buf);
|
||||||
|
i_obj++;
|
||||||
|
fpos += (fsize + sizeof(arhdro));
|
||||||
|
}
|
||||||
|
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
||||||
|
fpos = 0;
|
||||||
|
if ((hofs & 1)) // align
|
||||||
|
hofs++, fpos = 1;
|
||||||
|
// write header
|
||||||
|
fwrite("!<arch>\n", 8, 1, fh);
|
||||||
|
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
|
||||||
|
memcpy(&arhdr.ar_size, stmp, 10);
|
||||||
|
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
||||||
|
afpos[0] = le2belong(funccnt);
|
||||||
|
for (i=1; i<=funccnt; i++)
|
||||||
|
afpos[i] = le2belong(afpos[i] + hofs);
|
||||||
|
fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
|
||||||
|
fwrite(anames, strpos, 1, fh);
|
||||||
|
if (fpos)
|
||||||
|
fwrite("", 1, 1, fh);
|
||||||
|
// write objects
|
||||||
|
fseek(fo, 0, SEEK_END);
|
||||||
|
fsize = ftell(fo);
|
||||||
|
fseek(fo, 0, SEEK_SET);
|
||||||
|
buf = tcc_malloc(fsize + 1);
|
||||||
|
fread(buf, fsize, 1, fo);
|
||||||
|
fwrite(buf, fsize, 1, fh);
|
||||||
|
tcc_free(buf);
|
||||||
|
ret = 0;
|
||||||
|
the_end:
|
||||||
|
if (anames)
|
||||||
|
tcc_free(anames);
|
||||||
|
if (afpos)
|
||||||
|
tcc_free(afpos);
|
||||||
|
if (fh)
|
||||||
|
fclose(fh);
|
||||||
|
if (fo)
|
||||||
|
fclose(fo), remove(tfile);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
* tiny_impdef creates an export definition file (.def) from a dll
|
||||||
|
* on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005,2007 grischka
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
|
||||||
|
ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret, v, i;
|
||||||
|
char infile[MAX_PATH];
|
||||||
|
char outfile[MAX_PATH];
|
||||||
|
|
||||||
|
const char *file;
|
||||||
|
char *p, *q;
|
||||||
|
FILE *fp, *op;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
char path[MAX_PATH];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
infile[0] = outfile[0] = 0;
|
||||||
|
fp = op = NULL;
|
||||||
|
ret = 1;
|
||||||
|
p = NULL;
|
||||||
|
v = 0;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; ++i) {
|
||||||
|
const char *a = argv[i];
|
||||||
|
if ('-' == a[0]) {
|
||||||
|
if (0 == strcmp(a, "-v")) {
|
||||||
|
v = 1;
|
||||||
|
} else if (0 == strcmp(a, "-o")) {
|
||||||
|
if (++i == argc)
|
||||||
|
goto usage;
|
||||||
|
strcpy(outfile, argv[i]);
|
||||||
|
} else
|
||||||
|
goto usage;
|
||||||
|
} else if (0 == infile[0])
|
||||||
|
strcpy(infile, a);
|
||||||
|
else
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == infile[0]) {
|
||||||
|
usage:
|
||||||
|
fprintf(stderr,
|
||||||
|
"usage: tcc -impdef library.dll [-v] [-o outputfile]\n"
|
||||||
|
"create export definition file (.def) from dll\n"
|
||||||
|
);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == outfile[0]) {
|
||||||
|
strcpy(outfile, tcc_basename(infile));
|
||||||
|
q = strrchr(outfile, '.');
|
||||||
|
if (NULL == q)
|
||||||
|
q = strchr(outfile, 0);
|
||||||
|
strcpy(q, ".def");
|
||||||
|
}
|
||||||
|
|
||||||
|
file = infile;
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
|
||||||
|
file = path;
|
||||||
|
#endif
|
||||||
|
ret = tcc_get_dllexports(file, &p);
|
||||||
|
if (ret || !p) {
|
||||||
|
fprintf(stderr, "tcc: impdef: %s '%s'\n",
|
||||||
|
ret == 32 ? "can't read symbols from 32bit" :
|
||||||
|
ret == 64 ? "can't read symbols from 64bit" :
|
||||||
|
ret == -1 ? "can't find file" :
|
||||||
|
ret == 0 ? "no symbols found in" :
|
||||||
|
"unknown file type", file);
|
||||||
|
ret = 1;
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v)
|
||||||
|
printf("-> %s\n", file);
|
||||||
|
|
||||||
|
op = fopen(outfile, "w");
|
||||||
|
if (NULL == op) {
|
||||||
|
fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", tcc_basename(file));
|
||||||
|
for (q = p, i = 0; *q; ++i) {
|
||||||
|
fprintf(op, "%s\n", q);
|
||||||
|
q += strlen(q) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v)
|
||||||
|
printf("<- %s (%d symbol%s)\n", outfile, i, "s" + (i<2));
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
the_end:
|
||||||
|
/* cannot free memory received from tcc_get_dllexports
|
||||||
|
if it came from a dll */
|
||||||
|
/* if (p)
|
||||||
|
tcc_free(p); */
|
||||||
|
if (fp)
|
||||||
|
fclose(fp);
|
||||||
|
if (op)
|
||||||
|
fclose(op);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TCC_TARGET_PE */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
* TCC - Tiny C Compiler
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
|
||||||
|
|
||||||
|
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
||||||
|
|
||||||
|
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option)
|
||||||
|
{
|
||||||
|
tcc_error("-m%d not implemented.", option);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <process.h>
|
||||||
|
|
||||||
|
static char *str_replace(const char *str, const char *p, const char *r)
|
||||||
|
{
|
||||||
|
const char *s, *s0;
|
||||||
|
char *d, *d0;
|
||||||
|
int sl, pl, rl;
|
||||||
|
|
||||||
|
sl = strlen(str);
|
||||||
|
pl = strlen(p);
|
||||||
|
rl = strlen(r);
|
||||||
|
for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
|
||||||
|
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
|
||||||
|
if (d) {
|
||||||
|
memcpy(d, s0, sl = s - s0), d += sl;
|
||||||
|
memcpy(d, r, rl), d += rl;
|
||||||
|
} else
|
||||||
|
sl += rl - pl;
|
||||||
|
}
|
||||||
|
if (d) {
|
||||||
|
strcpy(d, s0);
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int execvp_win32(const char *prog, char **argv)
|
||||||
|
{
|
||||||
|
int ret; char **p;
|
||||||
|
/* replace all " by \" */
|
||||||
|
for (p = argv; *p; ++p)
|
||||||
|
if (strchr(*p, '"'))
|
||||||
|
*p = str_replace(*p, "\"", "\\\"");
|
||||||
|
ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
||||||
|
if (-1 == ret)
|
||||||
|
return ret;
|
||||||
|
_cwait(&ret, ret, WAIT_CHILD);
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
#define execvp execvp_win32
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target)
|
||||||
|
{
|
||||||
|
char program[4096];
|
||||||
|
char *a0 = argv[0];
|
||||||
|
int prefix = tcc_basename(a0) - a0;
|
||||||
|
|
||||||
|
snprintf(program, sizeof program,
|
||||||
|
"%.*s%s"
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
"-win32"
|
||||||
|
#endif
|
||||||
|
"-tcc"
|
||||||
|
#ifdef _WIN32
|
||||||
|
".exe"
|
||||||
|
#endif
|
||||||
|
, prefix, a0, target == 64 ? "x86_64" : "i386");
|
||||||
|
|
||||||
|
if (strcmp(a0, program))
|
||||||
|
execvp(argv[0] = program, argv);
|
||||||
|
tcc_error("could not run '%s'", program);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int _CRT_glob = 1;
|
||||||
|
#ifndef _CRT_glob
|
||||||
|
int _dowildcard = 1;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
/* generate xxx.d file */
|
||||||
|
|
||||||
|
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *depout;
|
||||||
|
char buf[1024];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!filename) {
|
||||||
|
/* compute filename automatically: dir/file.o -> dir/file.d */
|
||||||
|
snprintf(buf, sizeof buf, "%.*s.d",
|
||||||
|
(int)(tcc_fileextension(target) - target), target);
|
||||||
|
filename = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->verbose)
|
||||||
|
printf("<- %s\n", filename);
|
||||||
|
|
||||||
|
/* XXX return err codes instead of error() ? */
|
||||||
|
depout = fopen(filename, "w");
|
||||||
|
if (!depout)
|
||||||
|
tcc_error("could not open '%s'", filename);
|
||||||
|
|
||||||
|
fprintf(depout, "%s: \\\n", target);
|
||||||
|
for (i=0; i<s->nb_target_deps; ++i)
|
||||||
|
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
||||||
|
fprintf(depout, "\n");
|
||||||
|
fclose(depout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
@ -3431,7 +3431,7 @@ void builtin_test(void)
|
|||||||
i = sizeof (__builtin_choose_expr (0, ll, s));
|
i = sizeof (__builtin_choose_expr (0, ll, s));
|
||||||
printf("bce: %d\n", i);
|
printf("bce: %d\n", i);
|
||||||
|
|
||||||
printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
|
//printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -5,10 +5,6 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal
|
||||||
|
|
||||||
set VSCOMNTOOLS=%VS150COMNTOOLS%
|
|
||||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
|
|
||||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
|
|
||||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
|
|
||||||
set CC=gcc -Os -s
|
set CC=gcc -Os -s
|
||||||
set /p VERSION= < ..\VERSION
|
set /p VERSION= < ..\VERSION
|
||||||
set INST=
|
set INST=
|
||||||
@ -70,10 +66,17 @@ goto :a1
|
|||||||
if not (%1)==() goto :usage
|
if not (%1)==() goto :usage
|
||||||
|
|
||||||
if not "%CC%"=="@call :cl" goto :p1
|
if not "%CC%"=="@call :cl" goto :p1
|
||||||
|
set VSCOMNTOOLS=%VS150COMNTOOLS%
|
||||||
|
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
|
||||||
|
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
|
||||||
|
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
|
||||||
if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"
|
if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"
|
||||||
if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
|
if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
|
||||||
if %T%_==_ set T=32& if %Platform%_==X64_ set T=64
|
if %T%_==_ set T=32& if %Platform%_==X64_ set T=64
|
||||||
|
if %CLVARS%_==_ goto :p1
|
||||||
|
if exist %CLVARS% call %CLVARS%
|
||||||
:p1
|
:p1
|
||||||
|
|
||||||
if not %T%_==_ goto :p2
|
if not %T%_==_ goto :p2
|
||||||
set T=32
|
set T=32
|
||||||
if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
|
if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
|
||||||
@ -97,9 +100,6 @@ set PX=i386-win32
|
|||||||
|
|
||||||
@echo on
|
@echo on
|
||||||
|
|
||||||
@if %CLVARS%_==_ goto :config.h
|
|
||||||
call %CLVARS%
|
|
||||||
|
|
||||||
:config.h
|
:config.h
|
||||||
echo>..\config.h #define TCC_VERSION "%VERSION%"
|
echo>..\config.h #define TCC_VERSION "%VERSION%"
|
||||||
echo>> ..\config.h #ifdef TCC_TARGET_X86_64
|
echo>> ..\config.h #ifdef TCC_TARGET_X86_64
|
||||||
@ -108,7 +108,7 @@ echo>> ..\config.h #else
|
|||||||
echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"
|
echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"
|
||||||
echo>> ..\config.h #endif
|
echo>> ..\config.h #endif
|
||||||
|
|
||||||
@del /q *tcc.exe tiny_*.exe *tcc.dll
|
for %%f in (*tcc.exe *tcc.dll) do @del %%f
|
||||||
|
|
||||||
:compiler
|
:compiler
|
||||||
%CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL
|
%CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL
|
||||||
@ -116,10 +116,6 @@ echo>> ..\config.h #endif
|
|||||||
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D%
|
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D%
|
||||||
%CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE
|
%CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE
|
||||||
|
|
||||||
:tools
|
|
||||||
%CC% -o tiny_impdef.exe tools\tiny_impdef.c %D%
|
|
||||||
%CC% -o tiny_libmaker.exe tools\tiny_libmaker.c %D%
|
|
||||||
|
|
||||||
@if (%TCC_FILES%)==(no) goto :files-done
|
@if (%TCC_FILES%)==(no) goto :files-done
|
||||||
|
|
||||||
if not exist libtcc mkdir libtcc
|
if not exist libtcc mkdir libtcc
|
||||||
@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64
|
|||||||
copy>nul ..\include\*.h include
|
copy>nul ..\include\*.h include
|
||||||
copy>nul ..\tcclib.h include
|
copy>nul ..\tcclib.h include
|
||||||
copy>nul ..\libtcc.h libtcc
|
copy>nul ..\libtcc.h libtcc
|
||||||
tiny_impdef libtcc.dll -o libtcc\libtcc.def
|
|
||||||
copy>nul ..\tests\libtcc_test.c examples
|
copy>nul ..\tests\libtcc_test.c examples
|
||||||
copy>nul tcc-win32.txt doc
|
copy>nul tcc-win32.txt doc
|
||||||
|
|
||||||
copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
|
.\tcc -impdef libtcc.dll -o libtcc\libtcc.def
|
||||||
%CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX%
|
@if errorlevel 1 goto :the_end
|
||||||
|
|
||||||
:libtcc1.a
|
:libtcc1.a
|
||||||
@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.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
|
||||||
@ -149,7 +144,7 @@ copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
|
|||||||
.\tcc -m32 %D32% -w -c ../lib/bcheck.c
|
.\tcc -m32 %D32% -w -c ../lib/bcheck.c
|
||||||
.\tcc -m32 %D32% -c ../lib/alloca86.S
|
.\tcc -m32 %D32% -c ../lib/alloca86.S
|
||||||
.\tcc -m32 %D32% -c ../lib/alloca86-bt.S
|
.\tcc -m32 %D32% -c ../lib/alloca86-bt.S
|
||||||
tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
|
.\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
|
||||||
@if errorlevel 1 goto :the_end
|
@if errorlevel 1 goto :the_end
|
||||||
.\tcc -m64 %D64% -c ../lib/libtcc1.c
|
.\tcc -m64 %D64% -c ../lib/libtcc1.c
|
||||||
.\tcc -m64 %D64% -c lib/crt1.c
|
.\tcc -m64 %D64% -c lib/crt1.c
|
||||||
@ -162,7 +157,7 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
|
|||||||
.\tcc -m64 %D64% -w -c ../lib/bcheck.c
|
.\tcc -m64 %D64% -w -c ../lib/bcheck.c
|
||||||
.\tcc -m64 %D64% -c ../lib/alloca86_64.S
|
.\tcc -m64 %D64% -c ../lib/alloca86_64.S
|
||||||
.\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S
|
.\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S
|
||||||
tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
|
.\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
|
||||||
@if errorlevel 1 goto :the_end
|
@if errorlevel 1 goto :the_end
|
||||||
|
|
||||||
:tcc-doc.html
|
:tcc-doc.html
|
||||||
@ -172,7 +167,7 @@ cmd /c makeinfo --html --no-split ../tcc-doc.texi -o doc/tcc-doc.html
|
|||||||
:doc-done
|
:doc-done
|
||||||
|
|
||||||
:files-done
|
:files-done
|
||||||
@del /q *.o *.def *-m??.exe
|
for %%f in (*.o *.def) do @del %%f
|
||||||
|
|
||||||
:copy-install
|
:copy-install
|
||||||
@if (%INST%)==() goto :the_end
|
@if (%INST%)==() goto :the_end
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
For the 'Hello DLL' example type
|
For the 'Hello DLL' example type
|
||||||
|
|
||||||
tcc -shared dll.c
|
tcc -shared dll.c
|
||||||
tiny_impdef dll.dll (optional)
|
tcc -impdef dll.dll (optional)
|
||||||
tcc hello_dll.c dll.def
|
tcc hello_dll.c dll.def
|
||||||
|
|
||||||
|
|
||||||
@ -66,10 +66,10 @@
|
|||||||
To link with Windows system DLLs, TCC uses import definition
|
To link with Windows system DLLs, TCC uses import definition
|
||||||
files (.def) instead of libraries.
|
files (.def) instead of libraries.
|
||||||
|
|
||||||
The included 'tiny_impdef' program may be used to make additional
|
The now built-in 'tiny_impdef' program may be used to make
|
||||||
.def files for any DLL. For example:
|
additional .def files for any DLL. For example
|
||||||
|
|
||||||
tiny_impdef.exe opengl32.dll
|
tcc -impdef [-v] opengl32.dll [-o opengl32.def]
|
||||||
|
|
||||||
Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
|
Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
|
||||||
the TCC commandline to link a program that uses opengl32.dll.
|
the TCC commandline to link a program that uses opengl32.dll.
|
||||||
@ -98,10 +98,10 @@
|
|||||||
|
|
||||||
Tiny Libmaker:
|
Tiny Libmaker:
|
||||||
--------------
|
--------------
|
||||||
The included tiny_libmaker tool by Timovj Lahde can be used as
|
The now built-in tiny_libmaker tool by Timovj Lahde can be used as
|
||||||
'ar' replacement to make a library from several object files:
|
'ar' replacement to make a library from several object files:
|
||||||
|
|
||||||
tiny_libmaker [rcs] library objectfiles ...
|
tcc -ar [rcsv] library objectfiles ...
|
||||||
|
|
||||||
|
|
||||||
Compilation from source:
|
Compilation from source:
|
||||||
@ -143,15 +143,13 @@
|
|||||||
------------
|
------------
|
||||||
- On the object file level, currently TCC supports only the ELF format,
|
- On the object file level, currently TCC supports only the ELF format,
|
||||||
not COFF as used by MinGW and MSVC. It is not possible to exchange
|
not COFF as used by MinGW and MSVC. It is not possible to exchange
|
||||||
object files or libraries between TCC and these compilers. However
|
object files or libraries between TCC and these compilers.
|
||||||
libraries for TCC from objects by TCC can be made using tiny_libmaker
|
|
||||||
or MinGW's ar.
|
However libraries for TCC from objects by TCC can be made using
|
||||||
|
tcc -ar lib.a files.o ,,,
|
||||||
|
|
||||||
- No leading underscore is generated in the ELF symbols.
|
- No leading underscore is generated in the ELF symbols.
|
||||||
|
|
||||||
- Bounds checking (option -b) is not supported on 64-bit OS.
|
|
||||||
|
|
||||||
|
|
||||||
Documentation and License:
|
Documentation and License:
|
||||||
--------------------------
|
--------------------------
|
||||||
TCC is distributed under the GNU Lesser General Public License. (See
|
TCC is distributed under the GNU Lesser General Public License. (See
|
||||||
|
@ -1,249 +0,0 @@
|
|||||||
/* -------------------------------------------------------------- */
|
|
||||||
/*
|
|
||||||
* tiny_impdef creates an export definition file (.def) from a dll
|
|
||||||
* on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
|
|
||||||
*
|
|
||||||
* Copyright (c) 2005,2007 grischka
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
static char *get_export_names(int fd);
|
|
||||||
#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);
|
|
||||||
while (p > name
|
|
||||||
&& p[-1] != '/'
|
|
||||||
&& p[-1] != '\\'
|
|
||||||
)
|
|
||||||
--p;
|
|
||||||
return (char*)p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int ret, v, i;
|
|
||||||
char infile[MAX_PATH];
|
|
||||||
char outfile[MAX_PATH];
|
|
||||||
|
|
||||||
static const char *ext[] = { ".dll", ".exe", NULL };
|
|
||||||
const char *file, **pp;
|
|
||||||
char path[MAX_PATH], *p, *q;
|
|
||||||
FILE *fp, *op;
|
|
||||||
|
|
||||||
infile[0] = 0;
|
|
||||||
outfile[0] = 0;
|
|
||||||
fp = op = NULL;
|
|
||||||
v = 0;
|
|
||||||
ret = 1;
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
for (i = 1; i < argc; ++i) {
|
|
||||||
const char *a = argv[i];
|
|
||||||
if ('-' == a[0]) {
|
|
||||||
if (0 == strcmp(a, "-v")) {
|
|
||||||
v = 1;
|
|
||||||
} else if (0 == strcmp(a, "-o")) {
|
|
||||||
if (++i == argc)
|
|
||||||
goto usage;
|
|
||||||
strcpy(outfile, argv[i]);
|
|
||||||
} else
|
|
||||||
goto usage;
|
|
||||||
} else if (0 == infile[0])
|
|
||||||
strcpy(infile, a);
|
|
||||||
else
|
|
||||||
goto usage;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == infile[0]) {
|
|
||||||
usage:
|
|
||||||
fprintf(stderr,
|
|
||||||
"tiny_impdef: create export definition file (.def) from a dll\n"
|
|
||||||
"Usage: tiny_impdef library.dll [-o outputfile]\n"
|
|
||||||
);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == outfile[0])
|
|
||||||
{
|
|
||||||
strcpy(outfile, file_basename(infile));
|
|
||||||
q = strrchr(outfile, '.');
|
|
||||||
if (NULL == q)
|
|
||||||
q = strchr(outfile, 0);
|
|
||||||
strcpy(q, ".def");
|
|
||||||
}
|
|
||||||
|
|
||||||
file = infile;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
pp = ext;
|
|
||||||
do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
|
|
||||||
file = path;
|
|
||||||
break;
|
|
||||||
} while (*pp++);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fp = fopen(file, "rb");
|
|
||||||
if (NULL == fp) {
|
|
||||||
fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
if (v)
|
|
||||||
printf("--> %s\n", file);
|
|
||||||
|
|
||||||
p = get_export_names(fileno(fp));
|
|
||||||
if (NULL == p) {
|
|
||||||
fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
op = fopen(outfile, "w");
|
|
||||||
if (NULL == op) {
|
|
||||||
fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
|
|
||||||
for (q = p, i = 0; *q; ++i) {
|
|
||||||
fprintf(op, "%s\n", q);
|
|
||||||
q += strlen(q) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v) {
|
|
||||||
printf("<-- %s\n", outfile);
|
|
||||||
printf("%d symbol(s) found\n", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
the_end:
|
|
||||||
if (p)
|
|
||||||
free(p);
|
|
||||||
if (fp)
|
|
||||||
fclose(fp);
|
|
||||||
if (op)
|
|
||||||
fclose(op);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
|
||||||
{
|
|
||||||
lseek(fd, offset, SEEK_SET);
|
|
||||||
return len == read(fd, buffer, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_X86_64
|
|
||||||
# define IMAGE_FILE_MACHINE 0x8664
|
|
||||||
#elif defined TCC_TARGET_ARM
|
|
||||||
# define IMAGE_FILE_MACHINE 0x01C0
|
|
||||||
#elif 1 /* defined TCC_TARGET_I386 */
|
|
||||||
# define IMAGE_FILE_MACHINE 0x014C
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char *get_export_names(int fd)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
#else
|
|
||||||
IMAGE_OPTIONAL_HEADER32 oh;
|
|
||||||
#endif
|
|
||||||
int pef_hdroffset, opt_hdroffset, sec_hdroffset;
|
|
||||||
|
|
||||||
n = n0 = 0;
|
|
||||||
p = NULL;
|
|
||||||
|
|
||||||
if (!read_mem(fd, 0, &dh, sizeof dh))
|
|
||||||
goto the_end;
|
|
||||||
if (!read_mem(fd, 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(fd, pef_hdroffset, &ih, sizeof ih))
|
|
||||||
goto the_end;
|
|
||||||
if (IMAGE_FILE_MACHINE != ih.Machine)
|
|
||||||
goto the_end;
|
|
||||||
opt_hdroffset = pef_hdroffset + sizeof ih;
|
|
||||||
sec_hdroffset = opt_hdroffset + sizeof oh;
|
|
||||||
if (!read_mem(fd, 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(fd, 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(fd, addr - ref, &ied, sizeof ied))
|
|
||||||
goto the_end;
|
|
||||||
|
|
||||||
namep = ied.AddressOfNames - ref;
|
|
||||||
for (i = 0; i < ied.NumberOfNames; ++i) {
|
|
||||||
if (!read_mem(fd, 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(fd, ptr - ref + l++, p + n, 1)) {
|
|
||||||
tcc_free(p), p = NULL;
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
if (p[n++] == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p)
|
|
||||||
p[n] = 0;
|
|
||||||
the_end:
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
|
@ -1,278 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is for making libtcc1.a without ar
|
|
||||||
* tiny_libmaker - tiny elf lib maker
|
|
||||||
* usage: tiny_libmaker [lib] files...
|
|
||||||
* Copyright (c) 2007 Timppa
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "../../elf.h"
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
# define ELFCLASSW ELFCLASS64
|
|
||||||
# define ElfW(type) Elf##64##_##type
|
|
||||||
# define ELFW(type) ELF##64##_##type
|
|
||||||
#else
|
|
||||||
# define ELFCLASSW ELFCLASS32
|
|
||||||
# define ElfW(type) Elf##32##_##type
|
|
||||||
# define ELFW(type) ELF##32##_##type
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ARMAG "!<arch>\n"
|
|
||||||
#define ARFMAG "`\n"
|
|
||||||
|
|
||||||
typedef struct ArHdr {
|
|
||||||
char ar_name[16];
|
|
||||||
char ar_date[12];
|
|
||||||
char ar_uid[6];
|
|
||||||
char ar_gid[6];
|
|
||||||
char ar_mode[8];
|
|
||||||
char ar_size[10];
|
|
||||||
char ar_fmag[2];
|
|
||||||
} ArHdr;
|
|
||||||
|
|
||||||
unsigned long le2belong(unsigned long ul) {
|
|
||||||
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
|
|
||||||
((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArHdr arhdr = {
|
|
||||||
"/ ",
|
|
||||||
" ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
" ",
|
|
||||||
ARFMAG
|
|
||||||
};
|
|
||||||
|
|
||||||
ArHdr arhdro = {
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
" ",
|
|
||||||
ARFMAG
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Returns 1 if s contains any of the chars of list, else 0 */
|
|
||||||
int contains_any(const char *s, const char *list) {
|
|
||||||
const char *l;
|
|
||||||
for (; *s; s++) {
|
|
||||||
for (l = list; *l; l++) {
|
|
||||||
if (*s == *l)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usage(int ret) {
|
|
||||||
fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n");
|
|
||||||
fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
FILE *fi, *fh = NULL, *fo = NULL;
|
|
||||||
ElfW(Ehdr) *ehdr;
|
|
||||||
ElfW(Shdr) *shdr;
|
|
||||||
ElfW(Sym) *sym;
|
|
||||||
int i, fsize, i_lib, i_obj;
|
|
||||||
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
|
||||||
int symtabsize = 0;//, strtabsize = 0;
|
|
||||||
char *anames = NULL;
|
|
||||||
int *afpos = NULL;
|
|
||||||
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
|
||||||
char tfile[260], stmp[20];
|
|
||||||
char *file, *name;
|
|
||||||
int ret = 2;
|
|
||||||
char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
|
|
||||||
int verbose = 0;
|
|
||||||
|
|
||||||
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
const char *a = argv[i];
|
|
||||||
if (*a == '-' && strstr(a, "."))
|
|
||||||
return usage(1); // -x.y is always invalid (same as gnu ar)
|
|
||||||
if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
|
|
||||||
if (contains_any(a, ops_conflict))
|
|
||||||
return usage(1);
|
|
||||||
if (strstr(a, "v"))
|
|
||||||
verbose = 1;
|
|
||||||
} else { // lib or obj files: don't abort - keep validating all args.
|
|
||||||
if (!i_lib) // first file is the lib
|
|
||||||
i_lib = i;
|
|
||||||
else if (!i_obj) // second file is the first obj
|
|
||||||
i_obj = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!i_obj) // i_obj implies also i_lib. we require both.
|
|
||||||
return usage(1);
|
|
||||||
|
|
||||||
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't open file %s \n", argv[i_lib]);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
|
||||||
if ((fo = fopen(tfile, "wb+")) == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't create temporary file %s\n", tfile);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
funcmax = 250;
|
|
||||||
afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
|
||||||
memcpy(&arhdro.ar_mode, "100666", 6);
|
|
||||||
|
|
||||||
// i_obj = first input object file
|
|
||||||
while (i_obj < argc)
|
|
||||||
{
|
|
||||||
if (*argv[i_obj] == '-') { // by now, all options start with '-'
|
|
||||||
i_obj++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (verbose)
|
|
||||||
printf("a - %s\n", argv[i_obj]);
|
|
||||||
|
|
||||||
if ((fi = fopen(argv[i_obj], "rb")) == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't open file %s \n", argv[i_obj]);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
fseek(fi, 0, SEEK_END);
|
|
||||||
fsize = ftell(fi);
|
|
||||||
fseek(fi, 0, SEEK_SET);
|
|
||||||
buf = malloc(fsize + 1);
|
|
||||||
fread(buf, fsize, 1, fi);
|
|
||||||
fclose(fi);
|
|
||||||
|
|
||||||
// elf header
|
|
||||||
ehdr = (ElfW(Ehdr) *)buf;
|
|
||||||
if (ehdr->e_ident[4] != ELFCLASSW)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]);
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
|
|
||||||
shstr = (char *)(buf + shdr->sh_offset);
|
|
||||||
for (i = 0; i < ehdr->e_shnum; i++)
|
|
||||||
{
|
|
||||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
|
|
||||||
if (!shdr->sh_offset)
|
|
||||||
continue;
|
|
||||||
if (shdr->sh_type == SHT_SYMTAB)
|
|
||||||
{
|
|
||||||
symtab = (char *)(buf + shdr->sh_offset);
|
|
||||||
symtabsize = shdr->sh_size;
|
|
||||||
}
|
|
||||||
if (shdr->sh_type == SHT_STRTAB)
|
|
||||||
{
|
|
||||||
if (!strcmp(shstr + shdr->sh_name, ".strtab"))
|
|
||||||
{
|
|
||||||
strtab = (char *)(buf + shdr->sh_offset);
|
|
||||||
//strtabsize = shdr->sh_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symtab && symtabsize)
|
|
||||||
{
|
|
||||||
int nsym = symtabsize / sizeof(ElfW(Sym));
|
|
||||||
//printf("symtab: info size shndx name\n");
|
|
||||||
for (i = 1; i < nsym; i++)
|
|
||||||
{
|
|
||||||
sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
|
|
||||||
if (sym->st_shndx &&
|
|
||||||
(sym->st_info == 0x10
|
|
||||||
|| sym->st_info == 0x11
|
|
||||||
|| sym->st_info == 0x12
|
|
||||||
)) {
|
|
||||||
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
|
||||||
istrlen = strlen(strtab + sym->st_name)+1;
|
|
||||||
anames = realloc(anames, strpos+istrlen);
|
|
||||||
strcpy(anames + strpos, strtab + sym->st_name);
|
|
||||||
strpos += istrlen;
|
|
||||||
if (++funccnt >= funcmax) {
|
|
||||||
funcmax += 250;
|
|
||||||
afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more
|
|
||||||
}
|
|
||||||
afpos[funccnt] = fpos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file = argv[i_obj];
|
|
||||||
for (name = strchr(file, 0);
|
|
||||||
name > file && name[-1] != '/' && name[-1] != '\\';
|
|
||||||
--name);
|
|
||||||
istrlen = strlen(name);
|
|
||||||
if (istrlen >= sizeof(arhdro.ar_name))
|
|
||||||
istrlen = sizeof(arhdro.ar_name) - 1;
|
|
||||||
memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
|
|
||||||
memcpy(arhdro.ar_name, name, istrlen);
|
|
||||||
arhdro.ar_name[istrlen] = '/';
|
|
||||||
sprintf(stmp, "%-10d", fsize);
|
|
||||||
memcpy(&arhdro.ar_size, stmp, 10);
|
|
||||||
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
|
||||||
fwrite(buf, fsize, 1, fo);
|
|
||||||
free(buf);
|
|
||||||
i_obj++;
|
|
||||||
fpos += (fsize + sizeof(arhdro));
|
|
||||||
}
|
|
||||||
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
|
||||||
fpos = 0;
|
|
||||||
if ((hofs & 1)) // align
|
|
||||||
hofs++, fpos = 1;
|
|
||||||
// write header
|
|
||||||
fwrite("!<arch>\n", 8, 1, fh);
|
|
||||||
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
|
|
||||||
memcpy(&arhdr.ar_size, stmp, 10);
|
|
||||||
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
|
||||||
afpos[0] = le2belong(funccnt);
|
|
||||||
for (i=1; i<=funccnt; i++)
|
|
||||||
afpos[i] = le2belong(afpos[i] + hofs);
|
|
||||||
fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
|
|
||||||
fwrite(anames, strpos, 1, fh);
|
|
||||||
if (fpos)
|
|
||||||
fwrite("", 1, 1, fh);
|
|
||||||
// write objects
|
|
||||||
fseek(fo, 0, SEEK_END);
|
|
||||||
fsize = ftell(fo);
|
|
||||||
fseek(fo, 0, SEEK_SET);
|
|
||||||
buf = malloc(fsize + 1);
|
|
||||||
fread(buf, fsize, 1, fo);
|
|
||||||
fwrite(buf, fsize, 1, fh);
|
|
||||||
free(buf);
|
|
||||||
ret = 0;
|
|
||||||
the_end:
|
|
||||||
if (anames)
|
|
||||||
free(anames);
|
|
||||||
if (afpos)
|
|
||||||
free(afpos);
|
|
||||||
if (fh)
|
|
||||||
fclose(fh);
|
|
||||||
if (fo)
|
|
||||||
fclose(fo), remove(tfile);
|
|
||||||
return ret;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user