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 /* use GNU C extensions */
27 ST_DATA
int gnu_ext
= 1;
29 /* use TinyCC extensions */
30 ST_DATA
int tcc_ext
= 1;
32 /* XXX: get rid of this ASAP */
33 ST_DATA
struct TCCState
*tcc_state
;
35 #ifdef CONFIG_TCC_BACKTRACE
36 ST_DATA
int num_callers
= 6;
37 ST_DATA
const char **rt_bound_error_msg
;
38 ST_DATA
void *rt_prog_main
;
41 /********************************************************/
48 #ifdef TCC_TARGET_I386
57 #ifdef TCC_TARGET_X86_64
58 #include "x86_64-gen.c"
62 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
66 #ifdef TCC_TARGET_COFF
72 #endif /* ALL_IN_ONE */
74 /********************************************************/
75 #ifndef CONFIG_TCC_ASM
76 ST_FUNC
void asm_instr(void)
78 error("inline asm() not supported");
80 ST_FUNC
void asm_global_instr(void)
82 error("inline asm() not supported");
86 /********************************************************/
89 static char *normalize_slashes(char *path
)
92 for (p
= path
; *p
; ++p
)
98 static HMODULE tcc_module
;
100 /* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */
101 static void tcc_set_lib_path_w32(TCCState
*s
)
104 GetModuleFileNameA(tcc_module
, path
, sizeof path
);
105 p
= tcc_basename(normalize_slashes(strlwr(path
)));
106 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
111 tcc_set_lib_path(s
, path
);
114 #ifndef CONFIG_TCC_STATIC
115 void dlclose(void *p
)
117 FreeLibrary((HMODULE
)p
);
122 BOOL WINAPI
DllMain (HANDLE hDll
, DWORD dwReason
, LPVOID lpReserved
)
124 if (DLL_PROCESS_ATTACH
== dwReason
)
131 /********************************************************/
132 /* copy a string and truncate it. */
133 PUB_FUNC
char *pstrcpy(char *buf
, int buf_size
, const char *s
)
140 q_end
= buf
+ buf_size
- 1;
152 /* strcat and truncate. */
153 PUB_FUNC
char *pstrcat(char *buf
, int buf_size
, const char *s
)
158 pstrcpy(buf
+ len
, buf_size
- len
, s
);
162 /* extract the basename of a file */
163 PUB_FUNC
char *tcc_basename(const char *name
)
165 char *p
= strchr(name
, 0);
166 while (p
> name
&& !IS_PATHSEP(p
[-1]))
171 PUB_FUNC
char *tcc_fileextension (const char *name
)
173 char *b
= tcc_basename(name
);
174 char *e
= strrchr(b
, '.');
175 return e
? e
: strchr(b
, 0);
178 /********************************************************/
179 /* memory management */
188 unsigned malloc_usable_size(void*);
191 PUB_FUNC
void tcc_free(void *ptr
)
194 mem_cur_size
-= malloc_usable_size(ptr
);
199 PUB_FUNC
void *tcc_malloc(unsigned long size
)
204 error("memory full");
206 mem_cur_size
+= malloc_usable_size(ptr
);
207 if (mem_cur_size
> mem_max_size
)
208 mem_max_size
= mem_cur_size
;
213 PUB_FUNC
void *tcc_mallocz(unsigned long size
)
216 ptr
= tcc_malloc(size
);
217 memset(ptr
, 0, size
);
221 PUB_FUNC
void *tcc_realloc(void *ptr
, unsigned long size
)
225 mem_cur_size
-= malloc_usable_size(ptr
);
227 ptr1
= realloc(ptr
, size
);
229 /* NOTE: count not correct if alloc error, but not critical */
230 mem_cur_size
+= malloc_usable_size(ptr1
);
231 if (mem_cur_size
> mem_max_size
)
232 mem_max_size
= mem_cur_size
;
237 PUB_FUNC
char *tcc_strdup(const char *str
)
240 ptr
= tcc_malloc(strlen(str
) + 1);
245 PUB_FUNC
void tcc_memstats(void)
248 printf("memory in use: %d\n", mem_cur_size
);
252 #define free(p) use_tcc_free(p)
253 #define malloc(s) use_tcc_malloc(s)
254 #define realloc(p, s) use_tcc_realloc(p, s)
256 /********************************************************/
259 PUB_FUNC
void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
266 /* every power of two we double array size */
267 if ((nb
& (nb
- 1)) == 0) {
272 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
274 error("memory full");
281 PUB_FUNC
void dynarray_reset(void *pp
, int *n
)
284 for (p
= *(void***)pp
; *n
; ++p
, --*n
)
287 tcc_free(*(void**)pp
);
291 /* we use our own 'finite' function to avoid potential problems with
292 non standard math libs */
293 /* XXX: endianness dependent */
294 ST_FUNC
int ieee_finite(double d
)
297 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
300 /********************************************************/
302 ST_FUNC Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
306 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
307 strcpy(sec
->name
, name
);
308 sec
->sh_type
= sh_type
;
309 sec
->sh_flags
= sh_flags
;
317 sec
->sh_addralign
= 4;
320 sec
->sh_addralign
= 1;
323 sec
->sh_addralign
= 32; /* default conservative alignment */
327 if (sh_flags
& SHF_PRIVATE
) {
328 dynarray_add((void ***)&s1
->priv_sections
, &s1
->nb_priv_sections
, sec
);
330 sec
->sh_num
= s1
->nb_sections
;
331 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
337 static void free_section(Section
*s
)
342 /* realloc section and set its content to zero */
343 ST_FUNC
void section_realloc(Section
*sec
, unsigned long new_size
)
348 size
= sec
->data_allocated
;
351 while (size
< new_size
)
353 data
= tcc_realloc(sec
->data
, size
);
355 error("memory full");
356 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
358 sec
->data_allocated
= size
;
361 /* reserve at least 'size' bytes in section 'sec' from
363 ST_FUNC
void *section_ptr_add(Section
*sec
, unsigned long size
)
365 unsigned long offset
, offset1
;
367 offset
= sec
->data_offset
;
368 offset1
= offset
+ size
;
369 if (offset1
> sec
->data_allocated
)
370 section_realloc(sec
, offset1
);
371 sec
->data_offset
= offset1
;
372 return sec
->data
+ offset
;
375 /* return a reference to a section, and create it if it does not
377 ST_FUNC Section
*find_section(TCCState
*s1
, const char *name
)
381 for(i
= 1; i
< s1
->nb_sections
; i
++) {
382 sec
= s1
->sections
[i
];
383 if (!strcmp(name
, sec
->name
))
386 /* sections are created as PROGBITS */
387 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
390 /* update sym->c so that it points to an external symbol in section
391 'section' with value 'value' */
392 ST_FUNC
void put_extern_sym2(Sym
*sym
, Section
*section
,
393 unsigned long value
, unsigned long size
,
394 int can_add_underscore
)
396 int sym_type
, sym_bind
, sh_num
, info
, other
;
403 else if (section
== SECTION_ABS
)
406 sh_num
= section
->sh_num
;
408 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
) {
410 } else if ((sym
->type
.t
& VT_BTYPE
) == VT_VOID
) {
411 sym_type
= STT_NOTYPE
;
413 sym_type
= STT_OBJECT
;
416 if (sym
->type
.t
& VT_STATIC
)
417 sym_bind
= STB_LOCAL
;
419 sym_bind
= STB_GLOBAL
;
422 name
= get_tok_str(sym
->v
, NULL
);
423 #ifdef CONFIG_TCC_BCHECK
424 if (tcc_state
->do_bounds_check
) {
427 /* XXX: avoid doing that for statics ? */
428 /* if bound checking is activated, we change some function
429 names by adding the "__bound" prefix */
432 /* XXX: we rely only on malloc hooks */
445 strcpy(buf
, "__bound_");
455 if (sym
->type
.t
& VT_EXPORT
)
457 if (sym_type
== STT_FUNC
&& sym
->type
.ref
) {
458 int attr
= sym
->type
.ref
->r
;
459 if (FUNC_EXPORT(attr
))
461 if (FUNC_CALL(attr
) == FUNC_STDCALL
&& can_add_underscore
) {
462 sprintf(buf1
, "_%s@%d", name
, FUNC_ARGS(attr
) * PTR_SIZE
);
465 can_add_underscore
= 0;
468 if (find_elf_sym(tcc_state
->dynsymtab_section
, name
))
470 if (sym
->type
.t
& VT_IMPORT
)
474 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
476 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
479 info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
480 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, other
, sh_num
, name
);
482 esym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
];
483 esym
->st_value
= value
;
484 esym
->st_size
= size
;
485 esym
->st_shndx
= sh_num
;
489 ST_FUNC
void put_extern_sym(Sym
*sym
, Section
*section
,
490 unsigned long value
, unsigned long size
)
492 put_extern_sym2(sym
, section
, value
, size
, 1);
495 /* add a new relocation entry to symbol 'sym' in section 's' */
496 ST_FUNC
void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
501 put_extern_sym(sym
, NULL
, 0, 0);
504 /* now we can add ELF relocation info */
505 put_elf_reloc(symtab_section
, s
, offset
, type
, c
);
508 /********************************************************/
510 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
514 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
517 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
521 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
525 static void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
532 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
533 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
534 (*f
)->filename
, (*f
)->line_num
);
535 if (file
->line_num
> 0) {
536 strcat_printf(buf
, sizeof(buf
),
537 "%s:%d: ", file
->filename
, file
->line_num
);
539 strcat_printf(buf
, sizeof(buf
),
540 "%s: ", file
->filename
);
543 strcat_printf(buf
, sizeof(buf
),
547 strcat_printf(buf
, sizeof(buf
), "warning: ");
549 strcat_printf(buf
, sizeof(buf
), "error: ");
550 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
552 if (!s1
->error_func
) {
553 /* default case: stderr */
554 fprintf(stderr
, "%s\n", buf
);
556 s1
->error_func(s1
->error_opaque
, buf
);
558 if (!is_warning
|| s1
->warn_error
)
562 LIBTCCAPI
void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
563 void (*error_func
)(void *opaque
, const char *msg
))
565 s
->error_opaque
= error_opaque
;
566 s
->error_func
= error_func
;
569 /* error without aborting current compilation */
570 PUB_FUNC
void error_noabort(const char *fmt
, ...)
572 TCCState
*s1
= tcc_state
;
576 error1(s1
, 0, fmt
, ap
);
580 PUB_FUNC
void error(const char *fmt
, ...)
582 TCCState
*s1
= tcc_state
;
586 error1(s1
, 0, fmt
, ap
);
588 /* better than nothing: in some cases, we accept to handle errors */
589 if (s1
->error_set_jmp_enabled
) {
590 longjmp(s1
->error_jmp_buf
, 1);
592 /* XXX: eliminate this someday */
597 PUB_FUNC
void expect(const char *msg
)
599 error("%s expected", msg
);
602 PUB_FUNC
void warning(const char *fmt
, ...)
604 TCCState
*s1
= tcc_state
;
611 error1(s1
, 1, fmt
, ap
);
615 /********************************************************/
618 ST_FUNC BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
623 if (strcmp(filename
, "-") == 0)
624 fd
= 0, filename
= "stdin";
626 fd
= open(filename
, O_RDONLY
| O_BINARY
);
627 if ((s1
->verbose
== 2 && fd
>= 0) || s1
->verbose
== 3)
628 printf("%s %*s%s\n", fd
< 0 ? "nf":"->",
629 (int)(s1
->include_stack_ptr
- s1
->include_stack
), "", filename
);
632 bf
= tcc_malloc(sizeof(BufferedFile
));
634 bf
->buf_ptr
= bf
->buffer
;
635 bf
->buf_end
= bf
->buffer
;
636 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
637 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
639 normalize_slashes(bf
->filename
);
642 bf
->ifndef_macro
= 0;
643 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
644 // printf("opening '%s'\n", filename);
648 ST_FUNC
void tcc_close(BufferedFile
*bf
)
650 total_lines
+= bf
->line_num
;
655 /* compile the C file opened in 'file'. Return non zero if errors. */
656 static int tcc_compile(TCCState
*s1
)
660 volatile int section_sym
;
663 printf("%s: **** new file\n", file
->filename
);
667 cur_text_section
= NULL
;
669 anon_sym
= SYM_FIRST_ANOM
;
671 /* file info: full path + filename */
672 section_sym
= 0; /* avoid warning */
674 section_sym
= put_elf_sym(symtab_section
, 0, 0,
675 ELFW(ST_INFO
)(STB_LOCAL
, STT_SECTION
), 0,
676 text_section
->sh_num
, NULL
);
677 getcwd(buf
, sizeof(buf
));
679 normalize_slashes(buf
);
681 pstrcat(buf
, sizeof(buf
), "/");
682 put_stabs_r(buf
, N_SO
, 0, 0,
683 text_section
->data_offset
, text_section
, section_sym
);
684 put_stabs_r(file
->filename
, N_SO
, 0, 0,
685 text_section
->data_offset
, text_section
, section_sym
);
687 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
688 symbols can be safely used */
689 put_elf_sym(symtab_section
, 0, 0,
690 ELFW(ST_INFO
)(STB_LOCAL
, STT_FILE
), 0,
691 SHN_ABS
, file
->filename
);
693 /* define some often used types */
696 char_pointer_type
.t
= VT_BYTE
;
697 mk_pointer(&char_pointer_type
);
699 func_old_type
.t
= VT_FUNC
;
700 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
702 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
703 float_type
.t
= VT_FLOAT
;
704 double_type
.t
= VT_DOUBLE
;
706 func_float_type
.t
= VT_FUNC
;
707 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
708 func_double_type
.t
= VT_FUNC
;
709 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
713 /* define 'void *alloca(unsigned int)' builtin function */
718 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
719 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
722 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
726 define_start
= define_stack
;
729 if (setjmp(s1
->error_jmp_buf
) == 0) {
731 s1
->error_set_jmp_enabled
= 1;
733 ch
= file
->buf_ptr
[0];
734 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
735 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
739 expect("declaration");
741 /* end of translation unit info */
743 put_stabs_r(NULL
, N_SO
, 0, 0,
744 text_section
->data_offset
, text_section
, section_sym
);
747 s1
->error_set_jmp_enabled
= 0;
749 /* reset define stack, but leave -Dsymbols (may be incorrect if
750 they are undefined) */
751 free_defines(define_start
);
753 gen_inline_functions();
755 sym_pop(&global_stack
, NULL
);
756 sym_pop(&local_stack
, NULL
);
758 return s1
->nb_errors
!= 0 ? -1 : 0;
761 LIBTCCAPI
int tcc_compile_string(TCCState
*s
, const char *str
)
763 BufferedFile bf1
, *bf
= &bf1
;
767 /* init file structure */
769 /* XXX: avoid copying */
771 buf
= tcc_malloc(len
+ 1);
774 memcpy(buf
, str
, len
);
777 bf
->buf_end
= buf
+ len
;
778 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
781 ret
= tcc_compile(s
);
785 /* currently, no need to close */
789 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
790 LIBTCCAPI
void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
792 BufferedFile bf1
, *bf
= &bf1
;
794 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
795 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
799 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
801 /* init file structure */
803 bf
->buf_ptr
= bf
->buffer
;
804 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
805 *bf
->buf_end
= CH_EOB
;
806 bf
->filename
[0] = '\0';
810 s1
->include_stack_ptr
= s1
->include_stack
;
812 /* parse with define parser */
813 ch
= file
->buf_ptr
[0];
819 /* undefine a preprocessor symbol */
820 LIBTCCAPI
void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
824 ts
= tok_alloc(sym
, strlen(sym
));
825 s
= define_find(ts
->tok
);
826 /* undefine symbol by putting an invalid name */
831 static void tcc_cleanup(void)
835 if (NULL
== tcc_state
)
839 /* free -D defines */
843 n
= tok_ident
- TOK_IDENT
;
844 for(i
= 0; i
< n
; i
++)
845 tcc_free(table_ident
[i
]);
846 tcc_free(table_ident
);
849 dynarray_reset(&sym_pools
, &nb_sym_pools
);
852 /* reset symbol stack */
853 sym_free_first
= NULL
;
854 /* cleanup from error/setjmp */
858 LIBTCCAPI TCCState
*tcc_new(void)
866 s
= tcc_mallocz(sizeof(TCCState
));
871 tcc_set_lib_path_w32(s
);
873 tcc_set_lib_path(s
, CONFIG_TCCDIR
);
875 s
->output_type
= TCC_OUTPUT_MEMORY
;
878 /* we add dummy defines for some special macros to speed up tests
879 and to have working defined() */
880 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
881 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
882 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
883 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
885 /* standard defines */
886 tcc_define_symbol(s
, "__STDC__", NULL
);
887 tcc_define_symbol(s
, "__STDC_VERSION__", "199901L");
888 #if defined(TCC_TARGET_I386)
889 tcc_define_symbol(s
, "__i386__", NULL
);
890 tcc_define_symbol(s
, "__i386", NULL
);
891 tcc_define_symbol(s
, "i386", NULL
);
893 #if defined(TCC_TARGET_X86_64)
894 tcc_define_symbol(s
, "__x86_64__", NULL
);
896 #if defined(TCC_TARGET_ARM)
897 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
898 tcc_define_symbol(s
, "__arm_elf__", NULL
);
899 tcc_define_symbol(s
, "__arm_elf", NULL
);
900 tcc_define_symbol(s
, "arm_elf", NULL
);
901 tcc_define_symbol(s
, "__arm__", NULL
);
902 tcc_define_symbol(s
, "__arm", NULL
);
903 tcc_define_symbol(s
, "arm", NULL
);
904 tcc_define_symbol(s
, "__APCS_32__", NULL
);
907 tcc_define_symbol(s
, "_WIN32", NULL
);
908 #ifdef TCC_TARGET_X86_64
909 tcc_define_symbol(s
, "_WIN64", NULL
);
912 tcc_define_symbol(s
, "__unix__", NULL
);
913 tcc_define_symbol(s
, "__unix", NULL
);
914 tcc_define_symbol(s
, "unix", NULL
);
915 #if defined(__FreeBSD__)
917 tcc_define_symbol(s
, "__FreeBSD__", str( __FreeBSD__
));
921 tcc_define_symbol(s
, "__linux__", NULL
);
922 tcc_define_symbol(s
, "__linux", NULL
);
925 /* tiny C specific defines */
926 sscanf(TCC_VERSION
, "%d.%d.%d", &a
, &b
, &c
);
927 sprintf(buffer
, "%d", a
*10000 + b
*100 + c
);
928 tcc_define_symbol(s
, "__TINYC__", buffer
);
930 /* tiny C & gcc defines */
931 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
932 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned long long");
933 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "long long");
935 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned long");
936 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "long");
940 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
942 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
945 #ifndef TCC_TARGET_PE
946 /* default library paths */
947 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/local/lib");
948 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/lib");
949 tcc_add_library_path(s
, CONFIG_SYSROOT
"/lib");
952 /* no section zero */
953 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
955 /* create standard sections */
956 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
957 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
958 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
960 /* symbols are always generated for linking stage */
961 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
963 ".hashtab", SHF_PRIVATE
);
964 strtab_section
= symtab_section
->link
;
966 /* private symbol table for dynamic symbols */
967 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
969 ".dynhashtab", SHF_PRIVATE
);
970 s
->alacarte_link
= 1;
973 #ifdef CHAR_IS_UNSIGNED
974 s
->char_is_unsigned
= 1;
976 #if defined(TCC_TARGET_PE) && 0
977 /* XXX: currently the PE linker is not ready to support that */
978 s
->leading_underscore
= 1;
980 if (s
->section_align
== 0)
981 s
->section_align
= ELF_PAGE_SIZE
;
982 #ifdef TCC_TARGET_I386
988 LIBTCCAPI
void tcc_delete(TCCState
*s1
)
994 /* free all sections */
995 for(i
= 1; i
< s1
->nb_sections
; i
++)
996 free_section(s1
->sections
[i
]);
997 dynarray_reset(&s1
->sections
, &s1
->nb_sections
);
999 for(i
= 0; i
< s1
->nb_priv_sections
; i
++)
1000 free_section(s1
->priv_sections
[i
]);
1001 dynarray_reset(&s1
->priv_sections
, &s1
->nb_priv_sections
);
1003 /* free any loaded DLLs */
1004 for ( i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1005 DLLReference
*ref
= s1
->loaded_dlls
[i
];
1007 dlclose(ref
->handle
);
1010 /* free loaded dlls array */
1011 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
1013 /* free library paths */
1014 dynarray_reset(&s1
->library_paths
, &s1
->nb_library_paths
);
1016 /* free include paths */
1017 dynarray_reset(&s1
->cached_includes
, &s1
->nb_cached_includes
);
1018 dynarray_reset(&s1
->include_paths
, &s1
->nb_include_paths
);
1019 dynarray_reset(&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
);
1021 tcc_free(s1
->tcc_lib_path
);
1022 tcc_free(s1
->runtime_mem
);
1026 LIBTCCAPI
int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
1030 pathname1
= tcc_strdup(pathname
);
1031 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
1035 LIBTCCAPI
int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
1039 pathname1
= tcc_strdup(pathname
);
1040 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
1044 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
1049 BufferedFile
*saved_file
;
1053 /* find source file type with extension */
1054 ext
= tcc_fileextension(filename
);
1060 file
= tcc_open(s1
, filename
);
1062 if (flags
& AFF_PRINT_ERROR
)
1063 error_noabort("file '%s' not found", filename
);
1067 if (flags
& AFF_PREPROCESS
) {
1068 ret
= tcc_preprocess(s1
);
1072 if (!ext
[0] || !PATHCMP(ext
, "c")) {
1073 /* C file assumed */
1074 ret
= tcc_compile(s1
);
1078 #ifdef CONFIG_TCC_ASM
1079 if (!strcmp(ext
, "S")) {
1080 /* preprocessed assembler */
1081 ret
= tcc_assemble(s1
, 1);
1085 if (!strcmp(ext
, "s")) {
1086 /* non preprocessed assembler */
1087 ret
= tcc_assemble(s1
, 0);
1093 /* assume executable format: auto guess file type */
1094 size
= read(fd
, &ehdr
, sizeof(ehdr
));
1095 lseek(fd
, 0, SEEK_SET
);
1097 error_noabort("could not read header");
1101 if (size
== sizeof(ehdr
) &&
1102 ehdr
.e_ident
[0] == ELFMAG0
&&
1103 ehdr
.e_ident
[1] == ELFMAG1
&&
1104 ehdr
.e_ident
[2] == ELFMAG2
&&
1105 ehdr
.e_ident
[3] == ELFMAG3
) {
1107 /* do not display line number if error */
1109 if (ehdr
.e_type
== ET_REL
) {
1110 ret
= tcc_load_object_file(s1
, fd
, 0);
1114 #ifndef TCC_TARGET_PE
1115 if (ehdr
.e_type
== ET_DYN
) {
1116 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
1118 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
1122 ret
= tcc_load_dll(s1
, fd
, filename
,
1123 (flags
& AFF_REFERENCED_DLL
) != 0);
1128 error_noabort("unrecognized ELF file");
1132 if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
1133 file
->line_num
= 0; /* do not display line number if error */
1134 ret
= tcc_load_archive(s1
, fd
);
1138 #ifdef TCC_TARGET_COFF
1139 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
1140 ret
= tcc_load_coff(s1
, fd
);
1145 #ifdef TCC_TARGET_PE
1146 ret
= pe_load_file(s1
, filename
, fd
);
1148 /* as GNU ld, consider it is an ld script if not recognized */
1149 ret
= tcc_load_ldscript(s1
);
1152 error_noabort("unrecognized file type");
1161 LIBTCCAPI
int tcc_add_file(TCCState
*s
, const char *filename
)
1163 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
)
1164 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
| AFF_PREPROCESS
);
1166 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
1169 LIBTCCAPI
int tcc_add_library_path(TCCState
*s
, const char *pathname
)
1173 pathname1
= tcc_strdup(pathname
);
1174 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
1178 /* find and load a dll. Return non zero if not found */
1179 /* XXX: add '-rpath' option support ? */
1180 ST_FUNC
int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
1185 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
1186 snprintf(buf
, sizeof(buf
), "%s/%s",
1187 s
->library_paths
[i
], filename
);
1188 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
1194 /* the library name is the same as the argument of the '-l' option */
1195 LIBTCCAPI
int tcc_add_library(TCCState
*s
, const char *libraryname
)
1200 /* first we look for the dynamic library if not static linking */
1201 if (!s
->static_link
) {
1202 #ifdef TCC_TARGET_PE
1203 if (pe_add_dll(s
, libraryname
) == 0)
1206 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
1207 if (tcc_add_dll(s
, buf
, 0) == 0)
1211 /* then we look for the static library */
1212 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
1213 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
1214 s
->library_paths
[i
], libraryname
);
1215 if (tcc_add_file_internal(s
, buf
, 0) == 0)
1221 LIBTCCAPI
int tcc_add_symbol(TCCState
*s
, const char *name
, const void *val
)
1223 #ifdef TCC_TARGET_PE
1224 pe_putimport(s
, 0, name
, val
);
1226 add_elf_sym(symtab_section
, (uplong
)val
, 0,
1227 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1233 LIBTCCAPI
int tcc_set_output_type(TCCState
*s
, int output_type
)
1237 s
->output_type
= output_type
;
1240 /* default include paths */
1241 /* XXX: reverse order needed if -isystem support */
1242 #ifndef TCC_TARGET_PE
1243 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/local/include");
1244 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/include");
1246 snprintf(buf
, sizeof(buf
), "%s/include", s
->tcc_lib_path
);
1247 tcc_add_sysinclude_path(s
, buf
);
1248 #ifdef TCC_TARGET_PE
1249 snprintf(buf
, sizeof(buf
), "%s/include/winapi", s
->tcc_lib_path
);
1250 tcc_add_sysinclude_path(s
, buf
);
1254 /* if bound checking, then add corresponding sections */
1255 #ifdef CONFIG_TCC_BCHECK
1256 if (s
->do_bounds_check
) {
1258 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
1259 /* create bounds sections */
1260 bounds_section
= new_section(s
, ".bounds",
1261 SHT_PROGBITS
, SHF_ALLOC
);
1262 lbounds_section
= new_section(s
, ".lbounds",
1263 SHT_PROGBITS
, SHF_ALLOC
);
1267 if (s
->char_is_unsigned
) {
1268 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
1271 /* add debug sections */
1274 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
1275 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
1276 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
1277 put_elf_str(stabstr_section
, "");
1278 stab_section
->link
= stabstr_section
;
1279 /* put first entry */
1280 put_stabs("", 0, 0, 0, 0);
1283 /* add libc crt1/crti objects */
1284 #ifndef TCC_TARGET_PE
1285 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
1287 if (output_type
!= TCC_OUTPUT_DLL
)
1288 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
1289 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
1293 #ifdef TCC_TARGET_PE
1294 snprintf(buf
, sizeof(buf
), "%s/lib", s
->tcc_lib_path
);
1295 tcc_add_library_path(s
, buf
);
1297 if (GetSystemDirectory(buf
, sizeof buf
))
1298 tcc_add_library_path(s
, buf
);
1305 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
1306 #define FD_INVERT 0x0002 /* invert value before storing */
1308 typedef struct FlagDef
{
1314 static const FlagDef warning_defs
[] = {
1315 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
1316 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
1317 { offsetof(TCCState
, warn_error
), 0, "error" },
1318 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
1319 "implicit-function-declaration" },
1322 ST_FUNC
int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
1323 const char *name
, int value
)
1330 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
1334 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
1335 if (!strcmp(r
, p
->name
))
1340 if (p
->flags
& FD_INVERT
)
1342 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
1346 /* set/reset a warning */
1347 LIBTCCAPI
int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
1352 if (!strcmp(warning_name
, "all")) {
1353 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
1354 if (p
->flags
& WD_ALL
)
1355 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
1359 return set_flag(s
, warning_defs
, countof(warning_defs
),
1360 warning_name
, value
);
1364 static const FlagDef flag_defs
[] = {
1365 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
1366 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
1367 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
1368 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
1371 /* set/reset a flag */
1372 PUB_FUNC
int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
1374 return set_flag(s
, flag_defs
, countof(flag_defs
),
1378 PUB_FUNC
void tcc_print_stats(TCCState
*s
, int64_t total_time
)
1381 tt
= (double)total_time
/ 1000000.0;
1384 if (total_bytes
< 1)
1386 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
1387 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
1388 tt
, (int)(total_lines
/ tt
),
1389 total_bytes
/ tt
/ 1000000.0);
1392 /* set CONFIG_TCCDIR at runtime */
1393 LIBTCCAPI
void tcc_set_lib_path(TCCState
*s
, const char *path
)
1395 tcc_free(s
->tcc_lib_path
);
1396 s
->tcc_lib_path
= tcc_strdup(path
);
1399 PUB_FUNC
void set_num_callers(int n
)
1401 #ifdef CONFIG_TCC_BACKTRACE