2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /********************************************************/
24 /* global variables */
26 /* display benchmark infos */
31 struct BufferedFile
*file
;
34 CString tokcstr
; /* current parsed string, if any */
35 /* additional informations about token */
37 int *macro_ptr
, *macro_ptr_allocated
;
38 int *unget_saved_macro_ptr
;
39 int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
40 int unget_buffer_enabled
;
42 Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
43 Section
*cur_text_section
; /* current section where function code is
46 Section
*last_text_section
; /* to handle .previous asm directive */
48 /* bound check related sections */
49 Section
*bounds_section
; /* contains global data bound description */
50 Section
*lbounds_section
; /* contains local data bound description */
52 Section
*symtab_section
, *strtab_section
;
55 Section
*stab_section
, *stabstr_section
;
57 /* loc : local variable index
58 ind : output code index
60 anon_sym: anonymous symbol index
62 int rsym
, anon_sym
, ind
, loc
;
63 /* expression generation modifiers */
64 int const_wanted
; /* true if constant wanted */
65 int nocode_wanted
; /* true if no code generation wanted for an expression */
66 int global_expr
; /* true if compound literals must be allocated
67 globally (used during initializers parsing */
68 CType func_vt
; /* current function return type (used by return
71 int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
73 TokenSym
**table_ident
;
74 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
75 char token_buf
[STRING_MAX_SIZE
+ 1];
77 Sym
*global_stack
, *local_stack
;
79 Sym
*global_label_stack
, *local_label_stack
;
80 /* symbol allocator */
85 SValue vstack
[VSTACK_SIZE
], *vtop
;
86 /* some predefined types */
87 CType char_pointer_type
, func_old_type
, int_type
;
89 /* use GNU C extensions */
92 /* use Tiny C extensions */
95 /* max number of callers shown if error */
96 #ifdef CONFIG_TCC_BACKTRACE
98 const char **rt_bound_error_msg
;
99 unsigned long rt_prog_main
;
102 /* XXX: get rid of this ASAP */
103 struct TCCState
*tcc_state
;
105 /********************************************************/
107 #ifdef TCC_TARGET_I386
108 //#include "i386-gen.c"
111 #ifdef TCC_TARGET_ARM
112 //#include "arm-gen.c"
115 #ifdef TCC_TARGET_C67
116 //#include "c67-gen.c"
119 #ifdef TCC_TARGET_X86_64
120 //#include "x86_64-gen.c"
123 #ifdef CONFIG_TCC_ASM
125 #ifdef TCC_TARGET_I386
126 //#include "i386-asm.c"
129 #ifdef TCC_TARGET_X86_64
130 //#include "x86_64-asm.c"
133 //#include "tccasm.c"
138 error("inline asm() not supported");
140 void asm_global_instr(void)
142 error("inline asm() not supported");
146 /********************************************************/
148 char *normalize_slashes(char *path
)
151 for (p
= path
; *p
; ++p
)
159 /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */
160 void tcc_set_lib_path_w32(TCCState
*s
)
163 GetModuleFileNameA(tcc_module
, path
, sizeof path
);
164 p
= tcc_basename(normalize_slashes(strlwr(path
)));
165 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
170 tcc_set_lib_path(s
, path
);
174 BOOL WINAPI
DllMain (HANDLE hDll
, DWORD dwReason
, LPVOID lpReserved
)
176 if (DLL_PROCESS_ATTACH
== dwReason
)
183 /********************************************************/
184 /********************************************************/
189 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
193 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
196 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
200 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
204 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
211 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
212 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
213 (*f
)->filename
, (*f
)->line_num
);
214 if (file
->line_num
> 0) {
215 strcat_printf(buf
, sizeof(buf
),
216 "%s:%d: ", file
->filename
, file
->line_num
);
218 strcat_printf(buf
, sizeof(buf
),
219 "%s: ", file
->filename
);
222 strcat_printf(buf
, sizeof(buf
),
226 strcat_printf(buf
, sizeof(buf
), "warning: ");
228 strcat_printf(buf
, sizeof(buf
), "error: ");
229 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
231 if (!s1
->error_func
) {
232 /* default case: stderr */
233 fprintf(stderr
, "%s\n", buf
);
235 s1
->error_func(s1
->error_opaque
, buf
);
237 if (!is_warning
|| s1
->warn_error
)
241 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
242 void (*error_func
)(void *opaque
, const char *msg
))
244 s
->error_opaque
= error_opaque
;
245 s
->error_func
= error_func
;
248 /* error without aborting current compilation */
249 void error_noabort(const char *fmt
, ...)
251 TCCState
*s1
= tcc_state
;
255 error1(s1
, 0, fmt
, ap
);
259 void error(const char *fmt
, ...)
261 TCCState
*s1
= tcc_state
;
265 error1(s1
, 0, fmt
, ap
);
267 /* better than nothing: in some cases, we accept to handle errors */
268 if (s1
->error_set_jmp_enabled
) {
269 longjmp(s1
->error_jmp_buf
, 1);
271 /* XXX: eliminate this someday */
276 void expect(const char *msg
)
278 error("%s expected", msg
);
281 void warning(const char *fmt
, ...)
283 TCCState
*s1
= tcc_state
;
290 error1(s1
, 1, fmt
, ap
);
297 error("'%c' expected", c
);
301 void test_lvalue(void)
303 if (!(vtop
->r
& VT_LVAL
))
310 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
315 if (strcmp(filename
, "-") == 0)
316 fd
= 0, filename
= "stdin";
318 fd
= open(filename
, O_RDONLY
| O_BINARY
);
319 if ((s1
->verbose
== 2 && fd
>= 0) || s1
->verbose
== 3)
320 printf("%s %*s%s\n", fd
< 0 ? "nf":"->",
321 (int)(s1
->include_stack_ptr
- s1
->include_stack
), "", filename
);
324 bf
= tcc_malloc(sizeof(BufferedFile
));
326 bf
->buf_ptr
= bf
->buffer
;
327 bf
->buf_end
= bf
->buffer
;
328 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
329 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
331 normalize_slashes(bf
->filename
);
334 bf
->ifndef_macro
= 0;
335 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
336 // printf("opening '%s'\n", filename);
340 void tcc_close(BufferedFile
*bf
)
342 total_lines
+= bf
->line_num
;
347 /* compile the C file opened in 'file'. Return non zero if errors. */
348 static int tcc_compile(TCCState
*s1
)
352 volatile int section_sym
;
355 printf("%s: **** new file\n", file
->filename
);
359 cur_text_section
= NULL
;
361 anon_sym
= SYM_FIRST_ANOM
;
363 /* file info: full path + filename */
364 section_sym
= 0; /* avoid warning */
366 section_sym
= put_elf_sym(symtab_section
, 0, 0,
367 ELFW(ST_INFO
)(STB_LOCAL
, STT_SECTION
), 0,
368 text_section
->sh_num
, NULL
);
369 getcwd(buf
, sizeof(buf
));
371 normalize_slashes(buf
);
373 pstrcat(buf
, sizeof(buf
), "/");
374 put_stabs_r(buf
, N_SO
, 0, 0,
375 text_section
->data_offset
, text_section
, section_sym
);
376 put_stabs_r(file
->filename
, N_SO
, 0, 0,
377 text_section
->data_offset
, text_section
, section_sym
);
379 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
380 symbols can be safely used */
381 put_elf_sym(symtab_section
, 0, 0,
382 ELFW(ST_INFO
)(STB_LOCAL
, STT_FILE
), 0,
383 SHN_ABS
, file
->filename
);
385 /* define some often used types */
388 char_pointer_type
.t
= VT_BYTE
;
389 mk_pointer(&char_pointer_type
);
391 func_old_type
.t
= VT_FUNC
;
392 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
394 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
395 float_type
.t
= VT_FLOAT
;
396 double_type
.t
= VT_DOUBLE
;
398 func_float_type
.t
= VT_FUNC
;
399 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
400 func_double_type
.t
= VT_FUNC
;
401 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
405 /* define 'void *alloca(unsigned int)' builtin function */
410 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
411 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
414 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
418 define_start
= define_stack
;
421 if (setjmp(s1
->error_jmp_buf
) == 0) {
423 s1
->error_set_jmp_enabled
= 1;
425 ch
= file
->buf_ptr
[0];
426 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
427 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
431 expect("declaration");
433 /* end of translation unit info */
435 put_stabs_r(NULL
, N_SO
, 0, 0,
436 text_section
->data_offset
, text_section
, section_sym
);
439 s1
->error_set_jmp_enabled
= 0;
441 /* reset define stack, but leave -Dsymbols (may be incorrect if
442 they are undefined) */
443 free_defines(define_start
);
445 gen_inline_functions();
447 sym_pop(&global_stack
, NULL
);
448 sym_pop(&local_stack
, NULL
);
450 return s1
->nb_errors
!= 0 ? -1 : 0;
453 int tcc_compile_string(TCCState
*s
, const char *str
)
455 BufferedFile bf1
, *bf
= &bf1
;
459 /* init file structure */
461 /* XXX: avoid copying */
463 buf
= tcc_malloc(len
+ 1);
466 memcpy(buf
, str
, len
);
469 bf
->buf_end
= buf
+ len
;
470 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
473 ret
= tcc_compile(s
);
477 /* currently, no need to close */
481 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
482 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
484 BufferedFile bf1
, *bf
= &bf1
;
486 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
487 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
491 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
493 /* init file structure */
495 bf
->buf_ptr
= bf
->buffer
;
496 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
497 *bf
->buf_end
= CH_EOB
;
498 bf
->filename
[0] = '\0';
502 s1
->include_stack_ptr
= s1
->include_stack
;
504 /* parse with define parser */
505 ch
= file
->buf_ptr
[0];
511 /* undefine a preprocessor symbol */
512 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
516 ts
= tok_alloc(sym
, strlen(sym
));
517 s
= define_find(ts
->tok
);
518 /* undefine symbol by putting an invalid name */
524 #ifdef CONFIG_TCC_BACKTRACE
525 /* print the position in the source file of PC value 'pc' by reading
526 the stabs debug information */
527 unsigned long rt_printline(unsigned long wanted_pc
)
529 Stab_Sym
*sym
, *sym_end
;
530 char func_name
[128], last_func_name
[128];
531 unsigned long func_addr
, last_pc
, pc
;
532 const char *incl_files
[INCLUDE_STACK_SIZE
];
533 int incl_index
, len
, last_line_num
, i
;
536 fprintf(stderr
, "0x%08lx:", wanted_pc
);
541 last_func_name
[0] = '\0';
542 last_pc
= 0xffffffff;
544 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
545 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
546 while (sym
< sym_end
) {
547 switch(sym
->n_type
) {
548 /* function start or end */
550 if (sym
->n_strx
== 0) {
551 /* we test if between last line and end of function */
552 pc
= sym
->n_value
+ func_addr
;
553 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
558 str
= stabstr_section
->data
+ sym
->n_strx
;
559 p
= strchr(str
, ':');
561 pstrcpy(func_name
, sizeof(func_name
), str
);
564 if (len
> sizeof(func_name
) - 1)
565 len
= sizeof(func_name
) - 1;
566 memcpy(func_name
, str
, len
);
567 func_name
[len
] = '\0';
569 func_addr
= sym
->n_value
;
572 /* line number info */
574 pc
= sym
->n_value
+ func_addr
;
575 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
578 last_line_num
= sym
->n_desc
;
580 strcpy(last_func_name
, func_name
);
584 str
= stabstr_section
->data
+ sym
->n_strx
;
586 if (incl_index
< INCLUDE_STACK_SIZE
) {
587 incl_files
[incl_index
++] = str
;
595 if (sym
->n_strx
== 0) {
596 incl_index
= 0; /* end of translation unit */
598 str
= stabstr_section
->data
+ sym
->n_strx
;
599 /* do not add path */
601 if (len
> 0 && str
[len
- 1] != '/')
609 /* second pass: we try symtab symbols (no line number info) */
612 ElfW(Sym
) *sym
, *sym_end
;
615 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
616 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
619 type
= ELFW(ST_TYPE
)(sym
->st_info
);
620 if (type
== STT_FUNC
) {
621 if (wanted_pc
>= sym
->st_value
&&
622 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
623 pstrcpy(last_func_name
, sizeof(last_func_name
),
624 strtab_section
->data
+ sym
->st_name
);
625 func_addr
= sym
->st_value
;
631 /* did not find any info: */
632 fprintf(stderr
, " ???\n");
635 if (last_func_name
[0] != '\0') {
636 fprintf(stderr
, " %s()", last_func_name
);
638 if (incl_index
> 0) {
639 fprintf(stderr
, " (%s:%d",
640 incl_files
[incl_index
- 1], last_line_num
);
641 for(i
= incl_index
- 2; i
>= 0; i
--)
642 fprintf(stderr
, ", included from %s", incl_files
[i
]);
643 fprintf(stderr
, ")");
645 fprintf(stderr
, "\n");
651 /* copy code into memory passed in by the caller and do all relocations
652 (needed before using tcc_get_symbol()).
653 returns -1 on error and required size if ptr is NULL */
654 int tcc_relocate(TCCState
*s1
, void *ptr
)
657 unsigned long offset
, length
;
661 if (0 == s1
->runtime_added
) {
662 s1
->runtime_added
= 1;
665 pe_output_file(s1
, NULL
);
668 relocate_common_syms();
669 tcc_add_linker_symbols(s1
);
670 build_got_entries(s1
);
676 offset
= 0, mem
= (uplong
)ptr
;
677 for(i
= 1; i
< s1
->nb_sections
; i
++) {
679 if (0 == (s
->sh_flags
& SHF_ALLOC
))
681 length
= s
->data_offset
;
682 s
->sh_addr
= mem
? (mem
+ offset
+ 15) & ~15 : 0;
683 offset
= (offset
+ length
+ 15) & ~15;
686 /* relocate symbols */
687 relocate_syms(s1
, 1);
691 #ifndef TCC_TARGET_PE
692 #ifdef TCC_TARGET_X86_64
693 s1
->runtime_plt_and_got_offset
= 0;
694 s1
->runtime_plt_and_got
= (char *)(mem
+ offset
);
695 /* double the size of the buffer for got and plt entries
696 XXX: calculate exact size for them? */
704 /* relocate each section */
705 for(i
= 1; i
< s1
->nb_sections
; i
++) {
708 relocate_section(s1
, s
);
711 for(i
= 1; i
< s1
->nb_sections
; i
++) {
713 if (0 == (s
->sh_flags
& SHF_ALLOC
))
715 length
= s
->data_offset
;
716 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
717 ptr
= (void*)(uplong
)s
->sh_addr
;
718 if (NULL
== s
->data
|| s
->sh_type
== SHT_NOBITS
)
719 memset(ptr
, 0, length
);
721 memcpy(ptr
, s
->data
, length
);
722 /* mark executable sections as executable in memory */
723 if (s
->sh_flags
& SHF_EXECINSTR
)
724 set_pages_executable(ptr
, length
);
726 #ifndef TCC_TARGET_PE
727 #ifdef TCC_TARGET_X86_64
728 set_pages_executable(s1
->runtime_plt_and_got
,
729 s1
->runtime_plt_and_got_offset
);
735 /* launch the compiled program with the given arguments */
736 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
738 int (*prog_main
)(int, char **);
742 ret
= tcc_relocate(s1
, NULL
);
745 ptr
= tcc_malloc(ret
);
746 tcc_relocate(s1
, ptr
);
748 prog_main
= tcc_get_symbol_err(s1
, "main");
751 #ifdef CONFIG_TCC_BACKTRACE
752 handle_cpu_exception();
754 error("debug mode not available");
758 #ifdef CONFIG_TCC_BCHECK
759 if (s1
->do_bounds_check
) {
760 void (*bound_init
)(void);
761 void (*bound_exit
)(void);
762 /* set error function */
763 rt_bound_error_msg
= tcc_get_symbol_err(s1
, "__bound_error_msg");
764 rt_prog_main
= (unsigned long)prog_main
;
765 /* XXX: use .init section so that it also work in binary ? */
766 bound_init
= tcc_get_symbol_err(s1
, "__bound_init");
767 bound_exit
= tcc_get_symbol_err(s1
, "__bound_exit");
769 ret
= (*prog_main
)(argc
, argv
);
773 ret
= (*prog_main
)(argc
, argv
);
778 void tcc_memstats(void)
781 printf("memory in use: %d\n", mem_cur_size
);
785 static void tcc_cleanup(void)
789 if (NULL
== tcc_state
)
793 /* free -D defines */
797 n
= tok_ident
- TOK_IDENT
;
798 for(i
= 0; i
< n
; i
++)
799 tcc_free(table_ident
[i
]);
800 tcc_free(table_ident
);
803 dynarray_reset(&sym_pools
, &nb_sym_pools
);
806 /* reset symbol stack */
807 sym_free_first
= NULL
;
808 /* cleanup from error/setjmp */
812 TCCState
*tcc_new(void)
820 s
= tcc_mallocz(sizeof(TCCState
));
825 tcc_set_lib_path_w32(s
);
827 tcc_set_lib_path(s
, CONFIG_TCCDIR
);
829 s
->output_type
= TCC_OUTPUT_MEMORY
;
832 /* we add dummy defines for some special macros to speed up tests
833 and to have working defined() */
834 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
835 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
836 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
837 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
839 /* standard defines */
840 tcc_define_symbol(s
, "__STDC__", NULL
);
841 tcc_define_symbol(s
, "__STDC_VERSION__", "199901L");
842 #if defined(TCC_TARGET_I386)
843 tcc_define_symbol(s
, "__i386__", "1");
844 tcc_define_symbol(s
, "__i386", "1");
845 tcc_define_symbol(s
, "i386", "1");
847 #if defined(TCC_TARGET_X86_64)
848 tcc_define_symbol(s
, "__x86_64__", NULL
);
850 #if defined(TCC_TARGET_ARM)
851 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
852 tcc_define_symbol(s
, "__arm_elf__", NULL
);
853 tcc_define_symbol(s
, "__arm_elf", NULL
);
854 tcc_define_symbol(s
, "arm_elf", NULL
);
855 tcc_define_symbol(s
, "__arm__", NULL
);
856 tcc_define_symbol(s
, "__arm", NULL
);
857 tcc_define_symbol(s
, "arm", NULL
);
858 tcc_define_symbol(s
, "__APCS_32__", NULL
);
861 tcc_define_symbol(s
, "_WIN32", NULL
);
862 #ifdef TCC_TARGET_X86_64
863 tcc_define_symbol(s
, "_WIN64", NULL
);
866 tcc_define_symbol(s
, "__unix__", "1");
867 tcc_define_symbol(s
, "__unix", "1");
868 tcc_define_symbol(s
, "unix", "1");
869 #if defined(__FreeBSD__)
871 tcc_define_symbol(s
, "__FreeBSD__", str( __FreeBSD__
));
872 tcc_define_symbol(s
, "__INTEL_COMPILER", "1");
876 tcc_define_symbol(s
, "__linux__", NULL
);
877 tcc_define_symbol(s
, "__linux", NULL
);
880 /* tiny C specific defines */
881 sscanf(TCC_VERSION
, "%d.%d.%d", &a
, &b
, &c
);
882 sprintf(buffer
, "%d", a
*10000 + b
*100 + c
);
883 tcc_define_symbol(s
, "__TINYC__", buffer
);
885 /* tiny C & gcc defines */
886 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned long");
887 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "long");
889 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
891 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
894 #ifndef TCC_TARGET_PE
895 /* default library paths */
896 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/local/lib");
897 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/lib");
898 tcc_add_library_path(s
, CONFIG_SYSROOT
"/lib");
901 /* no section zero */
902 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
904 /* create standard sections */
905 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
906 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
907 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
909 /* symbols are always generated for linking stage */
910 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
912 ".hashtab", SHF_PRIVATE
);
913 strtab_section
= symtab_section
->link
;
915 /* private symbol table for dynamic symbols */
916 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
918 ".dynhashtab", SHF_PRIVATE
);
919 s
->alacarte_link
= 1;
921 #ifdef CHAR_IS_UNSIGNED
922 s
->char_is_unsigned
= 1;
924 #if defined(TCC_TARGET_PE) && 0
925 /* XXX: currently the PE linker is not ready to support that */
926 s
->leading_underscore
= 1;
929 if (s
->section_align
== 0)
930 s
->section_align
= ELF_PAGE_SIZE
;
932 #ifdef TCC_TARGET_I386
938 void tcc_delete(TCCState
*s1
)
944 /* free all sections */
945 for(i
= 1; i
< s1
->nb_sections
; i
++)
946 free_section(s1
->sections
[i
]);
947 dynarray_reset(&s1
->sections
, &s1
->nb_sections
);
949 for(i
= 0; i
< s1
->nb_priv_sections
; i
++)
950 free_section(s1
->priv_sections
[i
]);
951 dynarray_reset(&s1
->priv_sections
, &s1
->nb_priv_sections
);
953 /* free any loaded DLLs */
954 for ( i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
955 DLLReference
*ref
= s1
->loaded_dlls
[i
];
957 dlclose(ref
->handle
);
960 /* free loaded dlls array */
961 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
963 /* free library paths */
964 dynarray_reset(&s1
->library_paths
, &s1
->nb_library_paths
);
966 /* free include paths */
967 dynarray_reset(&s1
->cached_includes
, &s1
->nb_cached_includes
);
968 dynarray_reset(&s1
->include_paths
, &s1
->nb_include_paths
);
969 dynarray_reset(&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
);
971 tcc_free(s1
->tcc_lib_path
);
975 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
979 pathname1
= tcc_strdup(pathname
);
980 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
984 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
988 pathname1
= tcc_strdup(pathname
);
989 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
993 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
998 BufferedFile
*saved_file
;
1002 /* find source file type with extension */
1003 ext
= tcc_fileextension(filename
);
1009 file
= tcc_open(s1
, filename
);
1011 if (flags
& AFF_PRINT_ERROR
)
1012 error_noabort("file '%s' not found", filename
);
1016 if (flags
& AFF_PREPROCESS
) {
1017 ret
= tcc_preprocess(s1
);
1021 if (!ext
[0] || !PATHCMP(ext
, "c")) {
1022 /* C file assumed */
1023 ret
= tcc_compile(s1
);
1027 #ifdef CONFIG_TCC_ASM
1028 if (!strcmp(ext
, "S")) {
1029 /* preprocessed assembler */
1030 ret
= tcc_assemble(s1
, 1);
1034 if (!strcmp(ext
, "s")) {
1035 /* non preprocessed assembler */
1036 ret
= tcc_assemble(s1
, 0);
1042 /* assume executable format: auto guess file type */
1043 size
= read(fd
, &ehdr
, sizeof(ehdr
));
1044 lseek(fd
, 0, SEEK_SET
);
1046 error_noabort("could not read header");
1050 if (size
== sizeof(ehdr
) &&
1051 ehdr
.e_ident
[0] == ELFMAG0
&&
1052 ehdr
.e_ident
[1] == ELFMAG1
&&
1053 ehdr
.e_ident
[2] == ELFMAG2
&&
1054 ehdr
.e_ident
[3] == ELFMAG3
) {
1056 /* do not display line number if error */
1058 if (ehdr
.e_type
== ET_REL
) {
1059 ret
= tcc_load_object_file(s1
, fd
, 0);
1063 #ifndef TCC_TARGET_PE
1064 if (ehdr
.e_type
== ET_DYN
) {
1065 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
1067 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
1071 ret
= tcc_load_dll(s1
, fd
, filename
,
1072 (flags
& AFF_REFERENCED_DLL
) != 0);
1077 error_noabort("unrecognized ELF file");
1081 if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
1082 file
->line_num
= 0; /* do not display line number if error */
1083 ret
= tcc_load_archive(s1
, fd
);
1087 #ifdef TCC_TARGET_COFF
1088 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
1089 ret
= tcc_load_coff(s1
, fd
);
1094 #ifdef TCC_TARGET_PE
1095 ret
= pe_load_file(s1
, filename
, fd
);
1097 /* as GNU ld, consider it is an ld script if not recognized */
1098 ret
= tcc_load_ldscript(s1
);
1101 error_noabort("unrecognized file type");
1110 int tcc_add_file(TCCState
*s
, const char *filename
)
1112 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
)
1113 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
| AFF_PREPROCESS
);
1115 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
1118 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
1122 pathname1
= tcc_strdup(pathname
);
1123 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
1127 /* find and load a dll. Return non zero if not found */
1128 /* XXX: add '-rpath' option support ? */
1129 int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
1134 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
1135 snprintf(buf
, sizeof(buf
), "%s/%s",
1136 s
->library_paths
[i
], filename
);
1137 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
1143 /* the library name is the same as the argument of the '-l' option */
1144 int tcc_add_library(TCCState
*s
, const char *libraryname
)
1149 /* first we look for the dynamic library if not static linking */
1150 if (!s
->static_link
) {
1151 #ifdef TCC_TARGET_PE
1152 if (pe_add_dll(s
, libraryname
) == 0)
1155 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
1156 if (tcc_add_dll(s
, buf
, 0) == 0)
1160 /* then we look for the static library */
1161 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
1162 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
1163 s
->library_paths
[i
], libraryname
);
1164 if (tcc_add_file_internal(s
, buf
, 0) == 0)
1170 int tcc_add_symbol(TCCState
*s
, const char *name
, void *val
)
1172 add_elf_sym(symtab_section
, (uplong
)val
, 0,
1173 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1178 int tcc_set_output_type(TCCState
*s
, int output_type
)
1182 s
->output_type
= output_type
;
1185 /* default include paths */
1186 /* XXX: reverse order needed if -isystem support */
1187 #ifndef TCC_TARGET_PE
1188 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/local/include");
1189 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/include");
1191 snprintf(buf
, sizeof(buf
), "%s/include", s
->tcc_lib_path
);
1192 tcc_add_sysinclude_path(s
, buf
);
1193 #ifdef TCC_TARGET_PE
1194 snprintf(buf
, sizeof(buf
), "%s/include/winapi", s
->tcc_lib_path
);
1195 tcc_add_sysinclude_path(s
, buf
);
1199 /* if bound checking, then add corresponding sections */
1200 #ifdef CONFIG_TCC_BCHECK
1201 if (s
->do_bounds_check
) {
1203 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
1204 /* create bounds sections */
1205 bounds_section
= new_section(s
, ".bounds",
1206 SHT_PROGBITS
, SHF_ALLOC
);
1207 lbounds_section
= new_section(s
, ".lbounds",
1208 SHT_PROGBITS
, SHF_ALLOC
);
1212 if (s
->char_is_unsigned
) {
1213 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
1216 /* add debug sections */
1219 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
1220 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
1221 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
1222 put_elf_str(stabstr_section
, "");
1223 stab_section
->link
= stabstr_section
;
1224 /* put first entry */
1225 put_stabs("", 0, 0, 0, 0);
1228 /* add libc crt1/crti objects */
1229 #ifndef TCC_TARGET_PE
1230 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
1232 if (output_type
!= TCC_OUTPUT_DLL
)
1233 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
1234 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
1238 #ifdef TCC_TARGET_PE
1239 snprintf(buf
, sizeof(buf
), "%s/lib", s
->tcc_lib_path
);
1240 tcc_add_library_path(s
, buf
);
1242 if (GetSystemDirectory(buf
, sizeof buf
))
1243 tcc_add_library_path(s
, buf
);
1250 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
1251 #define FD_INVERT 0x0002 /* invert value before storing */
1253 typedef struct FlagDef
{
1259 static const FlagDef warning_defs
[] = {
1260 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
1261 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
1262 { offsetof(TCCState
, warn_error
), 0, "error" },
1263 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
1264 "implicit-function-declaration" },
1267 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
1268 const char *name
, int value
)
1275 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
1279 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
1280 if (!strcmp(r
, p
->name
))
1285 if (p
->flags
& FD_INVERT
)
1287 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
1292 /* set/reset a warning */
1293 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
1298 if (!strcmp(warning_name
, "all")) {
1299 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
1300 if (p
->flags
& WD_ALL
)
1301 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
1305 return set_flag(s
, warning_defs
, countof(warning_defs
),
1306 warning_name
, value
);
1310 static const FlagDef flag_defs
[] = {
1311 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
1312 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
1313 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
1314 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
1317 /* set/reset a flag */
1318 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
1320 return set_flag(s
, flag_defs
, countof(flag_defs
),
1324 /* set CONFIG_TCCDIR at runtime */
1325 void tcc_set_lib_path(TCCState
*s
, const char *path
)
1327 tcc_free(s
->tcc_lib_path
);
1328 s
->tcc_lib_path
= tcc_strdup(path
);
1331 void tcc_print_stats(TCCState
*s
, int64_t total_time
)
1334 tt
= (double)total_time
/ 1000000.0;
1337 if (total_bytes
< 1)
1339 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
1340 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
1341 tt
, (int)(total_lines
/ tt
),
1342 total_bytes
/ tt
/ 1000000.0);
1346 void tcc_set_options(TCCState
*s
, int argc
, char **argv
)
1349 init_tcc_config(&config
);
1350 parse_args(&config
, s
, argc
, argv
);
1351 /* The config structure is ignored. It has no effect in library mode. */