History

win32: enable bounds checker & exception handler

exception handler borrowed from k1w1. Thanks.

grischka committed 16 years ago

Commit 7fa712e1 parent 8bbde9111 files · +421 −331Browse files

Unified · Split

11 files
  1. Makefile +2 −5
  2. i386-gen.c +5 −1
  3. lib/bcheck.c +9 −34
  4. libtcc.c +6 −2
  5. tcc.h +4 −7
  6. tccelf.c +42 −33
  7. tccgen.c +12 −1
  8. tccpe.c +3 −3
  9. tccrun.c +321 −242
  10. tcctok.h +3 −1
  11. win32/build-tcc.bat +14 −2
Makefile+2−5
@@ -78,7 +78,7 @@ ARM_CROSS = arm-tcc-fpa$(EXESUF) arm-tcc-fpa-ld$(EXESUF) \ · 77 unmodified lines
78 arm-tcc-vfp$(EXESUF) arm-tcc-vfp-eabi$(EXESUF)78 arm-tcc-vfp$(EXESUF) arm-tcc-vfp-eabi$(EXESUF)
79C67_CROSS = c67-tcc$(EXESUF)79C67_CROSS = c67-tcc$(EXESUF)
80 80
81CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c \81CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c \
82 tcc.h config.h libtcc.h tcctok.h82 tcc.h config.h libtcc.h tcctok.h
83I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h83I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h
84WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c84WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
@@ -180,7 +180,7 @@ VPATH+=lib · 95 unmodified lines
180 180
181ifdef CONFIG_WIN32181ifdef CONFIG_WIN32
182# for windows, we must use TCC because we generate ELF objects182# for windows, we must use TCC because we generate ELF objects
183LIBTCC1_OBJS+=crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o183LIBTCC1_OBJS+=crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o bcheck.o
184LIBTCC1_CC=./tcc.exe -Bwin32 -Iinclude $(NATIVE_TARGET)184LIBTCC1_CC=./tcc.exe -Bwin32 -Iinclude $(NATIVE_TARGET)
185VPATH+=win32/lib185VPATH+=win32/lib
186endif186endif
@@ -193,9 +193,6 @@ endif · 6 unmodified lines
193libtcc1.a: $(LIBTCC1_OBJS)193libtcc1.a: $(LIBTCC1_OBJS)
194 $(AR) rcs $@ $^194 $(AR) rcs $@ $^
195 195
196bcheck.o: bcheck.c
197 $(CC) -o $@ -c $< -O2 -Wall
198
199# install196# install
200TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h tcclib.h197TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h tcclib.h
201INSTALL=install198INSTALL=install
i386-gen.c+5−1
@@ -87,8 +87,10 @@ const int reg_classes[NB_REGS] = { · 86 unmodified lines
87/******************************************************/87/******************************************************/
88 88
89static unsigned long func_sub_sp_offset;89static unsigned long func_sub_sp_offset;
90static unsigned long func_bound_offset;
91static int func_ret_sub;90static int func_ret_sub;
91#ifdef CONFIG_TCC_BCHECK
92static unsigned long func_bound_offset;
93#endif
92 94
93/* XXX: make it faster ? */95/* XXX: make it faster ? */
94void g(int c)96void g(int c)
@@ -511,12 +513,14 @@ void gfunc_prolog(CType *func_type) · 416 unmodified lines
511 func_ret_sub = 4;513 func_ret_sub = 4;
512#endif514#endif
513 515
516#ifdef CONFIG_TCC_BCHECK
514 /* leave some room for bound checking code */517 /* leave some room for bound checking code */
515 if (tcc_state->do_bounds_check) {518 if (tcc_state->do_bounds_check) {
516 oad(0xb8, 0); /* lbound section pointer */519 oad(0xb8, 0); /* lbound section pointer */
517 oad(0xb8, 0); /* call to function */520 oad(0xb8, 0); /* call to function */
518 func_bound_offset = lbounds_section->data_offset;521 func_bound_offset = lbounds_section->data_offset;
519 }522 }
523#endif
520}524}
521 525
522/* generate function epilog */526/* generate function epilog */
lib/bcheck.c+9−34
@@ -33,12 +33,11 @@ · 32 unmodified lines
33 33
34/* use malloc hooks. Currently the code cannot be reliable if no hooks */34/* use malloc hooks. Currently the code cannot be reliable if no hooks */
35#define CONFIG_TCC_MALLOC_HOOKS35#define CONFIG_TCC_MALLOC_HOOKS
36
37#define HAVE_MEMALIGN36#define HAVE_MEMALIGN
38 37
39#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__dietlibc__) \38#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__dietlibc__) \
40 || defined(__UCLIBC__) || defined(__OpenBSD__)39 || defined(__UCLIBC__) || defined(__OpenBSD__) || defined(_WIN32)
41#warning Bound checking not fully supported in this environment.40#warning Bound checking does not support malloc (etc.) in this environment.
42#undef CONFIG_TCC_MALLOC_HOOKS41#undef CONFIG_TCC_MALLOC_HOOKS
43#undef HAVE_MEMALIGN42#undef HAVE_MEMALIGN
44#endif43#endif
@@ -152,9 +151,6 @@ static void bound_alloc_error(void) · 107 unmodified lines
152 bound_error("not enough memory for bound checking code");151 bound_error("not enough memory for bound checking code");
153}152}
154 153
155/* currently, tcc cannot compile that because we use GNUC extensions */
156#if !defined(__TINYC__)
157
158/* return '(p + offset)' for pointer arithmetic (a pointer can reach154/* return '(p + offset)' for pointer arithmetic (a pointer can reach
159 the end of a region in this case */155 the end of a region in this case */
160void * FASTCALL __bound_ptr_add(void *p, int offset)156void * FASTCALL __bound_ptr_add(void *p, int offset)
@@ -203,6 +199,13 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \ · 42 unmodified lines
203 return p + offset; \199 return p + offset; \
204}200}
205 201
202BOUND_PTR_INDIR(1)
203BOUND_PTR_INDIR(2)
204BOUND_PTR_INDIR(4)
205BOUND_PTR_INDIR(8)
206BOUND_PTR_INDIR(12)
207BOUND_PTR_INDIR(16)
208
206#ifdef __i386__209#ifdef __i386__
207/* return the frame pointer of the caller */210/* return the frame pointer of the caller */
208#define GET_CALLER_FP(fp)\211#define GET_CALLER_FP(fp)\
@@ -246,34 +249,6 @@ void FASTCALL __bound_local_delete(void *p1) · 37 unmodified lines
246 }249 }
247}250}
248 251
249#else
250
251void __bound_local_new(void *p)
252{
253}
254void __bound_local_delete(void *p)
255{
256}
257
258void *__bound_ptr_add(void *p, int offset)
259{
260 return p + offset;
261}
262
263#define BOUND_PTR_INDIR(dsize) \
264void *__bound_ptr_indir ## dsize (void *p, int offset) \
265{ \
266 return p + offset; \
267}
268#endif
269
270BOUND_PTR_INDIR(1)
271BOUND_PTR_INDIR(2)
272BOUND_PTR_INDIR(4)
273BOUND_PTR_INDIR(8)
274BOUND_PTR_INDIR(12)
275BOUND_PTR_INDIR(16)
276
277static BoundEntry *__bound_new_page(void)252static BoundEntry *__bound_new_page(void)
278{253{
279 BoundEntry *page;254 BoundEntry *page;
libtcc.c+6−2
@@ -58,9 +58,13 @@ static Section *cur_text_section; /* current section where function code is · 57 unmodified lines
58#ifdef CONFIG_TCC_ASM58#ifdef CONFIG_TCC_ASM
59static Section *last_text_section; /* to handle .previous asm directive */59static Section *last_text_section; /* to handle .previous asm directive */
60#endif60#endif
61
62#ifdef CONFIG_TCC_BCHECK
61/* bound check related sections */63/* bound check related sections */
62static Section *bounds_section; /* contains global data bound description */64static Section *bounds_section; /* contains global data bound description */
63static Section *lbounds_section; /* contains local data bound description */65static Section *lbounds_section; /* contains local data bound description */
66#endif
67
64/* symbol sections */68/* symbol sections */
65static Section *symtab_section, *strtab_section;69static Section *symtab_section, *strtab_section;
66 70
@@ -109,8 +113,8 @@ static int tcc_ext = 1; · 42 unmodified lines
109/* max number of callers shown if error */113/* max number of callers shown if error */
110#ifdef CONFIG_TCC_BACKTRACE114#ifdef CONFIG_TCC_BACKTRACE
111int num_callers = 6;115int num_callers = 6;
116void *rt_prog_main;
112const char **rt_bound_error_msg;117const char **rt_bound_error_msg;
113unsigned long rt_prog_main;
114#endif118#endif
115 119
116/* XXX: get rid of this ASAP */120/* XXX: get rid of this ASAP */
@@ -731,7 +735,7 @@ static void put_extern_sym2(Sym *sym, Section *section, · 614 unmodified lines
731 /* if bound checking is activated, we change some function735 /* if bound checking is activated, we change some function
732 names by adding the "__bound" prefix */736 names by adding the "__bound" prefix */
733 switch(sym->v) {737 switch(sym->v) {
734#if 0738#ifdef TCC_TARGET_PE
735 /* XXX: we rely only on malloc hooks */739 /* XXX: we rely only on malloc hooks */
736 case TOK_malloc: 740 case TOK_malloc:
737 case TOK_free: 741 case TOK_free:
tcc.h+4−7
@@ -101,7 +101,7 @@ · 100 unmodified lines
101#define TCC_TARGET_I386101#define TCC_TARGET_I386
102#endif102#endif
103 103
104#if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \104#if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
105 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)105 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
106#define CONFIG_TCC_BCHECK /* enable bound checking code */106#define CONFIG_TCC_BCHECK /* enable bound checking code */
107#endif107#endif
@@ -120,7 +120,7 @@ · 12 unmodified lines
120#define TCC_TARGET_COFF120#define TCC_TARGET_COFF
121#endif121#endif
122 122
123#if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)123#if !defined(CONFIG_TCCBOOT)
124#define CONFIG_TCC_BACKTRACE124#define CONFIG_TCC_BACKTRACE
125#endif125#endif
126 126
@@ -465,8 +465,10 @@ struct TCCState { · 338 unmodified lines
465 int verbose;465 int verbose;
466 /* compile with debug symbol (and use them if error during execution) */466 /* compile with debug symbol (and use them if error during execution) */
467 int do_debug;467 int do_debug;
468#ifdef CONFIG_TCC_BCHECK
468 /* compile with built-in memory and bounds checker */469 /* compile with built-in memory and bounds checker */
469 int do_bounds_check;470 int do_bounds_check;
471#endif
470 /* give the path of the tcc libraries */472 /* give the path of the tcc libraries */
471 char *tcc_lib_path;473 char *tcc_lib_path;
472 474
@@ -809,11 +811,6 @@ char *pstrcat(char *buf, int buf_size, const char *s); · 336 unmodified lines
809void dynarray_add(void ***ptab, int *nb_ptr, void *data);811void dynarray_add(void ***ptab, int *nb_ptr, void *data);
810void dynarray_reset(void *pp, int *n);812void dynarray_reset(void *pp, int *n);
811 813
812#ifdef CONFIG_TCC_BACKTRACE
813extern int num_callers;
814extern const char **rt_bound_error_msg;
815#endif
816
817/* true if float/double/long double type */814/* true if float/double/long double type */
818static inline int is_float(int t)815static inline int is_float(int t)
819{816{
tccelf.c+42−33
@@ -1186,50 +1186,59 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 1185 unmodified lines
1186 s->sh_num, sym_end);1186 s->sh_num, sym_end);
1187}1187}
1188 1188
1189/* add tcc runtime libraries */1189static void tcc_add_bcheck(TCCState *s1)
1190static void tcc_add_runtime(TCCState *s1)
1191{1190{
1192#if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)1191#ifdef CONFIG_TCC_BCHECK
1192 unsigned long *ptr;
1193 Section *init_section;
1194 unsigned char *pinit;
1195 int sym_index;
1196
1197 if (0 == s1->do_bounds_check)
1198 return;
1199
1200 /* XXX: add an object file to do that */
1201 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1202 *ptr = 0;
1203 add_elf_sym(symtab_section, 0, 0,
1204 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1205 bounds_section->sh_num, "__bounds_start");
1206 /* add bound check code */
1207#ifndef TCC_TARGET_PE
1208 {
1193 char buf[1024];1209 char buf[1024];
1210 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1211 tcc_add_file(s1, buf);
1212 }
1194#endif1213#endif
1195
1196#ifdef CONFIG_TCC_BCHECK
1197 if (s1->do_bounds_check) {
1198 unsigned long *ptr;
1199 Section *init_section;
1200 unsigned char *pinit;
1201 int sym_index;
1202
1203 /* XXX: add an object file to do that */
1204 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1205 *ptr = 0;
1206 add_elf_sym(symtab_section, 0, 0,
1207 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1208 bounds_section->sh_num, "__bounds_start");
1209 /* add bound check code */
1210 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1211 tcc_add_file(s1, buf);
1212#ifdef TCC_TARGET_I3861214#ifdef TCC_TARGET_I386
1213 if (s1->output_type != TCC_OUTPUT_MEMORY) {1215 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1214 /* add 'call __bound_init()' in .init section */1216 /* add 'call __bound_init()' in .init section */
1215 init_section = find_section(s1, ".init");1217 init_section = find_section(s1, ".init");
1216 pinit = section_ptr_add(init_section, 5);1218 pinit = section_ptr_add(init_section, 5);
1217 pinit[0] = 0xe8;1219 pinit[0] = 0xe8;
1218 put32(pinit + 1, -4);1220 put32(pinit + 1, -4);
1219 sym_index = find_elf_sym(symtab_section, "__bound_init");1221 sym_index = find_elf_sym(symtab_section, "__bound_init");
1220 put_elf_reloc(symtab_section, init_section, 1222 put_elf_reloc(symtab_section, init_section,
1221 init_section->data_offset - 4, R_386_PC32, sym_index);1223 init_section->data_offset - 4, R_386_PC32, sym_index);
1222 }
1223#endif
1224 }1224 }
1225#endif1225#endif
1226#endif
1227}
1228
1229/* add tcc runtime libraries */
1230static void tcc_add_runtime(TCCState *s1)
1231{
1232 tcc_add_bcheck(s1);
1233
1226 /* add libc */1234 /* add libc */
1227 if (!s1->nostdlib) {1235 if (!s1->nostdlib) {
1228 tcc_add_library(s1, "c");
1229
1230#ifdef CONFIG_USE_LIBGCC1236#ifdef CONFIG_USE_LIBGCC
1237 tcc_add_library(s1, "c");
1231 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");1238 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1232#else1239#else
1240 char buf[1024];
1241 tcc_add_library(s1, "c");
1233 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");1242 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1234 tcc_add_file(s1, buf);1243 tcc_add_file(s1, buf);
1235#endif1244#endif
tccgen.c+12−1
@@ -2911,8 +2911,10 @@ static void indir(void) · 2910 unmodified lines
2911 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {2911 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
2912 vtop->r |= lvalue_type(vtop->type.t);2912 vtop->r |= lvalue_type(vtop->type.t);
2913 /* if bound checking, the referenced pointer must be checked */2913 /* if bound checking, the referenced pointer must be checked */
2914#ifdef CONFIG_TCC_BCHECK
2914 if (tcc_state->do_bounds_check)2915 if (tcc_state->do_bounds_check)
2915 vtop->r |= VT_MUSTBOUND;2916 vtop->r |= VT_MUSTBOUND;
2917#endif
2916 }2918 }
2917}2919}
2918 2920
@@ -3328,9 +3330,11 @@ static void unary(void) · 409 unmodified lines
3328 /* an array is never an lvalue */3330 /* an array is never an lvalue */
3329 if (!(vtop->type.t & VT_ARRAY)) {3331 if (!(vtop->type.t & VT_ARRAY)) {
3330 vtop->r |= lvalue_type(vtop->type.t);3332 vtop->r |= lvalue_type(vtop->type.t);
3333#ifdef CONFIG_TCC_BCHECK
3331 /* if bound checking, the referenced pointer must be checked */3334 /* if bound checking, the referenced pointer must be checked */
3332 if (tcc_state->do_bounds_check)3335 if (tcc_state->do_bounds_check)
3333 vtop->r |= VT_MUSTBOUND;3336 vtop->r |= VT_MUSTBOUND;
3337#endif
3334 }3338 }
3335 next();3339 next();
3336 } else if (tok == '[') {3340 } else if (tok == '[') {
@@ -4702,10 +4706,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 1365 unmodified lines
4702 }4706 }
4703 if ((r & VT_VALMASK) == VT_LOCAL) {4707 if ((r & VT_VALMASK) == VT_LOCAL) {
4704 sec = NULL;4708 sec = NULL;
4709#ifdef CONFIG_TCC_BCHECK
4705 if (tcc_state->do_bounds_check && (type->t & VT_ARRAY))4710 if (tcc_state->do_bounds_check && (type->t & VT_ARRAY))
4706 loc--;4711 loc--;
4712#endif
4707 loc = (loc - size) & -align;4713 loc = (loc - size) & -align;
4708 addr = loc;4714 addr = loc;
4715#ifdef CONFIG_TCC_BCHECK
4709 /* handles bounds */4716 /* handles bounds */
4710 /* XXX: currently, since we do only one pass, we cannot track4717 /* XXX: currently, since we do only one pass, we cannot track
4711 '&' operators, so we add only arrays */4718 '&' operators, so we add only arrays */
@@ -4718,6 +4725,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 6 unmodified lines
4718 bounds_ptr[0] = addr;4725 bounds_ptr[0] = addr;
4719 bounds_ptr[1] = size;4726 bounds_ptr[1] = size;
4720 }4727 }
4728#endif
4721 if (v) {4729 if (v) {
4722 /* local variable */4730 /* local variable */
4723 sym_push(v, type, r, addr);4731 sym_push(v, type, r, addr);
@@ -4774,9 +4782,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 50 unmodified lines
4774 /* very important to increment global pointer at this time4782 /* very important to increment global pointer at this time
4775 because initializers themselves can create new initializers */4783 because initializers themselves can create new initializers */
4776 data_offset += size;4784 data_offset += size;
4785#ifdef CONFIG_TCC_BCHECK
4777 /* add padding if bound check */4786 /* add padding if bound check */
4778 if (tcc_state->do_bounds_check)4787 if (tcc_state->do_bounds_check)
4779 data_offset++;4788 data_offset++;
4789#endif
4780 sec->data_offset = data_offset;4790 sec->data_offset = data_offset;
4781 /* allocate section space to put the data */4791 /* allocate section space to put the data */
4782 if (sec->sh_type != SHT_NOBITS && 4792 if (sec->sh_type != SHT_NOBITS &&
@@ -4813,7 +4823,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 30 unmodified lines
4813 vsetc(type, VT_CONST | VT_SYM, &cval);4823 vsetc(type, VT_CONST | VT_SYM, &cval);
4814 vtop->sym = sym;4824 vtop->sym = sym;
4815 }4825 }
4816 4826#ifdef CONFIG_TCC_BCHECK
4817 /* handles bounds now because the symbol must be defined4827 /* handles bounds now because the symbol must be defined
4818 before for the relocation */4828 before for the relocation */
4819 if (tcc_state->do_bounds_check) {4829 if (tcc_state->do_bounds_check) {
@@ -4825,6 +4835,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 5 unmodified lines
4825 bounds_ptr[0] = 0; /* relocated */4835 bounds_ptr[0] = 0; /* relocated */
4826 bounds_ptr[1] = size;4836 bounds_ptr[1] = size;
4827 }4837 }
4838#endif
4828 }4839 }
4829 if (has_init) {4840 if (has_init) {
4830 decl_initializer(type, sec, addr, 1, 0);4841 decl_initializer(type, sec, addr, 1, 0);
tccpe.c+3−3
@@ -1700,15 +1700,15 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename) · 1699 unmodified lines
1700 pe.filename = filename;1700 pe.filename = filename;
1701 pe.s1 = s1;1701 pe.s1 = s1;
1702 1702
1703 tcc_add_bcheck(s1);
1703 pe_add_runtime_ex(s1, &pe);1704 pe_add_runtime_ex(s1, &pe);
1704 relocate_common_syms(); /* assign bss adresses */1705 relocate_common_syms(); /* assign bss adresses */
1705 tcc_add_linker_symbols(s1);1706 tcc_add_linker_symbols(s1);
1706 1707
1707 ret = pe_check_symbols(&pe);1708 ret = pe_check_symbols(&pe);
1708 if (ret)1709 if (ret)
1709 return ret;1710 ;
1710 1711 else if (filename) {
1711 if (filename) {
1712 if (PE_DLL == pe.type) {1712 if (PE_DLL == pe.type) {
1713 pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);1713 pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
1714 /* XXX: check if is correct for arm-pe target */1714 /* XXX: check if is correct for arm-pe target */
tccrun.c+321−242
@@ -20,75 +20,167 @@ · 19 unmodified lines
20 20
21/* tccrun.c - support for tcc -run */21/* tccrun.c - support for tcc -run */
22 22
23#ifdef _WIN32
24#define ucontext_t CONTEXT
25#endif
23 26
24/********************************************************/27static void set_pages_executable(void *ptr, unsigned long length);
25#ifdef CONFIG_TCC_STATIC28static void set_exception_handler(void);
29static int rt_get_caller_pc(unsigned long *paddr, ucontext_t *uc, int level);
30static void rt_error(ucontext_t *uc, const char *fmt, ...);
31static int tcc_relocate_ex(TCCState *s1, void *ptr);
26 32
27#define RTLD_LAZY 0x00133/* ------------------------------------------------------------- */
28#define RTLD_NOW 0x00234/* Do all relocations (needed before using tcc_get_symbol())
29#define RTLD_GLOBAL 0x10035 Returns -1 on error. */
30#define RTLD_DEFAULT NULL
31 36
32/* dummy function for profiling */37int tcc_relocate(TCCState *s1)
33void *dlopen(const char *filename, int flag)
34{38{
35 return NULL;39 int ret;
36}
37 40
38void dlclose(void *p)41 ret = tcc_relocate_ex(s1, NULL);
39{42 if (-1 != ret) {
43 s1->runtime_mem = tcc_malloc(ret);
44 ret = tcc_relocate_ex(s1, s1->runtime_mem);
45 }
46 return ret;
40}47}
41 48
42const char *dlerror(void)49/* launch the compiled program with the given arguments */
50int tcc_run(TCCState *s1, int argc, char **argv)
43{51{
44 return "error";52 int (*prog_main)(int, char **);
45}
46 53
47typedef struct TCCSyms {54 if (tcc_relocate(s1) < 0)
48 char *str;55 return -1;
49 void *ptr;
50} TCCSyms;
51 56
52#define TCCSYM(a) { #a, &a, },57 prog_main = tcc_get_symbol_err(s1, "main");
53 58
54/* add the symbol you want here if no dynamic linking is done */59#ifdef CONFIG_TCC_BACKTRACE
55static TCCSyms tcc_syms[] = {60 if (s1->do_debug)
56#if !defined(CONFIG_TCCBOOT)61 set_exception_handler();
57 TCCSYM(printf)
58 TCCSYM(fprintf)
59 TCCSYM(fopen)
60 TCCSYM(fclose)
61#endif62#endif
62 { NULL, NULL },
63};
64 63
65void *resolve_sym(TCCState *s1, const char *symbol)64#ifdef CONFIG_TCC_BCHECK
66{65 if (s1->do_bounds_check) {
67 TCCSyms *p;66 void (*bound_init)(void);
68 p = tcc_syms;67 void (*bound_exit)(void);
69 while (p->str != NULL) {68 int ret;
70 if (!strcmp(p->str, symbol))69 /* set error function */
71 return p->ptr;70 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
72 p++;71 rt_prog_main = prog_main;
72 /* XXX: use .init section so that it also work in binary ? */
73 bound_init = tcc_get_symbol_err(s1, "__bound_init");
74 bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
75 bound_init();
76 ret = (*prog_main)(argc, argv);
77 bound_exit();
78 return ret;
73 }79 }
74 return NULL;80#endif
81 return (*prog_main)(argc, argv);
75}82}
76 83
77#elif defined(_WIN32)
78#define dlclose FreeLibrary
79 84
85/* relocate code. Return -1 on error, required size if ptr is NULL,
86 otherwise copy code into buffer passed by the caller */
87static int tcc_relocate_ex(TCCState *s1, void *ptr)
88{
89 Section *s;
90 unsigned long offset, length;
91 uplong mem;
92 int i;
93
94 if (0 == s1->runtime_added) {
95 s1->runtime_added = 1;
96 s1->nb_errors = 0;
97#ifdef TCC_TARGET_PE
98 pe_output_file(s1, NULL);
80#else99#else
81#include <dlfcn.h>100 tcc_add_runtime(s1);
101 relocate_common_syms();
102 tcc_add_linker_symbols(s1);
103 build_got_entries(s1);
104#endif
105 if (s1->nb_errors)
106 return -1;
107 }
82 108
83void *resolve_sym(TCCState *s1, const char *sym)109 offset = 0, mem = (uplong)ptr;
84{110 for(i = 1; i < s1->nb_sections; i++) {
85 return dlsym(RTLD_DEFAULT, sym);111 s = s1->sections[i];
112 if (0 == (s->sh_flags & SHF_ALLOC))
113 continue;
114 length = s->data_offset;
115 s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
116 offset = (offset + length + 15) & ~15;
117 }
118 offset += 16;
119
120 /* relocate symbols */
121 relocate_syms(s1, 1);
122 if (s1->nb_errors)
123 return -1;
124
125#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
126 s1->runtime_plt_and_got_offset = 0;
127 s1->runtime_plt_and_got = (char *)(mem + offset);
128 /* double the size of the buffer for got and plt entries
129 XXX: calculate exact size for them? */
130 offset *= 2;
131#endif
132
133 if (0 == mem)
134 return offset;
135
136 /* relocate each section */
137 for(i = 1; i < s1->nb_sections; i++) {
138 s = s1->sections[i];
139 if (s->reloc)
140 relocate_section(s1, s);
141 }
142
143 for(i = 1; i < s1->nb_sections; i++) {
144 s = s1->sections[i];
145 if (0 == (s->sh_flags & SHF_ALLOC))
146 continue;
147 length = s->data_offset;
148 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
149 ptr = (void*)(uplong)s->sh_addr;
150 if (NULL == s->data || s->sh_type == SHT_NOBITS)
151 memset(ptr, 0, length);
152 else
153 memcpy(ptr, s->data, length);
154 /* mark executable sections as executable in memory */
155 if (s->sh_flags & SHF_EXECINSTR)
156 set_pages_executable(ptr, length);
157 }
158
159#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
160 set_pages_executable(s1->runtime_plt_and_got,
161 s1->runtime_plt_and_got_offset);
162#endif
163 return 0;
86}164}
87 165
88#endif /* defined CONFIG_TCC_STATIC */166/* ------------------------------------------------------------- */
167/* allow to run code in memory */
89 168
90/********************************************************/169static void set_pages_executable(void *ptr, unsigned long length)
170{
171#ifdef _WIN32
172 unsigned long old_protect;
173 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
174#else
175 unsigned long start, end;
176 start = (unsigned long)ptr & ~(PAGESIZE - 1);
177 end = (unsigned long)ptr + length;
178 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
179 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
180#endif
181}
91 182
183/* ------------------------------------------------------------- */
92#ifdef CONFIG_TCC_BACKTRACE184#ifdef CONFIG_TCC_BACKTRACE
93 185
94/* print the position in the source file of PC value 'pc' by reading186/* print the position in the source file of PC value 'pc' by reading
@@ -215,7 +307,92 @@ static unsigned long rt_printline(unsigned long wanted_pc) · 120 unmodified lines
215 return func_addr;307 return func_addr;
216}308}
217 309
310/* emit a run time error at position 'pc' */
311static void rt_error(ucontext_t *uc, const char *fmt, ...)
312{
313 va_list ap;
314 unsigned long pc;
315 int i;
316
317 va_start(ap, fmt);
318 fprintf(stderr, "Runtime error: ");
319 vfprintf(stderr, fmt, ap);
320 fprintf(stderr, "\n");
321
322 for(i=0;i<num_callers;i++) {
323 if (rt_get_caller_pc(&pc, uc, i) < 0)
324 break;
325 if (i == 0)
326 fprintf(stderr, "at ");
327 else
328 fprintf(stderr, "by ");
329 pc = rt_printline(pc);
330 if (pc == (unsigned long)rt_prog_main && pc)
331 break;
332 }
333 exit(255);
334 va_end(ap);
335}
336
337/* ------------------------------------------------------------- */
338#ifndef _WIN32
339
340/* signal handler for fatal errors */
341static void sig_error(int signum, siginfo_t *siginf, void *puc)
342{
343 ucontext_t *uc = puc;
344
345 switch(signum) {
346 case SIGFPE:
347 switch(siginf->si_code) {
348 case FPE_INTDIV:
349 case FPE_FLTDIV:
350 rt_error(uc, "division by zero");
351 break;
352 default:
353 rt_error(uc, "floating point exception");
354 break;
355 }
356 break;
357 case SIGBUS:
358 case SIGSEGV:
359 if (rt_bound_error_msg && *rt_bound_error_msg)
360 rt_error(uc, *rt_bound_error_msg);
361 else
362 rt_error(uc, "dereferencing invalid pointer");
363 break;
364 case SIGILL:
365 rt_error(uc, "illegal instruction");
366 break;
367 case SIGABRT:
368 rt_error(uc, "abort() called");
369 break;
370 default:
371 rt_error(uc, "caught signal %d", signum);
372 break;
373 }
374 exit(255);
375}
376
377/* Generate a stack backtrace when a CPU exception occurs. */
378static void set_exception_handler(void)
379{
380 struct sigaction sigact;
381 /* install TCC signal handlers to print debug info on fatal
382 runtime errors */
383 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
384 sigact.sa_sigaction = sig_error;
385 sigemptyset(&sigact.sa_mask);
386 sigaction(SIGFPE, &sigact, NULL);
387 sigaction(SIGILL, &sigact, NULL);
388 sigaction(SIGSEGV, &sigact, NULL);
389 sigaction(SIGBUS, &sigact, NULL);
390 sigaction(SIGABRT, &sigact, NULL);
391}
392
393/* ------------------------------------------------------------- */
218#ifdef __i386__394#ifdef __i386__
395
219/* fix for glibc 2.1 */396/* fix for glibc 2.1 */
220#ifndef REG_EIP397#ifndef REG_EIP
221#define REG_EIP EIP398#define REG_EIP EIP
@@ -223,8 +400,7 @@ static unsigned long rt_printline(unsigned long wanted_pc) · 1 unmodified line
223#endif400#endif
224 401
225/* return the PC at frame level 'level'. Return non zero if not found */402/* return the PC at frame level 'level'. Return non zero if not found */
226static int rt_get_caller_pc(unsigned long *paddr,403static int rt_get_caller_pc(unsigned long *paddr, ucontext_t *uc, int level)
227 ucontext_t *uc, int level)
228{404{
229 unsigned long fp;405 unsigned long fp;
230 int i;406 int i;
@@ -256,7 +432,10 @@ static int rt_get_caller_pc(unsigned long *paddr, · 25 unmodified lines
256 return 0;432 return 0;
257 }433 }
258}434}
435
436/* ------------------------------------------------------------- */
259#elif defined(__x86_64__)437#elif defined(__x86_64__)
438
260/* return the PC at frame level 'level'. Return non zero if not found */439/* return the PC at frame level 'level'. Return non zero if not found */
261static int rt_get_caller_pc(unsigned long *paddr,440static int rt_get_caller_pc(unsigned long *paddr,
262 ucontext_t *uc, int level)441 ucontext_t *uc, int level)
@@ -288,236 +467,136 @@ static int rt_get_caller_pc(unsigned long *paddr, · 25 unmodified lines
288 return 0;467 return 0;
289 }468 }
290}469}
470
471/* ------------------------------------------------------------- */
291#else472#else
473
292#warning add arch specific rt_get_caller_pc()474#warning add arch specific rt_get_caller_pc()
293static int rt_get_caller_pc(unsigned long *paddr,475static int rt_get_caller_pc(unsigned long *paddr,
294 ucontext_t *uc, int level)476 ucontext_t *uc, int level)
295{477{
296 return -1;478 return -1;
297}479}
298#endif
299 480
300/* emit a run time error at position 'pc' */481#endif /* !__i386__ */
301void rt_error(ucontext_t *uc, const char *fmt, ...)
302{
303 va_list ap;
304 unsigned long pc;
305 int i;
306 482
307 va_start(ap, fmt);483/* ------------------------------------------------------------- */
308 fprintf(stderr, "Runtime error: ");484#else /* WIN32 */
309 vfprintf(stderr, fmt, ap);
310 fprintf(stderr, "\n");
311 for(i=0;i<num_callers;i++) {
312 if (rt_get_caller_pc(&pc, uc, i) < 0)
313 break;
314 if (i == 0)
315 fprintf(stderr, "at ");
316 else
317 fprintf(stderr, "by ");
318 pc = rt_printline(pc);
319 if (pc == rt_prog_main && pc)
320 break;
321 }
322 exit(255);
323 va_end(ap);
324}
325 485
326/* signal handler for fatal errors */486static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
327static void sig_error(int signum, siginfo_t *siginf, void *puc)
328{487{
329 ucontext_t *uc = puc;488 CONTEXT *uc = ex_info->ContextRecord;
330 489/*
331 switch(signum) {490 EXCEPTION_RECORD *er = ex_info->ExceptionRecord;
332 case SIGFPE:491 printf("CPU exception: code=%08lx addr=%p\n",
333 switch(siginf->si_code) {492 er->ExceptionCode, er->ExceptionAddress);
334 case FPE_INTDIV:493*/
335 case FPE_FLTDIV:494 if (rt_bound_error_msg && *rt_bound_error_msg)
336 rt_error(uc, "division by zero");495 rt_error(uc, *rt_bound_error_msg);
337 break;496 else
338 default:497 rt_error(uc, "dereferencing invalid pointer");
339 rt_error(uc, "floating point exception");
340 break;
341 }
342 break;
343 case SIGBUS:
344 case SIGSEGV:
345 if (rt_bound_error_msg && *rt_bound_error_msg)
346 rt_error(uc, *rt_bound_error_msg);
347 else
348 rt_error(uc, "dereferencing invalid pointer");
349 break;
350 case SIGILL:
351 rt_error(uc, "illegal instruction");
352 break;
353 case SIGABRT:
354 rt_error(uc, "abort() called");
355 break;
356 default:
357 rt_error(uc, "caught signal %d", signum);
358 break;
359 }
360 exit(255);498 exit(255);
499 //return EXCEPTION_CONTINUE_SEARCH;
361}500}
362 501
363#endif /* defined CONFIG_TCC_BACKTRACE */502/* Generate a stack backtrace when a CPU exception occurs. */
364 503static void set_exception_handler(void)
365/********************************************************/
366
367void set_pages_executable(void *ptr, unsigned long length)
368{504{
369#ifdef _WIN32505 SetUnhandledExceptionFilter(cpu_exception_handler);
370 unsigned long old_protect;
371 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
372#else
373 unsigned long start, end;
374 start = (unsigned long)ptr & ~(PAGESIZE - 1);
375 end = (unsigned long)ptr + length;
376 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
377 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
378#endif
379}506}
380 507
381/* relocate code. Return -1 on error, required size if ptr is NULL,508/* return the PC at frame level 'level'. Return non zero if not found */
382 otherwise copy code into buffer passed by the caller */509static int rt_get_caller_pc(unsigned long *paddr,
383static int tcc_relocate_ex(TCCState *s1, void *ptr)510 CONTEXT *uc, int level)
384{511{
385 Section *s;512 unsigned long fp;
386 unsigned long offset, length;
387 uplong mem;
388 int i;513 int i;
389 514
390 if (0 == s1->runtime_added) {515 if (level == 0) {
391 s1->runtime_added = 1;516 *paddr = uc->Eip;
392 s1->nb_errors = 0;517 return 0;
393#ifdef TCC_TARGET_PE518 } else {
394 pe_output_file(s1, NULL);519 fp = uc->Ebp;
395#else520 for(i=1;i<level;i++) {
396 tcc_add_runtime(s1);521 /* XXX: check address validity with program info */
397 relocate_common_syms();522 if (fp <= 0x1000 || fp >= 0xc0000000)
398 tcc_add_linker_symbols(s1);523 return -1;
399 build_got_entries(s1);524 fp = ((unsigned long *)fp)[0];
400#endif525 }
401 if (s1->nb_errors)526 *paddr = ((unsigned long *)fp)[1];
402 return -1;527 return 0;
403 }
404
405 offset = 0, mem = (uplong)ptr;
406 for(i = 1; i < s1->nb_sections; i++) {
407 s = s1->sections[i];
408 if (0 == (s->sh_flags & SHF_ALLOC))
409 continue;
410 length = s->data_offset;
411 s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
412 offset = (offset + length + 15) & ~15;
413 }528 }
414 offset += 16;529}
415
416 /* relocate symbols */
417 relocate_syms(s1, 1);
418 if (s1->nb_errors)
419 return -1;
420
421#ifndef TCC_TARGET_PE
422#ifdef TCC_TARGET_X86_64
423 s1->runtime_plt_and_got_offset = 0;
424 s1->runtime_plt_and_got = (char *)(mem + offset);
425 /* double the size of the buffer for got and plt entries
426 XXX: calculate exact size for them? */
427 offset *= 2;
428#endif
429#endif
430 530
431 if (0 == mem)531#endif /* _WIN32 */
432 return offset;532#endif /* CONFIG_TCC_BACKTRACE */
533/* ------------------------------------------------------------- */
433 534
434 /* relocate each section */535#ifdef CONFIG_TCC_STATIC
435 for(i = 1; i < s1->nb_sections; i++) {
436 s = s1->sections[i];
437 if (s->reloc)
438 relocate_section(s1, s);
439 }
440 536
441 for(i = 1; i < s1->nb_sections; i++) {537#define RTLD_LAZY 0x001
442 s = s1->sections[i];538#define RTLD_NOW 0x002
443 if (0 == (s->sh_flags & SHF_ALLOC))539#define RTLD_GLOBAL 0x100
444 continue;540#define RTLD_DEFAULT NULL
445 length = s->data_offset;
446 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
447 ptr = (void*)(uplong)s->sh_addr;
448 if (NULL == s->data || s->sh_type == SHT_NOBITS)
449 memset(ptr, 0, length);
450 else
451 memcpy(ptr, s->data, length);
452 /* mark executable sections as executable in memory */
453 if (s->sh_flags & SHF_EXECINSTR)
454 set_pages_executable(ptr, length);
455 }
456 541
457#ifndef TCC_TARGET_PE542/* dummy function for profiling */
458#ifdef TCC_TARGET_X86_64543void *dlopen(const char *filename, int flag)
459 set_pages_executable(s1->runtime_plt_and_got,544{
460 s1->runtime_plt_and_got_offset);545 return NULL;
461#endif
462#endif
463 return 0;
464}546}
465 547
466/* Do all relocations (needed before using tcc_get_symbol())548void dlclose(void *p)
467 Returns -1 on error. */
468int tcc_relocate(TCCState *s1)
469{549{
470 int ret = tcc_relocate_ex(s1, NULL);
471 if (-1 == ret)
472 return ret;
473 s1->runtime_mem = tcc_malloc(ret);
474 return tcc_relocate_ex(s1, s1->runtime_mem);
475}550}
476 551
477/* launch the compiled program with the given arguments */552const char *dlerror(void)
478int tcc_run(TCCState *s1, int argc, char **argv)
479{553{
480 int (*prog_main)(int, char **);554 return "error";
555}
481 556
482 if (tcc_relocate(s1) < 0)557typedef struct TCCSyms {
483 return -1;558 char *str;
559 void *ptr;
560} TCCSyms;
484 561
485 prog_main = tcc_get_symbol_err(s1, "main");562#define TCCSYM(a) { #a, &a, },
486 563
487 if (s1->do_debug) {564/* add the symbol you want here if no dynamic linking is done */
488#ifdef CONFIG_TCC_BACKTRACE565static TCCSyms tcc_syms[] = {
489 struct sigaction sigact;566#if !defined(CONFIG_TCCBOOT)
490 /* install TCC signal handlers to print debug info on fatal567 TCCSYM(printf)
491 runtime errors */568 TCCSYM(fprintf)
492 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;569 TCCSYM(fopen)
493 sigact.sa_sigaction = sig_error;570 TCCSYM(fclose)
494 sigemptyset(&sigact.sa_mask);
495 sigaction(SIGFPE, &sigact, NULL);
496 sigaction(SIGILL, &sigact, NULL);
497 sigaction(SIGSEGV, &sigact, NULL);
498 sigaction(SIGBUS, &sigact, NULL);
499 sigaction(SIGABRT, &sigact, NULL);
500#else
501 error("debug mode not available");
502#endif571#endif
572 { NULL, NULL },
573};
574
575void *resolve_sym(TCCState *s1, const char *symbol)
576{
577 TCCSyms *p;
578 p = tcc_syms;
579 while (p->str != NULL) {
580 if (!strcmp(p->str, symbol))
581 return p->ptr;
582 p++;
503 }583 }
584 return NULL;
585}
504 586
505#ifdef CONFIG_TCC_BCHECK587#elif defined(_WIN32)
506 if (s1->do_bounds_check) {588
507 void (*bound_init)(void);589#define dlclose FreeLibrary
508 void (*bound_exit)(void);590
509 /* set error function */591#else
510 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");592
511 rt_prog_main = (unsigned long)prog_main;593#include <dlfcn.h>
512 /* XXX: use .init section so that it also work in binary ? */594
513 bound_init = tcc_get_symbol_err(s1, "__bound_init");595void *resolve_sym(TCCState *s1, const char *sym)
514 bound_exit = tcc_get_symbol_err(s1, "__bound_exit");596{
515 bound_init();597 return dlsym(RTLD_DEFAULT, sym);
516 ret = (*prog_main)(argc, argv);
517 bound_exit();
518 } else
519#endif
520 return (*prog_main)(argc, argv);
521}598}
522 599
523/********************************************************/600#endif /* CONFIG_TCC_STATIC */
601
602/* ------------------------------------------------------------- */
tcctok.h+3−1
@@ -219,9 +219,11 @@ · 218 unmodified lines
219 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")219 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
220 DEF(TOK___bound_local_new, "__bound_local_new")220 DEF(TOK___bound_local_new, "__bound_local_new")
221 DEF(TOK___bound_local_delete, "__bound_local_delete")221 DEF(TOK___bound_local_delete, "__bound_local_delete")
222#if 0222#ifdef TCC_TARGET_PE
223#ifndef TCC_TARGET_X86_64
223 DEF(TOK_malloc, "malloc")224 DEF(TOK_malloc, "malloc")
224 DEF(TOK_free, "free")225 DEF(TOK_free, "free")
226#endif
225 DEF(TOK_realloc, "realloc")227 DEF(TOK_realloc, "realloc")
226 DEF(TOK_memalign, "memalign")228 DEF(TOK_memalign, "memalign")
227 DEF(TOK_calloc, "calloc")229 DEF(TOK_calloc, "calloc")
win32/build-tcc.bat+14−2
@@ -31,8 +31,10 @@ copy ..\libtcc.h libtcc\libtcc.h · 30 unmodified lines
31:tcc31:tcc
32%P%gcc -Os -fno-strict-aliasing ../tcc.c -o tcc.exe -s -DTCC_USE_LIBTCC -ltcc -Llibtcc32%P%gcc -Os -fno-strict-aliasing ../tcc.c -o tcc.exe -s -DTCC_USE_LIBTCC -ltcc -Llibtcc
33 33
34:libtcc1.a34:copy_std_includes
35copy ..\include\*.h include35copy ..\include\*.h include
36
37:libtcc1.a
36.\tcc -c lib/crt1.c38.\tcc -c lib/crt1.c
37.\tcc -c lib/wincrt1.c39.\tcc -c lib/wincrt1.c
38.\tcc -c lib/dllcrt1.c40.\tcc -c lib/dllcrt1.c
@@ -40,5 +42,15 @@ copy ..\include\*.h include · 1 unmodified line
40.\tcc -c ../lib/libtcc1.c42.\tcc -c ../lib/libtcc1.c
41.\tcc -c lib/chkstk.S43.\tcc -c lib/chkstk.S
42.\tcc -c ../lib/alloca86%S%.S44.\tcc -c ../lib/alloca86%S%.S
43tiny_libmaker lib/libtcc1.a crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o libtcc1.o alloca86%S%.o45
46@set LIBFILES=crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o libtcc1.o alloca86%S%.o
47
48@if not _%P%==_ goto makelib
49.\tcc -c ../lib/alloca86-bt%S%.S
50.\tcc -c ../lib/bcheck.c
51
52@set LIBFILES=%LIBFILES% alloca86-bt%S%.o bcheck.o
53
54:makelib
55tiny_libmaker lib/libtcc1.a %LIBFILES%
44del *.o56del *.o

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t