aboutsummaryrefslogtreecommitdiff
path: root/tcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'tcc.c')
-rw-r--r--tcc.c148
1 files changed, 110 insertions, 38 deletions
diff --git a/tcc.c b/tcc.c
index 8bfc50b..f37b687 100644
--- a/tcc.c
+++ b/tcc.c
@@ -25,7 +25,6 @@
#include <math.h>
#include <unistd.h>
#include <signal.h>
-#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#ifndef WIN32
@@ -307,6 +306,9 @@ int tcc_ext = 1;
/* if true, static linking is performed */
int static_link = 0;
+/* give the path of the tcc libraries */
+static const char *tcc_lib_path = CONFIG_TCC_PREFIX "/lib/tcc";
+
struct TCCState {
int output_type;
};
@@ -586,6 +588,8 @@ void type_to_str(char *buf, int buf_size,
int t, const char *varstr);
char *get_tok_str(int v, CValue *cv);
Sym *external_sym(int v, int u, int r);
+static Sym *get_sym_ref(int t, Section *sec,
+ unsigned long offset, unsigned long size);
/* section generation */
void put_extern_sym(Sym *sym, Section *section, unsigned long value);
@@ -613,10 +617,6 @@ static inline int is_float(int t)
return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
}
-#ifdef CONFIG_TCC_BCHECK
-#include "bcheck.c"
-#endif
-
#ifdef TCC_TARGET_I386
#include "i386-gen.c"
#endif
@@ -2494,18 +2494,27 @@ void vpushi(int v)
vsetc(VT_INT, VT_CONST, &cval);
}
-/* push a reference to a section offset by adding a dummy symbol */
-void vpush_ref(int t, Section *sec, unsigned long offset)
+/* Return a static symbol pointing to a section */
+static Sym *get_sym_ref(int t, Section *sec,
+ unsigned long offset, unsigned long size)
{
int v;
Sym *sym;
- CValue cval;
v = anon_sym++;
sym = sym_push1(&global_stack, v, t | VT_STATIC, 0);
sym->r = VT_CONST | VT_SYM;
put_extern_sym(sym, sec, offset);
- cval.sym = sym;
+ return sym;
+}
+
+/* push a reference to a section offset by adding a dummy symbol */
+/* XXX: add size */
+void vpush_ref(int t, Section *sec, unsigned long offset)
+{
+ CValue cval;
+
+ cval.sym = get_sym_ref(t, sec, offset, 0);
vsetc(t, VT_CONST | VT_SYM, &cval);
}
@@ -6397,7 +6406,8 @@ void put_extern_sym(Sym *sym, Section *section, unsigned long value)
int sym_type, sym_bind, sh_num, info;
Elf32_Sym *esym;
const char *name;
-
+ char buf[32];
+
if (section)
sh_num = section->sh_num;
else
@@ -6411,7 +6421,30 @@ void put_extern_sym(Sym *sym, Section *section, unsigned long value)
sym_bind = STB_LOCAL;
else
sym_bind = STB_GLOBAL;
+
name = get_tok_str(sym->v, NULL);
+#ifdef CONFIG_TCC_BCHECK
+ if (do_bounds_check) {
+ /* if bound checking is activated, we change some function
+ names by adding the "__bound" prefix */
+ switch(sym->v) {
+ case TOK_malloc:
+ case TOK_free:
+ case TOK_realloc:
+ case TOK_memalign:
+ case TOK_calloc:
+ case TOK_memcpy:
+ case TOK_memmove:
+ case TOK_memset:
+ case TOK_strlen:
+ case TOK_strcpy:
+ strcpy(buf, "__bound_");
+ strcat(buf, name);
+ name = buf;
+ break;
+ }
+ }
+#endif
info = ELF32_ST_INFO(sym_bind, sym_type);
sym->c = add_elf_sym(symtab_section, value, 0, info, sh_num, name);
} else {
@@ -6576,14 +6609,6 @@ static void relocate_common_syms(void)
static void *resolve_sym(const char *sym)
{
-#ifdef CONFIG_TCC_BCHECK
- if (do_bounds_check) {
- void *ptr;
- ptr = bound_resolve_sym(sym);
- if (ptr)
- return ptr;
- }
-#endif
return dlsym(NULL, sym);
}
@@ -6867,7 +6892,44 @@ static void put_dt(Section *dynamic, int dt, unsigned long val)
/* add tcc runtime libraries */
static void tcc_add_runtime(TCCState *s1)
{
- tcc_add_file(s1, CONFIG_TCC_PREFIX "/lib/tcc/libtcc1.o");
+ char buf[1024];
+
+ snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.o");
+ tcc_add_file(s1, buf);
+#ifdef CONFIG_TCC_BCHECK
+ if (do_bounds_check) {
+ /* XXX: add an object file to do that */
+ *(int *)bounds_section->data_ptr = 0;
+ bounds_section->data_ptr += sizeof(int);
+ add_elf_sym(symtab_section, 0, 0,
+ ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+ bounds_section->sh_num, "__bounds_start");
+ add_elf_sym(symtab_section, (long)&rt_error, 0,
+ ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
+ SHN_ABS, "rt_error");
+ /* add bound check code */
+ snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
+ tcc_add_file(s1, buf);
+ }
+#endif
+ /* add libc if not memory output */
+ if (s1->output_type != TCC_OUTPUT_MEMORY) {
+ tcc_add_library(s1, "c");
+ tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
+ }
+ /* add various standard linker symbols */
+ add_elf_sym(symtab_section,
+ text_section->data_ptr - text_section->data, 0,
+ ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+ text_section->sh_num, "_etext");
+ add_elf_sym(symtab_section,
+ data_section->data_ptr - data_section->data, 0,
+ ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+ data_section->sh_num, "_edata");
+ add_elf_sym(symtab_section,
+ bss_section->data_ptr - bss_section->data, 0,
+ ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+ bss_section->sh_num, "_end");
}
/* add dynamic sections so that the executable is dynamically linked */
@@ -6898,12 +6960,8 @@ int tcc_output_file(TCCState *s1, const char *filename)
file_type = s1->output_type;
- /* add libc crtn object */
- if (file_type != TCC_OUTPUT_OBJ) {
+ if (file_type != TCC_OUTPUT_OBJ)
tcc_add_runtime(s1);
- tcc_add_library(s1, "c");
- tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
- }
interp = NULL;
dynamic = NULL;
@@ -8012,6 +8070,7 @@ int tcc_run(TCCState *s1, int argc, char **argv)
{
Section *s;
int (*prog_main)(int, char **);
+ void (*bound_init)(void);
int i;
tcc_add_runtime(s1);
@@ -8056,18 +8115,11 @@ int tcc_run(TCCState *s1, int argc, char **argv)
#ifdef CONFIG_TCC_BCHECK
if (do_bounds_check) {
- int *p, *p_end;
- __bound_init();
- /* add all known static regions */
- p = (int *)bounds_section->data;
- p_end = (int *)bounds_section->data_ptr;
- while (p < p_end) {
- __bound_new_region((void *)p[0], p[1]);
- p += 2;
- }
+ /* XXX: use .init section so that it also work in binary ? */
+ bound_init = (void *)get_elf_sym_val("__bound_init");
+ bound_init();
}
#endif
-
return (*prog_main)(argc, argv);
}
@@ -8283,6 +8335,14 @@ int tcc_add_library(TCCState *s, const char *libraryname)
return -1;
}
+int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
+{
+ add_elf_sym(symtab_section, val, 0,
+ ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+ SHN_ABS, name);
+ return 0;
+}
+
int tcc_set_output_type(TCCState *s, int output_type)
{
s->output_type = output_type;
@@ -8302,16 +8362,17 @@ int tcc_set_output_type(TCCState *s, int output_type)
void help(void)
{
printf("tcc version 0.9.8 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
- "usage: tcc [-c] [-o outfile] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
+ "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
" [-g] [-b] [-Ldir] [-llib] [-shared] [-static]\n"
" [--] infile1 [infile2... --] [infile_args...]\n"
"\n"
"General options:\n"
" -c compile only - generate an object file\n"
- " -o outfile set output filename (NOT WORKING YET)\n"
- " -bench output compilation statistics\n"
+ " -o outfile set output filename\n"
" -- allows multiples input files if no -o option given. Also\n"
" separate input files from runtime arguments\n"
+ " -Bdir set tcc internal library path\n"
+ " -bench output compilation statistics\n"
"Preprocessor options:\n"
" -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\n"
@@ -8325,7 +8386,7 @@ void help(void)
" -Ldir add library path 'dir'\n"
" -llib link with dynamic library 'lib'\n"
" -shared generate a shared library (NOT WORKING YET)\n"
- " -static static linking (NOT WORKING YET)\n"
+ " -static static linking\n"
);
}
@@ -8376,6 +8437,9 @@ int main(int argc, char **argv)
tcc_undefine_symbol(s, r + 2);
} else if (r[1] == 'L') {
tcc_add_library_path(s, r + 2);
+ } else if (r[1] == 'B') {
+ /* set tcc utilities path (mainly for tcc development) */
+ tcc_lib_path = r + 2;
} else if (r[1] == 'l') {
dynarray_add((void ***)&libraries, &nb_libraries, r + 2);
} else if (!strcmp(r + 1, "bench")) {
@@ -8436,6 +8500,14 @@ int main(int argc, char **argv)
if (outfile && output_type == TCC_OUTPUT_MEMORY)
output_type = TCC_OUTPUT_EXE;
+ /* warning if not supported features */
+ if (output_type == TCC_OUTPUT_DLL)
+ warning("dll output is currently not supported");
+#ifdef CONFIG_TCC_BCHECK
+ if (do_bounds_check && output_type != TCC_OUTPUT_MEMORY)
+ warning("bounds checking is currently only supported for in-memory execution");
+#endif
+
tcc_set_output_type(s, output_type);
tcc_add_file(s, argv[optind]);