mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
libtcc: new LIBTCCAPI tcc_set_options(TCCState*, const char*str)
This replaces -> use instead: ----------------------------------- - tcc_set_linker -> tcc_set_options(s, "-Wl,..."); - tcc_set_warning -> tcc_set_options(s, "-W..."); - tcc_enable_debug -> tcc_set_options(s, "-g"); parse_args is moved to libtcc.c (now tcc_parse_args). Also some cleanups: - reorder TCCState members - add some comments here and there - do not use argv's directly, make string copies - use const char* in tcc_set_linker - tccpe: use fd instead of fp tested with -D MEM_DEBUG: 0 bytes left
This commit is contained in:
parent
829655949b
commit
05108a3b0a
@ -4,7 +4,8 @@ User interface:
|
||||
- -MD/-MF (automatically generate dependencies for make)
|
||||
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
|
||||
- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
|
||||
- Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
||||
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
||||
- new LIBTCCAPI tcc_set_options() (grischka)
|
||||
|
||||
Platforms:
|
||||
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
|
||||
|
641
libtcc.c
641
libtcc.c
@ -197,8 +197,8 @@ PUB_FUNC char *tcc_fileextension (const char *name)
|
||||
#undef realloc
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
int mem_cur_size;
|
||||
int mem_max_size;
|
||||
ST_DATA int mem_cur_size;
|
||||
ST_DATA int mem_max_size;
|
||||
unsigned malloc_usable_size(void*);
|
||||
#endif
|
||||
|
||||
@ -261,7 +261,7 @@ PUB_FUNC char *tcc_strdup(const char *str)
|
||||
PUB_FUNC void tcc_memstats(void)
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
printf("memory in use: %d\n", mem_cur_size);
|
||||
printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -272,7 +272,7 @@ PUB_FUNC void tcc_memstats(void)
|
||||
/********************************************************/
|
||||
/* dynarrays */
|
||||
|
||||
PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
|
||||
ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
|
||||
{
|
||||
int nb, nb_alloc;
|
||||
void **pp;
|
||||
@ -292,7 +292,7 @@ PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
|
||||
*nb_ptr = nb;
|
||||
}
|
||||
|
||||
PUB_FUNC void dynarray_reset(void *pp, int *n)
|
||||
ST_FUNC void dynarray_reset(void *pp, int *n)
|
||||
{
|
||||
void **p;
|
||||
for (p = *(void***)pp; *n; ++p, --*n)
|
||||
@ -860,10 +860,10 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
||||
define_undef(s);
|
||||
}
|
||||
|
||||
/* cleanup all static data used during compilation */
|
||||
static void tcc_cleanup(void)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if (NULL == tcc_state)
|
||||
return;
|
||||
tcc_state = NULL;
|
||||
@ -915,18 +915,23 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
|
||||
define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
|
||||
|
||||
/* define __TINYC__ 92X */
|
||||
sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
|
||||
sprintf(buffer, "%d", a*10000 + b*100 + c);
|
||||
tcc_define_symbol(s, "__TINYC__", buffer);
|
||||
|
||||
/* standard defines */
|
||||
tcc_define_symbol(s, "__STDC__", NULL);
|
||||
tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
|
||||
|
||||
/* target defines */
|
||||
#if defined(TCC_TARGET_I386)
|
||||
tcc_define_symbol(s, "__i386__", NULL);
|
||||
tcc_define_symbol(s, "__i386", NULL);
|
||||
tcc_define_symbol(s, "i386", NULL);
|
||||
#endif
|
||||
#if defined(TCC_TARGET_X86_64)
|
||||
#elif defined(TCC_TARGET_X86_64)
|
||||
tcc_define_symbol(s, "__x86_64__", NULL);
|
||||
#endif
|
||||
#if defined(TCC_TARGET_ARM)
|
||||
#elif defined(TCC_TARGET_ARM)
|
||||
tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
|
||||
tcc_define_symbol(s, "__arm_elf__", NULL);
|
||||
tcc_define_symbol(s, "__arm_elf", NULL);
|
||||
@ -936,34 +941,31 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
tcc_define_symbol(s, "arm", NULL);
|
||||
tcc_define_symbol(s, "__APCS_32__", NULL);
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
tcc_define_symbol(s, "_WIN32", NULL);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# ifdef TCC_TARGET_X86_64
|
||||
tcc_define_symbol(s, "_WIN64", NULL);
|
||||
#endif
|
||||
# endif
|
||||
#else
|
||||
tcc_define_symbol(s, "__unix__", NULL);
|
||||
tcc_define_symbol(s, "__unix", NULL);
|
||||
tcc_define_symbol(s, "unix", NULL);
|
||||
#if defined(__FreeBSD__)
|
||||
#define str(s) #s
|
||||
tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
|
||||
#undef str
|
||||
#endif
|
||||
#if defined(__FreeBSD_kernel__)
|
||||
tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
|
||||
#endif
|
||||
#if defined(__linux)
|
||||
# if defined(__linux)
|
||||
tcc_define_symbol(s, "__linux__", NULL);
|
||||
tcc_define_symbol(s, "__linux", NULL);
|
||||
# endif
|
||||
# if defined(__FreeBSD__)
|
||||
# define str(s) #s
|
||||
tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
|
||||
# undef str
|
||||
# endif
|
||||
# if defined(__FreeBSD_kernel__)
|
||||
tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
/* tiny C specific defines */
|
||||
sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
|
||||
sprintf(buffer, "%d", a*10000 + b*100 + c);
|
||||
tcc_define_symbol(s, "__TINYC__", buffer);
|
||||
|
||||
/* tiny C & gcc defines */
|
||||
/* TinyCC & gcc defines */
|
||||
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
|
||||
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
|
||||
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
|
||||
@ -978,11 +980,10 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
|
||||
#endif
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* glibc defines */
|
||||
tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
|
||||
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* default library paths */
|
||||
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
||||
/* paths for crt objects */
|
||||
@ -1010,16 +1011,15 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
".dynhashtab", SHF_PRIVATE);
|
||||
s->alacarte_link = 1;
|
||||
s->nocommon = 1;
|
||||
s->section_align = ELF_PAGE_SIZE;
|
||||
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
s->char_is_unsigned = 1;
|
||||
#endif
|
||||
/* enable this if you want symbols with leading underscore on windows: */
|
||||
#if defined(TCC_TARGET_PE) && 0
|
||||
#if 0 //def TCC_TARGET_PE
|
||||
s->leading_underscore = 1;
|
||||
#endif
|
||||
if (s->section_align == 0)
|
||||
s->section_align = ELF_PAGE_SIZE;
|
||||
#ifdef TCC_TARGET_I386
|
||||
s->seg_size = 32;
|
||||
#endif
|
||||
@ -1060,16 +1060,25 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
|
||||
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
||||
|
||||
tcc_free(s1->tcc_lib_path);
|
||||
tcc_free(s1->soname);
|
||||
tcc_free(s1->rpath);
|
||||
tcc_free(s1->init_symbol);
|
||||
tcc_free(s1->fini_symbol);
|
||||
tcc_free(s1->outfile);
|
||||
tcc_free(s1->deps_outfile);
|
||||
dynarray_reset(&s1->files, &s1->nb_files);
|
||||
dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
|
||||
|
||||
tcc_free(s1->tcc_lib_path);
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
#ifdef TCC_IS_NATIVE
|
||||
# ifdef HAVE_SELINUX
|
||||
munmap (s1->write_mem, s1->mem_size);
|
||||
munmap (s1->runtime_mem, s1->mem_size);
|
||||
#else
|
||||
# else
|
||||
tcc_free(s1->runtime_mem);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
tcc_free(s1);
|
||||
}
|
||||
|
||||
@ -1236,7 +1245,6 @@ static int tcc_add_library_internal(TCCState *s, const char *fmt,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* find and load a dll. Return non zero if not found */
|
||||
/* XXX: add '-rpath' option support ? */
|
||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
|
||||
@ -1244,7 +1252,6 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
|
||||
return tcc_add_library_internal(s, "%s/%s", filename, flags,
|
||||
s->library_paths, s->nb_library_paths);
|
||||
}
|
||||
#endif
|
||||
|
||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
|
||||
{
|
||||
@ -1276,9 +1283,13 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
|
||||
{
|
||||
#ifdef TCC_TARGET_PE
|
||||
pe_putimport(s, 0, name, (uintptr_t)val);
|
||||
/* On x86_64 'val' might not be reachable with a 32bit offset.
|
||||
So it is handled here as if it were in a DLL. */
|
||||
pe_putimport(s, 0, name, (uintptr_t)val);
|
||||
#else
|
||||
add_elf_sym(symtab_section, (uintptr_t)val, 0,
|
||||
/* XXX: Same problem on linux but currently "solved" elsewhere
|
||||
via the rather dirty 'runtime_plt_and_got' hack. */
|
||||
add_elf_sym(symtab_section, (uintptr_t)val, 0,
|
||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||
SHN_ABS, name);
|
||||
#endif
|
||||
@ -1341,6 +1352,12 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
|
||||
{
|
||||
tcc_free(s->tcc_lib_path);
|
||||
s->tcc_lib_path = tcc_strdup(path);
|
||||
}
|
||||
|
||||
#define WD_ALL 0x0001 /* warning is activated when using -Wall */
|
||||
#define FD_INVERT 0x0002 /* invert value before storing */
|
||||
|
||||
@ -1382,14 +1399,8 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* enable debug */
|
||||
LIBTCCAPI void tcc_enable_debug(TCCState *s)
|
||||
{
|
||||
s->do_debug = 1;
|
||||
}
|
||||
|
||||
/* set/reset a warning */
|
||||
LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value)
|
||||
static int tcc_set_warning(TCCState *s, const char *warning_name, int value)
|
||||
{
|
||||
int i;
|
||||
const FlagDef *p;
|
||||
@ -1414,30 +1425,28 @@ static const FlagDef flag_defs[] = {
|
||||
};
|
||||
|
||||
/* set/reset a flag */
|
||||
PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value)
|
||||
static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
|
||||
{
|
||||
return set_flag(s, flag_defs, countof(flag_defs),
|
||||
flag_name, value);
|
||||
}
|
||||
|
||||
|
||||
static int strstart(const char *str, const char *val, char **ptr)
|
||||
static int strstart(const char *val, const char **str)
|
||||
{
|
||||
const char *p, *q;
|
||||
p = str;
|
||||
p = *str;
|
||||
q = val;
|
||||
while (*q != '\0') {
|
||||
while (*q) {
|
||||
if (*p != *q)
|
||||
return 0;
|
||||
p++;
|
||||
q++;
|
||||
}
|
||||
if (ptr)
|
||||
*ptr = (char *) p;
|
||||
*str = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Like strstart, but automatically takes into account that ld options can
|
||||
*
|
||||
* - start with double or single dash (e.g. '--soname' or '-soname')
|
||||
@ -1446,7 +1455,7 @@ static int strstart(const char *str, const char *val, char **ptr)
|
||||
*
|
||||
* you provide `val` always in 'option[=]' form (no leading -)
|
||||
*/
|
||||
static int link_option(const char *str, const char *val, char **ptr)
|
||||
static int link_option(const char *str, const char *val, const char **ptr)
|
||||
{
|
||||
const char *p, *q;
|
||||
|
||||
@ -1476,64 +1485,72 @@ static int link_option(const char *str, const char *val, char **ptr)
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
*ptr = (char *) p;
|
||||
*ptr = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *skip_linker_arg(const char **str)
|
||||
{
|
||||
const char *s1 = *str;
|
||||
const char *s2 = strchr(s1, ',');
|
||||
*str = s2 ? s2++ : (s2 = s1 + strlen(s1));
|
||||
return s2;
|
||||
}
|
||||
|
||||
static char *copy_linker_arg(const char *p)
|
||||
{
|
||||
const char *q = p;
|
||||
skip_linker_arg(&q);
|
||||
return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
|
||||
}
|
||||
|
||||
/* set linker options */
|
||||
PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
|
||||
static int tcc_set_linker(TCCState *s, const char *option)
|
||||
{
|
||||
char *p = option;
|
||||
char *end;
|
||||
|
||||
while (option && *option) {
|
||||
end = NULL;
|
||||
|
||||
const char *p = option;
|
||||
char *end = NULL;
|
||||
int ignoring = 0;
|
||||
|
||||
if (link_option(option, "Bsymbolic", &p)) {
|
||||
s->symbolic = 1;
|
||||
} else if (link_option(option, "nostdlib", &p)) {
|
||||
s->nostdlib = 1;
|
||||
} else if (link_option(option, "fini=", &p)) {
|
||||
s->fini_symbol = p;
|
||||
if (s->warn_unsupported)
|
||||
tcc_warning("ignoring -fini %s", p);
|
||||
} else if (link_option(option, "image-base=", &p)) {
|
||||
s->fini_symbol = copy_linker_arg(p);
|
||||
ignoring = 1;
|
||||
} else if (link_option(option, "image-base=", &p)
|
||||
|| link_option(option, "Ttext=", &p)) {
|
||||
s->text_addr = strtoull(p, &end, 16);
|
||||
s->has_text_addr = 1;
|
||||
} else if (link_option(option, "init=", &p)) {
|
||||
s->init_symbol = p;
|
||||
if (s->warn_unsupported)
|
||||
tcc_warning("ignoring -init %s", p);
|
||||
s->init_symbol = copy_linker_arg(p);
|
||||
ignoring = 1;
|
||||
} else if (link_option(option, "oformat=", &p)) {
|
||||
#if defined(TCC_TARGET_PE)
|
||||
if (strstart(p, "pe-", NULL)) {
|
||||
if (strstart("pe-", &p)) {
|
||||
#elif defined(TCC_TARGET_X86_64)
|
||||
if (strstart("elf64-", &p)) {
|
||||
#else
|
||||
#if defined(TCC_TARGET_X86_64)
|
||||
if (strstart(p, "elf64-", NULL)) {
|
||||
#else
|
||||
if (strstart(p, "elf32-", NULL)) {
|
||||
#endif
|
||||
if (strstart("elf32-", &p)) {
|
||||
#endif
|
||||
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
||||
} else if (!strcmp(p, "binary")) {
|
||||
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
||||
} else
|
||||
#ifdef TCC_TARGET_COFF
|
||||
if (!strcmp(p, "coff")) {
|
||||
} else if (!strcmp(p, "coff")) {
|
||||
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return p;
|
||||
}
|
||||
} else
|
||||
goto err;
|
||||
|
||||
} else if (link_option(option, "rpath=", &p)) {
|
||||
s->rpath = p;
|
||||
s->rpath = copy_linker_arg(p);
|
||||
} else if (link_option(option, "section-alignment=", &p)) {
|
||||
s->section_align = strtoul(p, &end, 16);
|
||||
} else if (link_option(option, "soname=", &p)) {
|
||||
s->soname = p;
|
||||
multi = 0;
|
||||
s->soname = copy_linker_arg(p);
|
||||
#ifdef TCC_TARGET_PE
|
||||
} else if (link_option(option, "file-alignment=", &p)) {
|
||||
s->pe_file_align = strtoul(p, &end, 16);
|
||||
@ -1561,98 +1578,346 @@ PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
|
||||
if (!strcmp(p, "wince")) {
|
||||
s->pe_subsystem = 9;
|
||||
#endif
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (link_option(option, "Ttext=", &p)) {
|
||||
s->text_addr = strtoull(p, &end, 16);
|
||||
s->has_text_addr = 1;
|
||||
} else {
|
||||
char *comma_ptr = strchr(option, ',');
|
||||
if (comma_ptr)
|
||||
*comma_ptr = '\0';
|
||||
return option;
|
||||
}
|
||||
|
||||
if (multi) {
|
||||
option = NULL;
|
||||
p = strchr( (end) ? end : p, ',');
|
||||
if (p) {
|
||||
*p = 0; /* terminate last option */
|
||||
option = ++p;
|
||||
}
|
||||
} else
|
||||
option = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
|
||||
{
|
||||
tcc_free(s->tcc_lib_path);
|
||||
s->tcc_lib_path = tcc_strdup(path);
|
||||
}
|
||||
|
||||
PUB_FUNC char *tcc_default_target(TCCState *s, const char *default_file)
|
||||
{
|
||||
char buf[1024];
|
||||
char *ext;
|
||||
const char *name = "a";
|
||||
|
||||
if (default_file && strcmp(default_file, "-"))
|
||||
name = tcc_basename(default_file);
|
||||
pstrcpy(buf, sizeof(buf), name);
|
||||
ext = tcc_fileextension(buf);
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (s->output_type == TCC_OUTPUT_DLL)
|
||||
strcpy(ext, ".dll");
|
||||
else
|
||||
if (s->output_type == TCC_OUTPUT_EXE)
|
||||
strcpy(ext, ".exe");
|
||||
else
|
||||
goto err;
|
||||
#endif
|
||||
if (( (s->output_type == TCC_OUTPUT_OBJ && !s->reloc_output) ||
|
||||
(s->output_type == TCC_OUTPUT_PREPROCESS) )
|
||||
&& *ext)
|
||||
strcpy(ext, ".o");
|
||||
else
|
||||
strcpy(buf, "a.out");
|
||||
} else
|
||||
goto err;
|
||||
|
||||
return tcc_strdup(buf);
|
||||
if (ignoring && s->warn_unsupported) err: {
|
||||
char buf[100], *e;
|
||||
pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e);
|
||||
if (ignoring)
|
||||
tcc_warning("unsupported linker option '%s'", buf);
|
||||
else
|
||||
tcc_error("unsupported linker option '%s'", buf);
|
||||
}
|
||||
option = skip_linker_arg(&p);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct TCCOption {
|
||||
const char *name;
|
||||
uint16_t index;
|
||||
uint16_t flags;
|
||||
} TCCOption;
|
||||
|
||||
PUB_FUNC void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||
enum {
|
||||
TCC_OPTION_HELP,
|
||||
TCC_OPTION_I,
|
||||
TCC_OPTION_D,
|
||||
TCC_OPTION_U,
|
||||
TCC_OPTION_L,
|
||||
TCC_OPTION_B,
|
||||
TCC_OPTION_l,
|
||||
TCC_OPTION_bench,
|
||||
TCC_OPTION_bt,
|
||||
TCC_OPTION_b,
|
||||
TCC_OPTION_g,
|
||||
TCC_OPTION_c,
|
||||
TCC_OPTION_static,
|
||||
TCC_OPTION_shared,
|
||||
TCC_OPTION_soname,
|
||||
TCC_OPTION_o,
|
||||
TCC_OPTION_r,
|
||||
TCC_OPTION_s,
|
||||
TCC_OPTION_Wl,
|
||||
TCC_OPTION_W,
|
||||
TCC_OPTION_O,
|
||||
TCC_OPTION_m,
|
||||
TCC_OPTION_f,
|
||||
TCC_OPTION_isystem,
|
||||
TCC_OPTION_nostdinc,
|
||||
TCC_OPTION_nostdlib,
|
||||
TCC_OPTION_print_search_dirs,
|
||||
TCC_OPTION_rdynamic,
|
||||
TCC_OPTION_pedantic,
|
||||
TCC_OPTION_pthread,
|
||||
TCC_OPTION_run,
|
||||
TCC_OPTION_v,
|
||||
TCC_OPTION_w,
|
||||
TCC_OPTION_pipe,
|
||||
TCC_OPTION_E,
|
||||
TCC_OPTION_MD,
|
||||
TCC_OPTION_MF,
|
||||
TCC_OPTION_x,
|
||||
};
|
||||
|
||||
#define TCC_OPTION_HAS_ARG 0x0001
|
||||
#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
|
||||
|
||||
static const TCCOption tcc_options[] = {
|
||||
{ "h", TCC_OPTION_HELP, 0 },
|
||||
{ "-help", TCC_OPTION_HELP, 0 },
|
||||
{ "?", TCC_OPTION_HELP, 0 },
|
||||
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
|
||||
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
|
||||
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
|
||||
{ "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
|
||||
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
||||
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "bench", TCC_OPTION_bench, 0 },
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
{ "b", TCC_OPTION_b, 0 },
|
||||
#endif
|
||||
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "c", TCC_OPTION_c, 0 },
|
||||
{ "static", TCC_OPTION_static, 0 },
|
||||
{ "shared", TCC_OPTION_shared, 0 },
|
||||
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
|
||||
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
||||
{ "pedantic", TCC_OPTION_pedantic, 0},
|
||||
{ "pthread", TCC_OPTION_pthread, 0},
|
||||
{ "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
||||
{ "r", TCC_OPTION_r, 0 },
|
||||
{ "s", TCC_OPTION_s, 0 },
|
||||
{ "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
|
||||
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
|
||||
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
||||
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
||||
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "w", TCC_OPTION_w, 0 },
|
||||
{ "pipe", TCC_OPTION_pipe, 0},
|
||||
{ "E", TCC_OPTION_E, 0},
|
||||
{ "MD", TCC_OPTION_MD, 0},
|
||||
{ "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
|
||||
{ "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
|
||||
{ NULL, 0, 0 },
|
||||
};
|
||||
|
||||
static void parse_option_D(TCCState *s1, const char *optarg)
|
||||
{
|
||||
FILE *depout;
|
||||
char buf[1024], *ext;
|
||||
int i;
|
||||
char *sym = tcc_strdup(optarg);
|
||||
char *value = strchr(sym, '=');
|
||||
if (value)
|
||||
*value++ = '\0';
|
||||
tcc_define_symbol(s1, sym, value);
|
||||
tcc_free(sym);
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
/* compute filename automatically
|
||||
* dir/file.o -> dir/file.d */
|
||||
pstrcpy(buf, sizeof(buf), target);
|
||||
ext = tcc_fileextension(buf);
|
||||
pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
|
||||
filename = buf;
|
||||
PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
||||
{
|
||||
const TCCOption *popt;
|
||||
const char *optarg, *r;
|
||||
int run = 0;
|
||||
int pthread = 0;
|
||||
int optind = 0;
|
||||
|
||||
/* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */
|
||||
CString linker_arg;
|
||||
cstr_new(&linker_arg);
|
||||
|
||||
while (optind < argc) {
|
||||
|
||||
r = argv[optind++];
|
||||
if (r[0] != '-' || r[1] == '\0') {
|
||||
/* add a new file */
|
||||
dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
|
||||
if (run) {
|
||||
optind--;
|
||||
/* argv[0] will be this file */
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s->verbose)
|
||||
printf("<- %s\n", filename);
|
||||
/* find option in table */
|
||||
for(popt = tcc_options; ; ++popt) {
|
||||
const char *p1 = popt->name;
|
||||
const char *r1 = r + 1;
|
||||
if (p1 == NULL)
|
||||
tcc_error("invalid option -- '%s'", r);
|
||||
if (!strstart(p1, &r1))
|
||||
continue;
|
||||
optarg = r1;
|
||||
if (popt->flags & TCC_OPTION_HAS_ARG) {
|
||||
if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
|
||||
if (optind >= argc)
|
||||
tcc_error("argument to '%s' is missing", r);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
} else if (*r1 != '\0')
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX return err codes instead of error() ? */
|
||||
depout = fopen(filename, "w");
|
||||
if (!depout)
|
||||
tcc_error("could not open '%s'", filename);
|
||||
switch(popt->index) {
|
||||
case TCC_OPTION_HELP:
|
||||
return 0;
|
||||
case TCC_OPTION_I:
|
||||
if (tcc_add_include_path(s, optarg) < 0)
|
||||
tcc_error("too many include paths");
|
||||
break;
|
||||
case TCC_OPTION_D:
|
||||
parse_option_D(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_U:
|
||||
tcc_undefine_symbol(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_L:
|
||||
tcc_add_library_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_B:
|
||||
/* set tcc utilities path (mainly for tcc development) */
|
||||
tcc_set_lib_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_l:
|
||||
dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
|
||||
s->nb_libraries++;
|
||||
break;
|
||||
case TCC_OPTION_pthread:
|
||||
parse_option_D(s, "_REENTRANT");
|
||||
pthread = 1;
|
||||
break;
|
||||
case TCC_OPTION_bench:
|
||||
s->do_bench = 1;
|
||||
break;
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
case TCC_OPTION_bt:
|
||||
tcc_set_num_callers(atoi(optarg));
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
case TCC_OPTION_b:
|
||||
s->do_bounds_check = 1;
|
||||
s->do_debug = 1;
|
||||
break;
|
||||
#endif
|
||||
case TCC_OPTION_g:
|
||||
s->do_debug = 1;
|
||||
break;
|
||||
case TCC_OPTION_c:
|
||||
s->output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
case TCC_OPTION_static:
|
||||
s->static_link = 1;
|
||||
break;
|
||||
case TCC_OPTION_shared:
|
||||
s->output_type = TCC_OUTPUT_DLL;
|
||||
break;
|
||||
case TCC_OPTION_soname:
|
||||
s->soname = tcc_strdup(optarg);
|
||||
break;
|
||||
case TCC_OPTION_m:
|
||||
s->option_m = tcc_strdup(optarg);
|
||||
break;
|
||||
case TCC_OPTION_o:
|
||||
s->outfile = tcc_strdup(optarg);
|
||||
break;
|
||||
case TCC_OPTION_r:
|
||||
/* generate a .o merging several output files */
|
||||
s->option_r = 1;
|
||||
s->output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
case TCC_OPTION_isystem:
|
||||
tcc_add_sysinclude_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_nostdinc:
|
||||
s->nostdinc = 1;
|
||||
break;
|
||||
case TCC_OPTION_nostdlib:
|
||||
s->nostdlib = 1;
|
||||
break;
|
||||
case TCC_OPTION_print_search_dirs:
|
||||
s->print_search_dirs = 1;
|
||||
break;
|
||||
case TCC_OPTION_run:
|
||||
s->output_type = TCC_OUTPUT_MEMORY;
|
||||
tcc_set_options(s, optarg);
|
||||
run = 1;
|
||||
break;
|
||||
case TCC_OPTION_v:
|
||||
do ++s->verbose; while (*optarg++ == 'v');
|
||||
break;
|
||||
case TCC_OPTION_f:
|
||||
if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_W:
|
||||
if (tcc_set_warning(s, optarg, 1) < 0 &&
|
||||
s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_w:
|
||||
s->warn_none = 1;
|
||||
break;
|
||||
case TCC_OPTION_rdynamic:
|
||||
s->rdynamic = 1;
|
||||
break;
|
||||
case TCC_OPTION_Wl:
|
||||
if (linker_arg.size)
|
||||
--linker_arg.size, cstr_ccat(&linker_arg, ',');
|
||||
cstr_cat(&linker_arg, optarg);
|
||||
cstr_ccat(&linker_arg, '\0');
|
||||
break;
|
||||
case TCC_OPTION_E:
|
||||
s->output_type = TCC_OUTPUT_PREPROCESS;
|
||||
break;
|
||||
case TCC_OPTION_MD:
|
||||
s->gen_deps = 1;
|
||||
break;
|
||||
case TCC_OPTION_MF:
|
||||
s->deps_outfile = tcc_strdup(optarg);
|
||||
break;
|
||||
case TCC_OPTION_O:
|
||||
case TCC_OPTION_pedantic:
|
||||
case TCC_OPTION_pipe:
|
||||
case TCC_OPTION_s:
|
||||
case TCC_OPTION_x:
|
||||
/* ignored */
|
||||
break;
|
||||
default:
|
||||
if (s->warn_unsupported) {
|
||||
unsupported_option:
|
||||
tcc_warning("unsupported option '%s'", r);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(depout, "%s : \\\n", target);
|
||||
for (i=0; i<s->nb_target_deps; ++i)
|
||||
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
||||
fprintf(depout, "\n");
|
||||
fclose(depout);
|
||||
if (pthread && s->output_type != TCC_OUTPUT_OBJ)
|
||||
tcc_set_options(s, "-lpthread");
|
||||
|
||||
tcc_set_linker(s, (const char *)linker_arg.data);
|
||||
cstr_free(&linker_arg);
|
||||
|
||||
return optind;
|
||||
}
|
||||
|
||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
|
||||
{
|
||||
const char *s1;
|
||||
char **argv, *arg;
|
||||
int argc, len;
|
||||
int ret;
|
||||
|
||||
argc = 0, argv = NULL;
|
||||
for(;;) {
|
||||
while (is_space(*str))
|
||||
str++;
|
||||
if (*str == '\0')
|
||||
break;
|
||||
s1 = str;
|
||||
while (*str != '\0' && !is_space(*str))
|
||||
str++;
|
||||
len = str - s1;
|
||||
arg = tcc_malloc(len + 1);
|
||||
pstrncpy(arg, s1, len);
|
||||
dynarray_add((void ***)&argv, &argc, arg);
|
||||
}
|
||||
ret = tcc_parse_args(s, argc, argv);
|
||||
dynarray_reset(&argv, &argc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
|
||||
@ -1668,53 +1933,3 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
|
||||
tt, (int)(total_lines / tt),
|
||||
total_bytes / tt / 1000000.0);
|
||||
}
|
||||
|
||||
static void print_paths(const char *msg, char **paths, int nb_paths)
|
||||
{
|
||||
int i;
|
||||
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
||||
for(i = 0; i < nb_paths; i++)
|
||||
printf(" %s\n", paths[i]);
|
||||
}
|
||||
|
||||
PUB_FUNC void tcc_display_info(TCCState *s, int what)
|
||||
{
|
||||
switch (what) {
|
||||
case 0:
|
||||
printf("tcc version %s ("
|
||||
#ifdef TCC_TARGET_I386
|
||||
"i386"
|
||||
# ifdef TCC_TARGET_PE
|
||||
" Win32"
|
||||
# endif
|
||||
#elif defined TCC_TARGET_X86_64
|
||||
"x86-64"
|
||||
# ifdef TCC_TARGET_PE
|
||||
" Win64"
|
||||
# endif
|
||||
#elif defined TCC_TARGET_ARM
|
||||
"ARM"
|
||||
# ifdef TCC_ARM_HARDFLOAT
|
||||
" Hard Float"
|
||||
# endif
|
||||
# ifdef TCC_TARGET_PE
|
||||
" WinCE"
|
||||
# endif
|
||||
#endif
|
||||
#ifndef TCC_TARGET_PE
|
||||
# ifdef __linux
|
||||
" Linux"
|
||||
# endif
|
||||
#endif
|
||||
")\n", TCC_VERSION);
|
||||
break;
|
||||
case 1:
|
||||
printf("install: %s/\n", s->tcc_lib_path);
|
||||
/* print_paths("programs", NULL, 0); */
|
||||
print_paths("crt", s->crt_paths, s->nb_crt_paths);
|
||||
print_paths("libraries", s->library_paths, s->nb_library_paths);
|
||||
print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
39
libtcc.h
39
libtcc.h
@ -19,18 +19,15 @@ LIBTCCAPI TCCState *tcc_new(void);
|
||||
/* free a TCC compilation context */
|
||||
LIBTCCAPI void tcc_delete(TCCState *s);
|
||||
|
||||
/* add debug information in the generated code */
|
||||
LIBTCCAPI void tcc_enable_debug(TCCState *s);
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||
|
||||
/* set error/warning display callback */
|
||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
|
||||
void (*error_func)(void *opaque, const char *msg));
|
||||
|
||||
/* set/reset a warning */
|
||||
LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value);
|
||||
|
||||
/* set linker option */
|
||||
LIBTCCAPI const char * tcc_set_linker(TCCState *s, char *option, int multi);
|
||||
/* set options as from command line (multiple supported) */
|
||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
||||
|
||||
/*****************************/
|
||||
/* preprocessor */
|
||||
@ -50,29 +47,22 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||
/*****************************/
|
||||
/* compiling */
|
||||
|
||||
/* add a file (either a C file, dll, an object, a library or an ld
|
||||
script). Return -1 if error. */
|
||||
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
|
||||
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
||||
|
||||
/* compile a string containing a C source. Return non zero if
|
||||
error. */
|
||||
/* compile a string containing a C source. Return -1 if error. */
|
||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
||||
|
||||
/*****************************/
|
||||
/* linking commands */
|
||||
|
||||
/* set output type. MUST BE CALLED before any compilation */
|
||||
#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
|
||||
output file) (default) */
|
||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||
#define TCC_OUTPUT_MEMORY 0 /* output will be run in memory (default) */
|
||||
#define TCC_OUTPUT_EXE 1 /* executable file */
|
||||
#define TCC_OUTPUT_DLL 2 /* dynamic library */
|
||||
#define TCC_OUTPUT_OBJ 3 /* object file */
|
||||
#define TCC_OUTPUT_PREPROCESS 4 /* preprocessed file (used internally) */
|
||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||
|
||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||
#define TCC_OUTPUT_PREPROCESS 4 /* only preprocess (used internally) */
|
||||
|
||||
/* equivalent to -Lpath option */
|
||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
@ -91,21 +81,18 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
||||
tcc_relocate() before. */
|
||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* do all relocations (needed before using tcc_get_symbol())
|
||||
possible values for 'ptr':
|
||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
||||
/* possible values for 'ptr':
|
||||
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
||||
- NULL : return required memory size for the step below
|
||||
- memory address : copy code to memory passed by the caller
|
||||
returns -1 on error. */
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
||||
returns -1 if error. */
|
||||
#define TCC_RELOCATE_AUTO (void*)1
|
||||
|
||||
/* return symbol value or NULL if not found */
|
||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
606
tcc.c
606
tcc.c
@ -24,22 +24,6 @@
|
||||
#include "tcc.h"
|
||||
#endif
|
||||
|
||||
static char **files;
|
||||
static int nb_files, nb_libraries;
|
||||
static int multiple_files;
|
||||
static int print_search_dirs;
|
||||
static int output_type;
|
||||
static int reloc_output;
|
||||
static char *outfile;
|
||||
static int do_bench = 0;
|
||||
static int gen_deps;
|
||||
static const char *deps_outfile;
|
||||
static const char *m_option;
|
||||
static CString linker_arg;
|
||||
|
||||
#define TCC_OPTION_HAS_ARG 0x0001
|
||||
#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
||||
@ -60,19 +44,16 @@ static void help(void)
|
||||
" -Idir add include path 'dir'\n"
|
||||
" -Dsym[=val] define 'sym' with value 'val'\n"
|
||||
" -Usym undefine 'sym'\n"
|
||||
" -nostdinc do not use standard system include paths\n"
|
||||
"Linker options:\n"
|
||||
" -Ldir add library path 'dir'\n"
|
||||
" -llib link with dynamic or static library 'lib'\n"
|
||||
" -Bdir use 'dir' as tcc internal library and include path\n"
|
||||
" -nostdlib do not link with standard crt and libraries\n"
|
||||
" -pthread link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
|
||||
" -r generate (relocatable) object file\n"
|
||||
" -rdynamic export all global symbols to dynamic linker\n"
|
||||
" -shared generate a shared library\n"
|
||||
" -soname set name for shared library to be used at runtime\n"
|
||||
" -static static linking\n"
|
||||
" -Wl,opt[=val] set linker option 'opt' (see manual)\n"
|
||||
" -Wl,-opt[=val] set linker option (see manual)\n"
|
||||
"Debugger options:\n"
|
||||
" -g generate runtime debug info\n"
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
@ -82,146 +63,14 @@ static void help(void)
|
||||
" -bt N show N callers in stack traces\n"
|
||||
#endif
|
||||
"Misc options:\n"
|
||||
" -nostdinc do not use standard system include paths\n"
|
||||
" -nostdlib do not link with standard crt and libraries\n"
|
||||
" -Bdir use 'dir' as tcc internal library and include path\n"
|
||||
" -MD generate target dependencies for make\n"
|
||||
" -MF depfile put generated dependencies here\n"
|
||||
);
|
||||
}
|
||||
|
||||
typedef struct TCCOption {
|
||||
const char *name;
|
||||
uint16_t index;
|
||||
uint16_t flags;
|
||||
} TCCOption;
|
||||
|
||||
enum {
|
||||
TCC_OPTION_HELP,
|
||||
TCC_OPTION_I,
|
||||
TCC_OPTION_D,
|
||||
TCC_OPTION_U,
|
||||
TCC_OPTION_L,
|
||||
TCC_OPTION_B,
|
||||
TCC_OPTION_l,
|
||||
TCC_OPTION_bench,
|
||||
TCC_OPTION_bt,
|
||||
TCC_OPTION_b,
|
||||
TCC_OPTION_g,
|
||||
TCC_OPTION_c,
|
||||
TCC_OPTION_static,
|
||||
TCC_OPTION_shared,
|
||||
TCC_OPTION_soname,
|
||||
TCC_OPTION_o,
|
||||
TCC_OPTION_r,
|
||||
TCC_OPTION_s,
|
||||
TCC_OPTION_Wl,
|
||||
TCC_OPTION_W,
|
||||
TCC_OPTION_O,
|
||||
TCC_OPTION_m,
|
||||
TCC_OPTION_f,
|
||||
TCC_OPTION_isystem,
|
||||
TCC_OPTION_nostdinc,
|
||||
TCC_OPTION_nostdlib,
|
||||
TCC_OPTION_print_search_dirs,
|
||||
TCC_OPTION_rdynamic,
|
||||
TCC_OPTION_pedantic,
|
||||
TCC_OPTION_pthread,
|
||||
TCC_OPTION_run,
|
||||
TCC_OPTION_v,
|
||||
TCC_OPTION_w,
|
||||
TCC_OPTION_pipe,
|
||||
TCC_OPTION_E,
|
||||
TCC_OPTION_MD,
|
||||
TCC_OPTION_MF,
|
||||
TCC_OPTION_x,
|
||||
};
|
||||
|
||||
static const TCCOption tcc_options[] = {
|
||||
{ "h", TCC_OPTION_HELP, 0 },
|
||||
{ "-help", TCC_OPTION_HELP, 0 },
|
||||
{ "?", TCC_OPTION_HELP, 0 },
|
||||
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
|
||||
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
|
||||
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
|
||||
{ "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
|
||||
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
||||
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "bench", TCC_OPTION_bench, 0 },
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
{ "b", TCC_OPTION_b, 0 },
|
||||
#endif
|
||||
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "c", TCC_OPTION_c, 0 },
|
||||
{ "static", TCC_OPTION_static, 0 },
|
||||
{ "shared", TCC_OPTION_shared, 0 },
|
||||
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
|
||||
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
||||
{ "pedantic", TCC_OPTION_pedantic, 0},
|
||||
{ "pthread", TCC_OPTION_pthread, 0},
|
||||
{ "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
||||
{ "r", TCC_OPTION_r, 0 },
|
||||
{ "s", TCC_OPTION_s, 0 },
|
||||
{ "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
|
||||
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
|
||||
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
||||
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
||||
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "w", TCC_OPTION_w, 0 },
|
||||
{ "pipe", TCC_OPTION_pipe, 0},
|
||||
{ "E", TCC_OPTION_E, 0},
|
||||
{ "MD", TCC_OPTION_MD, 0},
|
||||
{ "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
|
||||
{ "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
|
||||
{ NULL, 0, 0 },
|
||||
};
|
||||
|
||||
static int64_t getclock_us(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _timeb tb;
|
||||
_ftime(&tb);
|
||||
return (tb.time * 1000LL + tb.millitm) * 1000LL;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000LL + tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* convert 'str' into an array of space separated strings */
|
||||
static int expand_args(char ***pargv, const char *str)
|
||||
{
|
||||
const char *s1;
|
||||
char **argv, *arg;
|
||||
int argc, len;
|
||||
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
for(;;) {
|
||||
while (is_space(*str))
|
||||
str++;
|
||||
if (*str == '\0')
|
||||
break;
|
||||
s1 = str;
|
||||
while (*str != '\0' && !is_space(*str))
|
||||
str++;
|
||||
len = str - s1;
|
||||
arg = tcc_malloc(len + 1);
|
||||
memcpy(arg, s1, len);
|
||||
arg[len] = '\0';
|
||||
dynarray_add((void ***)&argv, &argc, arg);
|
||||
}
|
||||
*pargv = argv;
|
||||
return argc;
|
||||
}
|
||||
|
||||
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#ifdef _WIN32
|
||||
@ -266,317 +115,198 @@ static void exec_other_tcc(TCCState *s, char **argv, const char *optarg)
|
||||
tcc_warning("unsupported option \"-m%s\"", optarg);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define exec_other_tcc(s, argv, optarg)
|
||||
#endif
|
||||
|
||||
static void parse_option_D(TCCState *s1, const char *optarg)
|
||||
static void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||
{
|
||||
char *sym = tcc_strdup(optarg);
|
||||
char *value = strchr(sym, '=');
|
||||
if (value)
|
||||
*value++ = '\0';
|
||||
tcc_define_symbol(s1, sym, value);
|
||||
tcc_free(sym);
|
||||
FILE *depout;
|
||||
char buf[1024], *ext;
|
||||
int i;
|
||||
|
||||
if (!filename) {
|
||||
/* compute filename automatically
|
||||
* dir/file.o -> dir/file.d */
|
||||
pstrcpy(buf, sizeof(buf), target);
|
||||
ext = tcc_fileextension(buf);
|
||||
pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
|
||||
filename = buf;
|
||||
}
|
||||
|
||||
if (s->verbose)
|
||||
printf("<- %s\n", filename);
|
||||
|
||||
/* XXX return err codes instead of error() ? */
|
||||
depout = fopen(filename, "w");
|
||||
if (!depout)
|
||||
tcc_error("could not open '%s'", filename);
|
||||
|
||||
fprintf(depout, "%s : \\\n", target);
|
||||
for (i=0; i<s->nb_target_deps; ++i)
|
||||
fprintf(depout, " %s \\\n", s->target_deps[i]);
|
||||
fprintf(depout, "\n");
|
||||
fclose(depout);
|
||||
}
|
||||
|
||||
static int parse_args(TCCState *s, int argc, char **argv)
|
||||
static char *default_outputfile(TCCState *s, const char *first_file)
|
||||
{
|
||||
int optind;
|
||||
const TCCOption *popt;
|
||||
const char *optarg, *p1, *r1;
|
||||
char *r;
|
||||
int was_pthread;
|
||||
char buf[1024];
|
||||
char *ext;
|
||||
const char *name = "a";
|
||||
|
||||
was_pthread = 0; /* is set if commandline contains -pthread key */
|
||||
optind = 0;
|
||||
cstr_new(&linker_arg);
|
||||
|
||||
while (optind < argc) {
|
||||
|
||||
r = argv[optind++];
|
||||
if (r[0] != '-' || r[1] == '\0') {
|
||||
/* add a new file */
|
||||
dynarray_add((void ***)&files, &nb_files, r);
|
||||
if (!multiple_files) {
|
||||
optind--;
|
||||
/* argv[0] will be this file */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* find option in table (match only the first chars */
|
||||
popt = tcc_options;
|
||||
for(;;) {
|
||||
p1 = popt->name;
|
||||
if (p1 == NULL)
|
||||
tcc_error("invalid option -- '%s'", r);
|
||||
r1 = r + 1;
|
||||
for(;;) {
|
||||
if (*p1 == '\0')
|
||||
goto option_found;
|
||||
if (*r1 != *p1)
|
||||
break;
|
||||
p1++;
|
||||
r1++;
|
||||
}
|
||||
popt++;
|
||||
}
|
||||
option_found:
|
||||
if (popt->flags & TCC_OPTION_HAS_ARG) {
|
||||
if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
|
||||
optarg = r1;
|
||||
} else {
|
||||
if (optind >= argc)
|
||||
tcc_error("argument to '%s' is missing", r);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
} else {
|
||||
if (*r1 != '\0')
|
||||
return 0;
|
||||
optarg = NULL;
|
||||
}
|
||||
|
||||
switch(popt->index) {
|
||||
case TCC_OPTION_HELP:
|
||||
return 0;
|
||||
|
||||
case TCC_OPTION_I:
|
||||
if (tcc_add_include_path(s, optarg) < 0)
|
||||
tcc_error("too many include paths");
|
||||
break;
|
||||
case TCC_OPTION_D:
|
||||
parse_option_D(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_U:
|
||||
tcc_undefine_symbol(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_L:
|
||||
tcc_add_library_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_B:
|
||||
/* set tcc utilities path (mainly for tcc development) */
|
||||
tcc_set_lib_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_l:
|
||||
dynarray_add((void ***)&files, &nb_files, r);
|
||||
nb_libraries++;
|
||||
break;
|
||||
case TCC_OPTION_pthread:
|
||||
was_pthread = 1;
|
||||
parse_option_D(s, "_REENTRANT");
|
||||
break;
|
||||
case TCC_OPTION_bench:
|
||||
do_bench = 1;
|
||||
break;
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
case TCC_OPTION_bt:
|
||||
tcc_set_num_callers(atoi(optarg));
|
||||
break;
|
||||
if (first_file && strcmp(first_file, "-"))
|
||||
name = tcc_basename(first_file);
|
||||
pstrcpy(buf, sizeof(buf), name);
|
||||
ext = tcc_fileextension(buf);
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (s->output_type == TCC_OUTPUT_DLL)
|
||||
strcpy(ext, ".dll");
|
||||
else
|
||||
if (s->output_type == TCC_OUTPUT_EXE)
|
||||
strcpy(ext, ".exe");
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
case TCC_OPTION_b:
|
||||
s->do_bounds_check = 1;
|
||||
s->do_debug = 1;
|
||||
break;
|
||||
if (( (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) ||
|
||||
(s->output_type == TCC_OUTPUT_PREPROCESS) )
|
||||
&& *ext)
|
||||
strcpy(ext, ".o");
|
||||
else
|
||||
strcpy(buf, "a.out");
|
||||
|
||||
return tcc_strdup(buf);
|
||||
}
|
||||
|
||||
static void print_paths(const char *msg, char **paths, int nb_paths)
|
||||
{
|
||||
int i;
|
||||
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
||||
for(i = 0; i < nb_paths; i++)
|
||||
printf(" %s\n", paths[i]);
|
||||
}
|
||||
|
||||
static void display_info(TCCState *s, int what)
|
||||
{
|
||||
switch (what) {
|
||||
case 0:
|
||||
printf("tcc version %s ("
|
||||
#ifdef TCC_TARGET_I386
|
||||
"i386"
|
||||
# ifdef TCC_TARGET_PE
|
||||
" Win32"
|
||||
# endif
|
||||
#elif defined TCC_TARGET_X86_64
|
||||
"x86-64"
|
||||
# ifdef TCC_TARGET_PE
|
||||
" Win64"
|
||||
# endif
|
||||
#elif defined TCC_TARGET_ARM
|
||||
"ARM"
|
||||
# ifdef TCC_ARM_HARDFLOAT
|
||||
" Hard Float"
|
||||
# endif
|
||||
# ifdef TCC_TARGET_PE
|
||||
" WinCE"
|
||||
# endif
|
||||
#endif
|
||||
case TCC_OPTION_g:
|
||||
s->do_debug = 1;
|
||||
#ifndef TCC_TARGET_PE
|
||||
# ifdef __linux
|
||||
" Linux"
|
||||
# endif
|
||||
#endif
|
||||
")\n", TCC_VERSION);
|
||||
break;
|
||||
case TCC_OPTION_c:
|
||||
multiple_files = 1;
|
||||
output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
case TCC_OPTION_static:
|
||||
s->static_link = 1;
|
||||
break;
|
||||
case TCC_OPTION_shared:
|
||||
output_type = TCC_OUTPUT_DLL;
|
||||
break;
|
||||
case TCC_OPTION_soname:
|
||||
s->soname = optarg;
|
||||
break;
|
||||
case TCC_OPTION_m:
|
||||
m_option = optarg;
|
||||
break;
|
||||
case TCC_OPTION_o:
|
||||
multiple_files = 1;
|
||||
outfile = tcc_strdup(optarg);
|
||||
break;
|
||||
case TCC_OPTION_r:
|
||||
/* generate a .o merging several output files */
|
||||
reloc_output = 1;
|
||||
output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
case TCC_OPTION_isystem:
|
||||
tcc_add_sysinclude_path(s, optarg);
|
||||
break;
|
||||
case TCC_OPTION_nostdinc:
|
||||
s->nostdinc = 1;
|
||||
break;
|
||||
case TCC_OPTION_nostdlib:
|
||||
s->nostdlib = 1;
|
||||
break;
|
||||
case TCC_OPTION_print_search_dirs:
|
||||
print_search_dirs = 1;
|
||||
break;
|
||||
case TCC_OPTION_run:
|
||||
{
|
||||
int argc1;
|
||||
char **argv1;
|
||||
argc1 = expand_args(&argv1, optarg);
|
||||
if (argc1 > 0) {
|
||||
parse_args(s, argc1, argv1);
|
||||
}
|
||||
multiple_files = 0;
|
||||
output_type = TCC_OUTPUT_MEMORY;
|
||||
case 1:
|
||||
printf("install: %s/\n", s->tcc_lib_path);
|
||||
/* print_paths("programs", NULL, 0); */
|
||||
print_paths("crt", s->crt_paths, s->nb_crt_paths);
|
||||
print_paths("libraries", s->library_paths, s->nb_library_paths);
|
||||
print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||
break;
|
||||
}
|
||||
case TCC_OPTION_v:
|
||||
do ++s->verbose; while (*optarg++ == 'v');
|
||||
break;
|
||||
case TCC_OPTION_f:
|
||||
if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_W:
|
||||
if (tcc_set_warning(s, optarg, 1) < 0 &&
|
||||
s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_w:
|
||||
s->warn_none = 1;
|
||||
break;
|
||||
case TCC_OPTION_rdynamic:
|
||||
s->rdynamic = 1;
|
||||
break;
|
||||
case TCC_OPTION_Wl:
|
||||
if (linker_arg.size)
|
||||
--linker_arg.size, cstr_ccat(&linker_arg, ',');
|
||||
cstr_cat(&linker_arg, optarg);
|
||||
cstr_ccat(&linker_arg, '\0');
|
||||
break;
|
||||
case TCC_OPTION_E:
|
||||
output_type = TCC_OUTPUT_PREPROCESS;
|
||||
break;
|
||||
case TCC_OPTION_MD:
|
||||
gen_deps = 1;
|
||||
break;
|
||||
case TCC_OPTION_MF:
|
||||
deps_outfile = optarg;
|
||||
break;
|
||||
case TCC_OPTION_O:
|
||||
case TCC_OPTION_pedantic:
|
||||
case TCC_OPTION_pipe:
|
||||
case TCC_OPTION_s:
|
||||
case TCC_OPTION_x:
|
||||
/* ignored */
|
||||
break;
|
||||
default:
|
||||
if (s->warn_unsupported) {
|
||||
unsupported_option:
|
||||
tcc_warning("unsupported option '%s'", r);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL != (r1 = tcc_set_linker(s, (char *) linker_arg.data, 1)))
|
||||
tcc_error("unsupported linker option '%s'", r1);
|
||||
/* fixme: these options could be different on your platform */
|
||||
if (was_pthread && output_type != TCC_OUTPUT_OBJ) {
|
||||
dynarray_add((void ***)&files, &nb_files, "-lpthread");
|
||||
nb_libraries++;
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
static int64_t getclock_us(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _timeb tb;
|
||||
_ftime(&tb);
|
||||
return (tb.time * 1000LL + tb.millitm) * 1000LL;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000LL + tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
TCCState *s;
|
||||
int nb_objfiles, ret, optind;
|
||||
int ret, optind, i, bench;
|
||||
int64_t start_time = 0;
|
||||
const char *default_file = NULL;
|
||||
const char *first_file = NULL;
|
||||
|
||||
s = tcc_new();
|
||||
s->output_type = TCC_OUTPUT_EXE;
|
||||
|
||||
output_type = TCC_OUTPUT_EXE;
|
||||
outfile = NULL;
|
||||
multiple_files = 1;
|
||||
files = NULL;
|
||||
nb_files = 0;
|
||||
nb_libraries = 0;
|
||||
reloc_output = 0;
|
||||
print_search_dirs = 0;
|
||||
m_option = NULL;
|
||||
ret = 0;
|
||||
optind = tcc_parse_args(s, argc - 1, argv + 1);
|
||||
|
||||
optind = parse_args(s, argc - 1, argv + 1);
|
||||
|
||||
#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
|
||||
if (m_option)
|
||||
exec_other_tcc(s, argv, m_option);
|
||||
#endif
|
||||
|
||||
if (print_search_dirs) {
|
||||
psd:
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
tcc_display_info(s, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->verbose)
|
||||
tcc_display_info(s, 0);
|
||||
|
||||
if (optind == 0 || nb_files == 0) {
|
||||
if (optind && s->verbose) {
|
||||
if (s->verbose == 2)
|
||||
goto psd;
|
||||
return 0;
|
||||
}
|
||||
if (optind == 0) {
|
||||
help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
nb_objfiles = nb_files - nb_libraries;
|
||||
if (s->option_m)
|
||||
exec_other_tcc(s, argv, s->option_m);
|
||||
|
||||
/* if outfile provided without other options, we output an
|
||||
executable */
|
||||
if (outfile && output_type == TCC_OUTPUT_MEMORY)
|
||||
output_type = TCC_OUTPUT_EXE;
|
||||
if (s->verbose)
|
||||
display_info(s, 0);
|
||||
|
||||
if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) {
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
display_info(s, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->verbose && optind == 1)
|
||||
return 0;
|
||||
|
||||
if (s->nb_files == 0)
|
||||
tcc_error("no input files\n");
|
||||
|
||||
/* check -c consistency : only single file handled. XXX: checks file type */
|
||||
if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
|
||||
/* accepts only a single input file */
|
||||
if (nb_objfiles != 1)
|
||||
tcc_error("cannot specify multiple files with -c");
|
||||
if (nb_libraries != 0)
|
||||
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
||||
if (s->nb_libraries != 0)
|
||||
tcc_error("cannot specify libraries with -c");
|
||||
/* accepts only a single input file */
|
||||
if (s->nb_files != 1)
|
||||
tcc_error("cannot specify multiple files with -c");
|
||||
}
|
||||
|
||||
if (output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (!outfile) {
|
||||
s->outfile = stdout;
|
||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (!s->outfile) {
|
||||
s->ppfp = stdout;
|
||||
} else {
|
||||
s->outfile = fopen(outfile, "w");
|
||||
if (!s->outfile)
|
||||
tcc_error("could not open '%s'", outfile);
|
||||
s->ppfp = fopen(s->outfile, "w");
|
||||
if (!s->ppfp)
|
||||
tcc_error("could not write '%s'", s->outfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_bench) {
|
||||
bench = s->do_bench;
|
||||
if (bench)
|
||||
start_time = getclock_us();
|
||||
}
|
||||
|
||||
tcc_set_output_type(s, output_type);
|
||||
s->reloc_output = reloc_output;
|
||||
tcc_set_output_type(s, s->output_type);
|
||||
|
||||
/* compile or add each files or library */
|
||||
for(i = 0; i < nb_files && ret == 0; i++) {
|
||||
for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
|
||||
const char *filename;
|
||||
|
||||
filename = files[i];
|
||||
filename = s->files[i];
|
||||
if (filename[0] == '-' && filename[1] == 'l') {
|
||||
if (tcc_add_library(s, filename + 2) < 0) {
|
||||
tcc_error_noabort("cannot find %s", filename);
|
||||
tcc_error_noabort("cannot find '%s'", filename);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
@ -584,16 +314,13 @@ psd:
|
||||
printf("-> %s\n", filename);
|
||||
if (tcc_add_file(s, filename) < 0)
|
||||
ret = 1;
|
||||
if (!default_file)
|
||||
default_file = filename;
|
||||
if (!first_file)
|
||||
first_file = filename;
|
||||
}
|
||||
}
|
||||
|
||||
/* free all files */
|
||||
tcc_free(files);
|
||||
|
||||
if (0 == ret) {
|
||||
if (do_bench)
|
||||
if (bench)
|
||||
tcc_print_stats(s, getclock_us() - start_time);
|
||||
|
||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
||||
@ -601,28 +328,23 @@ psd:
|
||||
ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
|
||||
#else
|
||||
tcc_error_noabort("-run is not available in a cross compiler");
|
||||
ret = 1;
|
||||
#endif
|
||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (s->outfile)
|
||||
fclose(s->outfile);
|
||||
fclose(s->ppfp);
|
||||
} else {
|
||||
if (!outfile)
|
||||
outfile = tcc_default_target(s, default_file);
|
||||
ret = !!tcc_output_file(s, outfile);
|
||||
if (!s->outfile)
|
||||
s->outfile = default_outputfile(s, first_file);
|
||||
ret = !!tcc_output_file(s, s->outfile);
|
||||
/* dump collected dependencies */
|
||||
if (gen_deps && !ret)
|
||||
tcc_gen_makedeps(s, outfile, deps_outfile);
|
||||
if (s->gen_deps && !ret)
|
||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||
}
|
||||
}
|
||||
|
||||
tcc_delete(s);
|
||||
cstr_free(&linker_arg);
|
||||
tcc_free(outfile);
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
if (do_bench) {
|
||||
printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
|
||||
}
|
||||
#endif
|
||||
if (bench)
|
||||
tcc_memstats();
|
||||
return ret;
|
||||
}
|
||||
|
306
tcc.h
306
tcc.h
@ -25,10 +25,8 @@
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CONFIG_TCCBOOT
|
||||
|
||||
#include "tccboot.h"
|
||||
#define CONFIG_TCC_STATIC
|
||||
|
||||
#else
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -70,16 +68,8 @@
|
||||
|
||||
#endif /* !CONFIG_TCCBOOT */
|
||||
|
||||
#ifndef PAGESIZE
|
||||
#define PAGESIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef SA_SIGINFO
|
||||
#define SA_SIGINFO 0x00000004u
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include "elf.h"
|
||||
@ -516,29 +506,108 @@ struct sym_attr {
|
||||
};
|
||||
|
||||
struct TCCState {
|
||||
unsigned output_type : 8;
|
||||
unsigned reloc_output : 1;
|
||||
|
||||
BufferedFile **include_stack_ptr;
|
||||
int *ifdef_stack_ptr;
|
||||
int verbose; /* if true, display some information during compilation */
|
||||
int nostdinc; /* if true, no standard headers are added */
|
||||
int nostdlib; /* if true, no standard libraries are added */
|
||||
int nocommon; /* if true, do not use common symbols for .bss data */
|
||||
int static_link; /* if true, static linking is performed */
|
||||
int rdynamic; /* if true, all symbols are exported */
|
||||
int symbolic; /* if true, resolve symbols in the current module first */
|
||||
int alacarte_link; /* if true, only link in referenced objects from archive */
|
||||
|
||||
/* include file handling */
|
||||
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
||||
char *soname; /* as specified on the command line (-soname) */
|
||||
char *rpath; /* as specified on the command line (-Wl,-rpath=) */
|
||||
|
||||
/* output type, see TCC_OUTPUT_XXX */
|
||||
int output_type;
|
||||
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
||||
int output_format;
|
||||
|
||||
/* C language options */
|
||||
int char_is_unsigned;
|
||||
int leading_underscore;
|
||||
|
||||
/* warning switches */
|
||||
int warn_write_strings;
|
||||
int warn_unsupported;
|
||||
int warn_error;
|
||||
int warn_none;
|
||||
int warn_implicit_function_declaration;
|
||||
|
||||
/* compile with debug symbol (and use them if error during execution) */
|
||||
int do_debug;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* compile with built-in memory and bounds checker */
|
||||
int do_bounds_check;
|
||||
#endif
|
||||
|
||||
addr_t text_addr; /* address of text section */
|
||||
int has_text_addr;
|
||||
|
||||
unsigned long section_align; /* section alignment */
|
||||
|
||||
char *init_symbol; /* symbols to call at load-time (not used currently) */
|
||||
char *fini_symbol; /* symbols to call at unload-time (not used currently) */
|
||||
|
||||
#ifdef TCC_TARGET_I386
|
||||
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
|
||||
#endif
|
||||
|
||||
/* array of all loaded dlls (including those referenced by loaded dlls) */
|
||||
DLLReference **loaded_dlls;
|
||||
int nb_loaded_dlls;
|
||||
|
||||
/* include paths */
|
||||
char **include_paths;
|
||||
int nb_include_paths;
|
||||
|
||||
char **sysinclude_paths;
|
||||
int nb_sysinclude_paths;
|
||||
CachedInclude **cached_includes;
|
||||
int nb_cached_includes;
|
||||
|
||||
/* library paths */
|
||||
char **library_paths;
|
||||
int nb_library_paths;
|
||||
|
||||
/* crt?.o object path */
|
||||
char **crt_paths;
|
||||
int nb_crt_paths;
|
||||
|
||||
/* array of all loaded dlls (including those referenced by loaded
|
||||
dlls) */
|
||||
DLLReference **loaded_dlls;
|
||||
int nb_loaded_dlls;
|
||||
/* error handling */
|
||||
void *error_opaque;
|
||||
void (*error_func)(void *opaque, const char *msg);
|
||||
int error_set_jmp_enabled;
|
||||
jmp_buf error_jmp_buf;
|
||||
int nb_errors;
|
||||
|
||||
/* output file for preprocessing (-E) */
|
||||
FILE *ppfp;
|
||||
|
||||
/* for -MD/-MF: collected dependencies for this compilation */
|
||||
char **target_deps;
|
||||
int nb_target_deps;
|
||||
|
||||
/* compilation */
|
||||
BufferedFile *include_stack[INCLUDE_STACK_SIZE];
|
||||
BufferedFile **include_stack_ptr;
|
||||
|
||||
int ifdef_stack[IFDEF_STACK_SIZE];
|
||||
int *ifdef_stack_ptr;
|
||||
|
||||
/* included files enclosed with #ifndef MACRO */
|
||||
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
|
||||
CachedInclude **cached_includes;
|
||||
int nb_cached_includes;
|
||||
|
||||
/* #pragma pack stack */
|
||||
int pack_stack[PACK_STACK_SIZE];
|
||||
int *pack_stack_ptr;
|
||||
|
||||
/* inline functions are stored as token lists and compiled last
|
||||
only if referenced */
|
||||
struct InlineFunc **inline_fns;
|
||||
int nb_inline_fns;
|
||||
|
||||
/* sections */
|
||||
Section **sections;
|
||||
@ -559,137 +628,54 @@ struct TCCState {
|
||||
Section *dynsymtab_section;
|
||||
/* exported dynamic symbol section */
|
||||
Section *dynsym;
|
||||
|
||||
/* copy of the gobal symtab_section variable */
|
||||
Section *symtab;
|
||||
|
||||
int nostdinc; /* if true, no standard headers are added */
|
||||
int nostdlib; /* if true, no standard libraries are added */
|
||||
int nocommon; /* if true, do not use common symbols for .bss data */
|
||||
|
||||
/* if true, static linking is performed */
|
||||
int static_link;
|
||||
|
||||
/* soname as specified on the command line (-soname) */
|
||||
const char *soname;
|
||||
/* rpath as specified on the command line (-Wl,-rpath=) */
|
||||
const char *rpath;
|
||||
|
||||
/* if true, all symbols are exported */
|
||||
int rdynamic;
|
||||
|
||||
/* if true, resolve symbols in the current module first (-Wl,Bsymbolic) */
|
||||
int symbolic;
|
||||
|
||||
/* if true, only link in referenced objects from archive */
|
||||
int alacarte_link;
|
||||
|
||||
/* address of text section */
|
||||
addr_t text_addr;
|
||||
int has_text_addr;
|
||||
|
||||
/* symbols to call at load-time / unload-time */
|
||||
const char *init_symbol;
|
||||
const char *fini_symbol;
|
||||
|
||||
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
||||
int output_format;
|
||||
|
||||
/* C language options */
|
||||
int char_is_unsigned;
|
||||
int leading_underscore;
|
||||
|
||||
/* warning switches */
|
||||
int warn_write_strings;
|
||||
int warn_unsupported;
|
||||
int warn_error;
|
||||
int warn_none;
|
||||
int warn_implicit_function_declaration;
|
||||
|
||||
/* display some information during compilation */
|
||||
int verbose;
|
||||
/* compile with debug symbol (and use them if error during execution) */
|
||||
int do_debug;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* compile with built-in memory and bounds checker */
|
||||
int do_bounds_check;
|
||||
#endif
|
||||
/* give the path of the tcc libraries */
|
||||
char *tcc_lib_path;
|
||||
|
||||
/* error handling */
|
||||
void *error_opaque;
|
||||
void (*error_func)(void *opaque, const char *msg);
|
||||
int error_set_jmp_enabled;
|
||||
jmp_buf error_jmp_buf;
|
||||
int nb_errors;
|
||||
|
||||
/* tiny assembler state */
|
||||
Sym *asm_labels;
|
||||
|
||||
/* see include_stack_ptr */
|
||||
BufferedFile *include_stack[INCLUDE_STACK_SIZE];
|
||||
|
||||
/* see ifdef_stack_ptr */
|
||||
int ifdef_stack[IFDEF_STACK_SIZE];
|
||||
|
||||
/* see cached_includes */
|
||||
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
|
||||
|
||||
/* pack stack */
|
||||
int pack_stack[PACK_STACK_SIZE];
|
||||
int *pack_stack_ptr;
|
||||
|
||||
/* output file for preprocessing */
|
||||
FILE *outfile;
|
||||
|
||||
/* automatically collected dependencies for this compilation */
|
||||
char **target_deps;
|
||||
int nb_target_deps;
|
||||
|
||||
/* for tcc_relocate */
|
||||
int runtime_added;
|
||||
void *runtime_mem;
|
||||
#ifdef HAVE_SELINUX
|
||||
void *write_mem;
|
||||
unsigned long mem_size;
|
||||
#endif
|
||||
|
||||
struct InlineFunc **inline_fns;
|
||||
int nb_inline_fns;
|
||||
|
||||
#ifdef TCC_TARGET_I386
|
||||
int seg_size;
|
||||
#endif
|
||||
|
||||
/* section alignment */
|
||||
unsigned long section_align;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
/* PE info */
|
||||
int pe_subsystem;
|
||||
unsigned long pe_file_align;
|
||||
unsigned long pe_stack_size;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
unsigned pe_file_align;
|
||||
unsigned pe_stack_size;
|
||||
# ifdef TCC_TARGET_X86_64
|
||||
Section *uw_pdata;
|
||||
int uw_sym;
|
||||
unsigned uw_offs;
|
||||
#endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE \
|
||||
&& (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
|
||||
#ifdef TCC_IS_NATIVE
|
||||
/* for tcc_relocate */
|
||||
void *runtime_mem;
|
||||
# ifdef HAVE_SELINUX
|
||||
void *write_mem;
|
||||
unsigned long mem_size;
|
||||
# endif
|
||||
# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
|
||||
/* write PLT and GOT here */
|
||||
char *runtime_plt_and_got;
|
||||
unsigned int runtime_plt_and_got_offset;
|
||||
unsigned runtime_plt_and_got_offset;
|
||||
# define TCC_HAS_RUNTIME_PLTGOT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* used by main and tcc_parse_args only */
|
||||
char **files; /* files seen on command line */
|
||||
int nb_files; /* number thereof */
|
||||
int nb_libraries; /* number of libs thereof */
|
||||
char *outfile; /* output filename */
|
||||
char *option_m; /* only -m32/-m64 handled */
|
||||
int print_search_dirs; /* option */
|
||||
int option_r; /* option -r */
|
||||
int do_bench; /* option -bench */
|
||||
int gen_deps; /* option -MD */
|
||||
char *deps_outfile; /* option -MF */
|
||||
};
|
||||
|
||||
/* The current value can be: */
|
||||
#define VT_VALMASK 0x003f
|
||||
#define VT_CONST 0x0030 /* constant in vc
|
||||
(must be first non register value) */
|
||||
#define VT_VALMASK 0x003f /* mask for value location, register or: */
|
||||
#define VT_CONST 0x0030 /* constant in vc (must be first non register value) */
|
||||
#define VT_LLOCAL 0x0031 /* lvalue, offset on stack */
|
||||
#define VT_LOCAL 0x0032 /* offset on stack */
|
||||
#define VT_CMP 0x0033 /* the value is stored in processor flags (in vc) */
|
||||
@ -710,6 +696,7 @@ struct TCCState {
|
||||
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
|
||||
|
||||
/* types */
|
||||
#define VT_BTYPE 0x000f /* mask for basic type */
|
||||
#define VT_INT 0 /* integer type */
|
||||
#define VT_BYTE 1 /* signed byte type */
|
||||
#define VT_SHORT 2 /* short type */
|
||||
@ -725,14 +712,13 @@ struct TCCState {
|
||||
#define VT_LLONG 12 /* 64 bit integer */
|
||||
#define VT_LONG 13 /* long integer (NEVER USED as type, only
|
||||
during parsing) */
|
||||
#define VT_BTYPE 0x000f /* mask for basic type */
|
||||
#define VT_UNSIGNED 0x0010 /* unsigned type */
|
||||
#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
|
||||
#define VT_VLA 0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
||||
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
||||
#define VT_CONSTANT 0x0800 /* const modifier */
|
||||
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
||||
#define VT_SIGNED 0x2000 /* signed type */
|
||||
#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
||||
|
||||
/* storage */
|
||||
#define VT_EXTERN 0x00000080 /* extern definition */
|
||||
@ -741,9 +727,9 @@ struct TCCState {
|
||||
#define VT_INLINE 0x00000400 /* inline definition */
|
||||
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
|
||||
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
|
||||
#define VT_WEAK 0x00010000 /* win32: data exported from dll */
|
||||
#define VT_WEAK 0x00010000 /* weak symbol */
|
||||
|
||||
#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values */
|
||||
#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */
|
||||
|
||||
/* type mask (except storage) */
|
||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK)
|
||||
@ -999,6 +985,11 @@ ST_DATA int tcc_ext;
|
||||
/* XXX: get rid of this ASAP */
|
||||
ST_DATA struct TCCState *tcc_state;
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
ST_DATA int mem_cur_size;
|
||||
ST_DATA int mem_max_size;
|
||||
#endif
|
||||
|
||||
#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
|
||||
#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
|
||||
#define AFF_PREPROCESS 0x0004 /* preprocess file */
|
||||
@ -1020,19 +1011,19 @@ PUB_FUNC char *tcc_strdup(const char *str);
|
||||
#undef strdup
|
||||
#define strdup(s) use_tcc_strdup(s)
|
||||
PUB_FUNC void tcc_memstats(void);
|
||||
PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data);
|
||||
PUB_FUNC void dynarray_reset(void *pp, int *n);
|
||||
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
|
||||
PUB_FUNC void tcc_error(const char *fmt, ...);
|
||||
PUB_FUNC void tcc_warning(const char *fmt, ...);
|
||||
|
||||
/* other utilities */
|
||||
PUB_FUNC void cstr_ccat(CString *cstr, int ch);
|
||||
PUB_FUNC void cstr_cat(CString *cstr, const char *str);
|
||||
PUB_FUNC void cstr_wccat(CString *cstr, int ch);
|
||||
PUB_FUNC void cstr_new(CString *cstr);
|
||||
PUB_FUNC void cstr_free(CString *cstr);
|
||||
PUB_FUNC void cstr_reset(CString *cstr);
|
||||
ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data);
|
||||
ST_FUNC void dynarray_reset(void *pp, int *n);
|
||||
ST_FUNC void cstr_ccat(CString *cstr, int ch);
|
||||
ST_FUNC void cstr_cat(CString *cstr, const char *str);
|
||||
ST_FUNC void cstr_wccat(CString *cstr, int ch);
|
||||
ST_FUNC void cstr_new(CString *cstr);
|
||||
ST_FUNC void cstr_free(CString *cstr);
|
||||
ST_FUNC void cstr_reset(CString *cstr);
|
||||
|
||||
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
|
||||
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
|
||||
@ -1059,15 +1050,10 @@ ST_FUNC void tcc_close(void);
|
||||
|
||||
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
|
||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
||||
#ifndef TCC_TARGET_PE
|
||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
||||
#endif
|
||||
|
||||
PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value);
|
||||
PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time);
|
||||
PUB_FUNC char *tcc_default_target(TCCState *s, const char *default_file);
|
||||
PUB_FUNC void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename);
|
||||
PUB_FUNC void tcc_display_info(TCCState *s, int what);
|
||||
PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* ------------ tccpp.c ------------ */
|
||||
|
||||
@ -1208,6 +1194,10 @@ ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsign
|
||||
|
||||
/* ------------ tccelf.c ------------ */
|
||||
|
||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||
|
||||
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
|
||||
|
||||
typedef struct {
|
||||
@ -1259,11 +1249,11 @@ ST_FUNC int handle_eob(void);
|
||||
|
||||
/* ------------ xxx-gen.c ------------ */
|
||||
|
||||
ST_DATA const int reg_classes[NB_REGS
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
+ 7
|
||||
ST_DATA const int reg_classes[NB_REGS+7];
|
||||
#else
|
||||
ST_DATA const int reg_classes[NB_REGS];
|
||||
#endif
|
||||
];
|
||||
|
||||
ST_FUNC void gsym_addr(int t, int a);
|
||||
ST_FUNC void gsym(int t);
|
||||
@ -1329,7 +1319,6 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
|
||||
/* ------------ tccasm.c ------------ */
|
||||
ST_FUNC void asm_instr(void);
|
||||
ST_FUNC void asm_global_instr(void);
|
||||
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
||||
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
|
||||
@ -1343,14 +1332,13 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
|
||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
|
||||
#endif
|
||||
|
||||
/* ------------ tccpe.c -------------- */
|
||||
#ifdef TCC_TARGET_PE
|
||||
ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd);
|
||||
ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
|
||||
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value);
|
||||
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
|
||||
/* tiny_impdef.c */
|
||||
ST_FUNC char *get_export_names(FILE *fp);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
|
||||
#endif
|
||||
@ -1366,7 +1354,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
|
||||
/* dummy function for profiling */
|
||||
ST_FUNC void *dlopen(const char *filename, int flag);
|
||||
ST_FUNC void dlclose(void *p);
|
||||
//ST_FUNC const char *dlerror(void);
|
||||
ST_FUNC const char *dlerror(void);
|
||||
ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
|
||||
#elif !defined _WIN32
|
||||
ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
|
||||
@ -1376,7 +1364,7 @@ ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
|
||||
ST_DATA int rt_num_callers;
|
||||
ST_DATA const char **rt_bound_error_msg;
|
||||
ST_DATA void *rt_prog_main;
|
||||
PUB_FUNC void tcc_set_num_callers(int n);
|
||||
ST_FUNC void tcc_set_num_callers(int n);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
2
tccelf.c
2
tccelf.c
@ -240,7 +240,7 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
|
||||
} else if (s == tcc_state->dynsymtab_section) {
|
||||
/* we accept that two DLL define the same symbol */
|
||||
} else {
|
||||
#if 1
|
||||
#if 0
|
||||
printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
|
||||
sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
|
||||
#endif
|
||||
|
54
tccpe.c
54
tccpe.c
@ -1505,10 +1505,10 @@ static int add_dllref(TCCState *s1, const char *dllname)
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||
static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
||||
{
|
||||
fseek(fp, offset, 0);
|
||||
return len == fread(buffer, 1, len, fp);
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
return len == read(fd, buffer, len);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
@ -1516,7 +1516,7 @@ static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||
* as generated by 'windres.exe -O coff ...'.
|
||||
*/
|
||||
|
||||
static int pe_load_res(TCCState *s1, FILE *fp)
|
||||
static int pe_load_res(TCCState *s1, int fd)
|
||||
{
|
||||
struct pe_rsrc_header hdr;
|
||||
Section *rsrc_section;
|
||||
@ -1524,7 +1524,7 @@ static int pe_load_res(TCCState *s1, FILE *fp)
|
||||
BYTE *ptr;
|
||||
unsigned offs;
|
||||
|
||||
if (!read_mem(fp, 0, &hdr, sizeof hdr))
|
||||
if (!read_mem(fd, 0, &hdr, sizeof hdr))
|
||||
goto quit;
|
||||
|
||||
if (hdr.filehdr.Machine != 0x014C
|
||||
@ -1535,13 +1535,13 @@ static int pe_load_res(TCCState *s1, FILE *fp)
|
||||
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
|
||||
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
|
||||
offs = hdr.sectionhdr.PointerToRawData;
|
||||
if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData))
|
||||
if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
|
||||
goto quit;
|
||||
offs = hdr.sectionhdr.PointerToRelocations;
|
||||
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
|
||||
{
|
||||
struct pe_rsrc_reloc rel;
|
||||
if (!read_mem(fp, offs, &rel, sizeof rel))
|
||||
if (!read_mem(fd, offs, &rel, sizeof rel))
|
||||
goto quit;
|
||||
// printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
|
||||
if (rel.type != 7) /* DIR32NB */
|
||||
@ -1571,22 +1571,26 @@ static char *trimback(char *a, char *e)
|
||||
return a;
|
||||
}
|
||||
|
||||
static char *get_line(char *line, int size, FILE *fp)
|
||||
static char *get_line(char *line, int size, int fd)
|
||||
{
|
||||
if (NULL == fgets(line, size, fp))
|
||||
int n;
|
||||
for (n = 0; n < size - 1; )
|
||||
if (read(fd, line + n, 1) < 1 || line[n++] == '\n')
|
||||
break;
|
||||
if (0 == n)
|
||||
return NULL;
|
||||
trimback(line, strchr(line, 0));
|
||||
trimback(line, line + n);
|
||||
return trimfront(line);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
static int pe_load_def(TCCState *s1, FILE *fp)
|
||||
static int pe_load_def(TCCState *s1, int fd)
|
||||
{
|
||||
int state = 0, ret = -1, dllindex = 0;
|
||||
char line[400], dllname[80], *p;
|
||||
|
||||
for (;;) {
|
||||
p = get_line(line, sizeof line, fp);
|
||||
p = get_line(line, sizeof line, fd);
|
||||
if (NULL == p)
|
||||
break;
|
||||
if (0 == *p || ';' == *p)
|
||||
@ -1623,11 +1627,11 @@ quit:
|
||||
#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
||||
#include "win32/tools/tiny_impdef.c"
|
||||
|
||||
static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
|
||||
static int pe_load_dll(TCCState *s1, const char *dllname, int fd)
|
||||
{
|
||||
char *p, *q;
|
||||
int index;
|
||||
p = get_export_names(fp);
|
||||
p = get_export_names(fd);
|
||||
if (!p)
|
||||
return -1;
|
||||
index = add_dllref(s1, dllname);
|
||||
@ -1640,18 +1644,14 @@ static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
|
||||
/* ------------------------------------------------------------- */
|
||||
ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
|
||||
{
|
||||
FILE *fp = fdopen(dup(fd), "rb");
|
||||
int ret = -1;
|
||||
char buf[10];
|
||||
if (fp) {
|
||||
if (0 == strcmp(tcc_fileextension(filename), ".def"))
|
||||
ret = pe_load_def(s1, fp);
|
||||
else if (pe_load_res(s1, fp) == 0)
|
||||
ret = pe_load_def(s1, fd);
|
||||
else if (pe_load_res(s1, fd) == 0)
|
||||
ret = 0;
|
||||
else if (read_mem(fp, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
|
||||
ret = pe_load_dll(s1, tcc_basename(filename), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
else if (read_mem(fd, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
|
||||
ret = pe_load_dll(s1, tcc_basename(filename), fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1723,7 +1723,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
#define PE_STDSYM(n,s) "_" n s
|
||||
#endif
|
||||
|
||||
static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
|
||||
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||
{
|
||||
const char *start_symbol;
|
||||
ADDR3264 addr = 0;
|
||||
@ -1762,15 +1762,17 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
|
||||
|
||||
if (0 == s1->nostdlib) {
|
||||
static const char *libs[] = {
|
||||
"tcc1", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||
"libtcc1.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||
};
|
||||
const char **pp, *p;
|
||||
for (pp = libs; 0 != (p = *pp); ++pp) {
|
||||
if (0 == *p) {
|
||||
if (PE_DLL != pe_type && PE_GUI != pe_type)
|
||||
break;
|
||||
} else if (tcc_add_library(s1, p) < 0)
|
||||
} else if (pp == libs ? tcc_add_dll(s1, p, 0) : tcc_add_library(s1, p)) {
|
||||
tcc_error_noabort("cannot find library: %s", p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1802,7 +1804,7 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
|
||||
pe.s1 = s1;
|
||||
|
||||
tcc_add_bcheck(s1);
|
||||
pe_add_runtime_ex(s1, &pe);
|
||||
pe_add_runtime(s1, &pe);
|
||||
relocate_common_syms(); /* assign bss adresses */
|
||||
tcc_add_linker_symbols(s1);
|
||||
|
||||
|
18
tccpp.c
18
tccpp.c
@ -118,7 +118,7 @@ static void cstr_realloc(CString *cstr, int new_size)
|
||||
}
|
||||
|
||||
/* add a byte */
|
||||
PUB_FUNC void cstr_ccat(CString *cstr, int ch)
|
||||
ST_FUNC void cstr_ccat(CString *cstr, int ch)
|
||||
{
|
||||
int size;
|
||||
size = cstr->size + 1;
|
||||
@ -128,7 +128,7 @@ PUB_FUNC void cstr_ccat(CString *cstr, int ch)
|
||||
cstr->size = size;
|
||||
}
|
||||
|
||||
PUB_FUNC void cstr_cat(CString *cstr, const char *str)
|
||||
ST_FUNC void cstr_cat(CString *cstr, const char *str)
|
||||
{
|
||||
int c;
|
||||
for(;;) {
|
||||
@ -141,7 +141,7 @@ PUB_FUNC void cstr_cat(CString *cstr, const char *str)
|
||||
}
|
||||
|
||||
/* add a wide char */
|
||||
PUB_FUNC void cstr_wccat(CString *cstr, int ch)
|
||||
ST_FUNC void cstr_wccat(CString *cstr, int ch)
|
||||
{
|
||||
int size;
|
||||
size = cstr->size + sizeof(nwchar_t);
|
||||
@ -151,20 +151,20 @@ PUB_FUNC void cstr_wccat(CString *cstr, int ch)
|
||||
cstr->size = size;
|
||||
}
|
||||
|
||||
PUB_FUNC void cstr_new(CString *cstr)
|
||||
ST_FUNC void cstr_new(CString *cstr)
|
||||
{
|
||||
memset(cstr, 0, sizeof(CString));
|
||||
}
|
||||
|
||||
/* free string and reset it to NULL */
|
||||
PUB_FUNC void cstr_free(CString *cstr)
|
||||
ST_FUNC void cstr_free(CString *cstr)
|
||||
{
|
||||
tcc_free(cstr->data_allocated);
|
||||
cstr_new(cstr);
|
||||
}
|
||||
|
||||
/* reset string to empty */
|
||||
PUB_FUNC void cstr_reset(CString *cstr)
|
||||
ST_FUNC void cstr_reset(CString *cstr)
|
||||
{
|
||||
cstr->size = 0;
|
||||
}
|
||||
@ -3112,17 +3112,17 @@ print_line:
|
||||
: ""
|
||||
;
|
||||
iptr = iptr_new;
|
||||
fprintf(s1->outfile, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
|
||||
fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
|
||||
} else {
|
||||
while (d)
|
||||
fputs("\n", s1->outfile), --d;
|
||||
fputs("\n", s1->ppfp), --d;
|
||||
}
|
||||
line_ref = (file_ref = file)->line_num;
|
||||
token_seen = tok != TOK_LINEFEED;
|
||||
if (!token_seen)
|
||||
continue;
|
||||
}
|
||||
fputs(get_tok_str(tok, &tokc), s1->outfile);
|
||||
fputs(get_tok_str(tok, &tokc), s1->ppfp);
|
||||
}
|
||||
free_defines(define_start);
|
||||
return 0;
|
||||
|
58
tccrun.c
58
tccrun.c
@ -54,33 +54,36 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
||||
if (TCC_RELOCATE_AUTO != ptr)
|
||||
return tcc_relocate_ex(s1, ptr);
|
||||
|
||||
ret = tcc_relocate_ex(s1, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
/* Use mmap instead of malloc for Selinux
|
||||
Ref http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
|
||||
{ /* Use mmap instead of malloc for Selinux. Ref:
|
||||
http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
|
||||
|
||||
char tmpfname[] = "/tmp/.tccrunXXXXXX";
|
||||
int fd = mkstemp (tmpfname);
|
||||
if ((ret= tcc_relocate_ex(s1,NULL)) < 0)return -1;
|
||||
s1->mem_size=ret;
|
||||
unlink (tmpfname); ftruncate (fd, s1->mem_size);
|
||||
|
||||
s1->mem_size = ret;
|
||||
unlink (tmpfname);
|
||||
ftruncate (fd, s1->mem_size);
|
||||
|
||||
s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
if(s1->write_mem == MAP_FAILED){
|
||||
if (s1->write_mem == MAP_FAILED)
|
||||
tcc_error("/tmp not writeable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
|
||||
MAP_SHARED, fd, 0);
|
||||
if(s1->runtime_mem == MAP_FAILED){
|
||||
if (s1->runtime_mem == MAP_FAILED)
|
||||
tcc_error("/tmp not executable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = tcc_relocate_ex(s1, s1->write_mem);
|
||||
}
|
||||
#else
|
||||
ret = tcc_relocate_ex(s1, NULL);
|
||||
if (-1 != ret) {
|
||||
s1->runtime_mem = tcc_malloc(ret);
|
||||
ret = tcc_relocate_ex(s1, s1->runtime_mem);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@ -130,8 +133,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
||||
addr_t mem;
|
||||
int i;
|
||||
|
||||
if (0 == s1->runtime_added) {
|
||||
s1->runtime_added = 1;
|
||||
if (NULL == ptr) {
|
||||
s1->nb_errors = 0;
|
||||
#ifdef TCC_TARGET_PE
|
||||
pe_output_file(s1, NULL);
|
||||
@ -215,6 +217,9 @@ static void set_pages_executable(void *ptr, unsigned long length)
|
||||
unsigned long old_protect;
|
||||
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
#else
|
||||
#ifndef PAGESIZE
|
||||
# define PAGESIZE 4096
|
||||
#endif
|
||||
addr_t start, end;
|
||||
start = (addr_t)ptr & ~(PAGESIZE - 1);
|
||||
end = (addr_t)ptr + length;
|
||||
@ -226,7 +231,7 @@ static void set_pages_executable(void *ptr, unsigned long length)
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
|
||||
PUB_FUNC void tcc_set_num_callers(int n)
|
||||
ST_FUNC void tcc_set_num_callers(int n)
|
||||
{
|
||||
rt_num_callers = n;
|
||||
}
|
||||
@ -436,6 +441,10 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
||||
exit(255);
|
||||
}
|
||||
|
||||
#ifndef SA_SIGINFO
|
||||
# define SA_SIGINFO 0x00000004u
|
||||
#endif
|
||||
|
||||
/* Generate a stack backtrace when a CPU exception occurs. */
|
||||
static void set_exception_handler(void)
|
||||
{
|
||||
@ -663,14 +672,8 @@ static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
|
||||
#endif /* _WIN32 */
|
||||
#endif /* CONFIG_TCC_BACKTRACE */
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_TCC_STATIC
|
||||
|
||||
#define RTLD_LAZY 0x001
|
||||
#define RTLD_NOW 0x002
|
||||
#define RTLD_GLOBAL 0x100
|
||||
#define RTLD_DEFAULT NULL
|
||||
|
||||
/* dummy function for profiling */
|
||||
ST_FUNC void *dlopen(const char *filename, int flag)
|
||||
{
|
||||
@ -680,26 +683,27 @@ ST_FUNC void *dlopen(const char *filename, int flag)
|
||||
ST_FUNC void dlclose(void *p)
|
||||
{
|
||||
}
|
||||
/*
|
||||
const char *dlerror(void)
|
||||
|
||||
ST_FUNC const char *dlerror(void)
|
||||
{
|
||||
return "error";
|
||||
}
|
||||
*/
|
||||
|
||||
typedef struct TCCSyms {
|
||||
char *str;
|
||||
void *ptr;
|
||||
} TCCSyms;
|
||||
|
||||
#define TCCSYM(a) { #a, &a, },
|
||||
|
||||
/* add the symbol you want here if no dynamic linking is done */
|
||||
static TCCSyms tcc_syms[] = {
|
||||
#if !defined(CONFIG_TCCBOOT)
|
||||
#define TCCSYM(a) { #a, &a, },
|
||||
TCCSYM(printf)
|
||||
TCCSYM(fprintf)
|
||||
TCCSYM(fopen)
|
||||
TCCSYM(fclose)
|
||||
#undef TCCSYM
|
||||
#endif
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
@ -6,13 +6,11 @@
|
||||
under MS-Windows. See tcc-doc.html to have all the features.
|
||||
|
||||
|
||||
|
||||
Installation from the binary ZIP package:
|
||||
-----------------------------------------
|
||||
Unzip the package to a directory of your choice.
|
||||
|
||||
|
||||
|
||||
Set the system PATH:
|
||||
--------------------
|
||||
To be able to invoke the compiler from everywhere on your computer by
|
||||
@ -20,7 +18,6 @@
|
||||
system PATH.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
---------
|
||||
Open a console window (DOS box) and 'cd' to the examples directory.
|
||||
@ -39,9 +36,23 @@
|
||||
tiny_impdef dll.dll (optional)
|
||||
tcc hello_dll.c dll.def
|
||||
|
||||
For the 'libtcc_test' example type
|
||||
|
||||
tcc examples/libtcc_test.c -I libtcc -L libtcc -ltcc
|
||||
Using libtcc as JIT compiler in your program
|
||||
--------------------------------------------
|
||||
Check out the 'libtcc_test' example:
|
||||
|
||||
- Running it from source:
|
||||
tcc -I libtcc libtcc/libtcc.def -run examples/libtcc_test.c
|
||||
|
||||
- Compiling with TCC:
|
||||
tcc examples/libtcc_test.c -I libtcc libtcc/libtcc.def
|
||||
|
||||
- Compiling with MinGW:
|
||||
gcc examples/libtcc_test.c -I libtcc libtcc.dll
|
||||
|
||||
- Compiling with MSVC:
|
||||
lib /def:libtcc\libtcc.def /out:libtcc.lib
|
||||
cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
|
||||
|
||||
|
||||
Import Definition Files:
|
||||
@ -58,7 +69,6 @@
|
||||
the TCC commandline to link a program that uses opengl32.dll.
|
||||
|
||||
|
||||
|
||||
Header Files:
|
||||
-------------
|
||||
The system header files (except _mingw.h) are from the MinGW
|
||||
@ -71,7 +81,6 @@
|
||||
into your "tcc/include/winapi" directory.
|
||||
|
||||
|
||||
|
||||
Resource Files:
|
||||
---------------
|
||||
TCC can link windows resources in coff format as generated by MinGW's
|
||||
@ -81,7 +90,6 @@
|
||||
tcc app.c appres.o -o app.exe
|
||||
|
||||
|
||||
|
||||
Tiny Libmaker:
|
||||
--------------
|
||||
The included tiny_libmaker tool by Timovj Lahde can be used as
|
||||
@ -90,7 +98,6 @@
|
||||
tiny_libmaker [rcs] library objectfiles ...
|
||||
|
||||
|
||||
|
||||
Compilation from source:
|
||||
------------------------
|
||||
* You can use the MinGW and MSYS tools available at
|
||||
@ -99,22 +106,20 @@
|
||||
|
||||
Untar the TCC archive and type in the MSYS shell:
|
||||
|
||||
./configure
|
||||
./configure [--prefix installpath]
|
||||
make
|
||||
make install
|
||||
|
||||
The default install location is c:\Program Files\tcc
|
||||
|
||||
|
||||
* Alternatively you can compile TCC with just GCC from MinGW using
|
||||
|
||||
win32\build-tcc.bat
|
||||
build-tcc.bat (from the win32 directory)
|
||||
|
||||
To install, copy the entire contents of the win32 directory to
|
||||
where you want.
|
||||
|
||||
|
||||
|
||||
Limitations:
|
||||
------------
|
||||
- On the object file level, currently TCC supports only the ELF format,
|
||||
@ -128,7 +133,6 @@
|
||||
- Bounds checking (option -b) is not supported on 64-bit OS.
|
||||
|
||||
|
||||
|
||||
Documentation and License:
|
||||
--------------------------
|
||||
TCC is distributed under the GNU Lesser General Public License. (See
|
||||
@ -139,7 +143,6 @@
|
||||
http://fabrice.bellard.free.fr/tcc/
|
||||
|
||||
|
||||
|
||||
WinAPI Help and 3rd-party tools:
|
||||
--------------------------------
|
||||
The Windows API documentation (Win95) in a single .hlp file is
|
||||
@ -150,5 +153,4 @@
|
||||
"ResEd", available at the RadASM website.
|
||||
|
||||
|
||||
|
||||
--- grischka
|
||||
|
@ -25,9 +25,10 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
|
||||
char *get_export_names(FILE *fp);
|
||||
char *get_export_names(int fd);
|
||||
#define tcc_free free
|
||||
#define tcc_realloc realloc
|
||||
|
||||
@ -114,7 +115,7 @@ usage:
|
||||
if (v)
|
||||
printf("--> %s\n", file);
|
||||
|
||||
p = get_export_names(fp);
|
||||
p = get_export_names(fileno(fp));
|
||||
if (NULL == p) {
|
||||
fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
|
||||
goto the_end;
|
||||
@ -149,18 +150,18 @@ the_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
|
||||
int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
|
||||
int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
||||
{
|
||||
fseek(fp, offset, 0);
|
||||
return len == fread(buffer, 1, len, fp);
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
return len == read(fd, buffer, len);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
#endif
|
||||
|
||||
char *get_export_names(FILE *fp)
|
||||
char *get_export_names(int fd)
|
||||
{
|
||||
int l, i, n, n0;
|
||||
char *p;
|
||||
@ -182,20 +183,20 @@ char *get_export_names(FILE *fp)
|
||||
n = n0 = 0;
|
||||
p = NULL;
|
||||
|
||||
if (!read_mem(fp, 0, &dh, sizeof dh))
|
||||
if (!read_mem(fd, 0, &dh, sizeof dh))
|
||||
goto the_end;
|
||||
if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig))
|
||||
if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
|
||||
goto the_end;
|
||||
if (sig != 0x00004550)
|
||||
goto the_end;
|
||||
pef_hdroffset = dh.e_lfanew + sizeof sig;
|
||||
if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih))
|
||||
if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
|
||||
goto the_end;
|
||||
if (MACHINE != ih.Machine)
|
||||
goto the_end;
|
||||
opt_hdroffset = pef_hdroffset + sizeof ih;
|
||||
sec_hdroffset = opt_hdroffset + sizeof oh;
|
||||
if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh))
|
||||
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
|
||||
goto the_end;
|
||||
|
||||
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
|
||||
@ -204,7 +205,7 @@ char *get_export_names(FILE *fp)
|
||||
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
//printf("addr: %08x\n", addr);
|
||||
for (i = 0; i < ih.NumberOfSections; ++i) {
|
||||
if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
|
||||
if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
|
||||
goto the_end;
|
||||
//printf("vaddr: %08x\n", ish.VirtualAddress);
|
||||
if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
|
||||
@ -214,18 +215,18 @@ char *get_export_names(FILE *fp)
|
||||
|
||||
found:
|
||||
ref = ish.VirtualAddress - ish.PointerToRawData;
|
||||
if (!read_mem(fp, addr - ref, &ied, sizeof ied))
|
||||
if (!read_mem(fd, addr - ref, &ied, sizeof ied))
|
||||
goto the_end;
|
||||
|
||||
namep = ied.AddressOfNames - ref;
|
||||
for (i = 0; i < ied.NumberOfNames; ++i) {
|
||||
if (!read_mem(fp, namep, &ptr, sizeof ptr))
|
||||
if (!read_mem(fd, namep, &ptr, sizeof ptr))
|
||||
goto the_end;
|
||||
namep += sizeof ptr;
|
||||
for (l = 0;;) {
|
||||
if (n+1 >= n0)
|
||||
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
|
||||
if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) {
|
||||
if (!read_mem(fd, ptr - ref + l, p + n, 1) || ++l >= 80) {
|
||||
tcc_free(p), p = NULL;
|
||||
goto the_end;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ int main(int argc, char **argv)
|
||||
ElfW(Sym) *sym;
|
||||
int i, fsize, iarg;
|
||||
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
||||
int symtabsize = 0, strtabsize = 0;
|
||||
int symtabsize = 0;//, strtabsize = 0;
|
||||
char *anames = NULL;
|
||||
int *afpos = NULL;
|
||||
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
||||
@ -171,7 +171,7 @@ int main(int argc, char **argv)
|
||||
if (!strcmp(shstr + shdr->sh_name, ".strtab"))
|
||||
{
|
||||
strtab = (char *)(buf + shdr->sh_offset);
|
||||
strtabsize = shdr->sh_size;
|
||||
//strtabsize = shdr->sh_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user