Switch to newer tccpe.c (includes support for resources)

tcc-xref
grischka 2007-12-19 17:36:42 +00:00
parent adb1456472
commit 5342b32eef
6 changed files with 1354 additions and 999 deletions

View File

@ -1,5 +1,6 @@
version 0.9.24:
- Switch to newer tccpe.c (includes support for resources)
- Handle backslashes within #include, #error, #warning
- Import changesets (part 4) 428,457,460,467: defines for openbsd etc.
- Use _WIN32 for a windows hosted tcc and define it for the PE target,

View File

@ -380,7 +380,7 @@ void gfunc_call(int nb_args)
}
save_regs(0); /* save used temporary registers */
func_sym = vtop->type.ref;
func_call = func_sym->r;
func_call = FUNC_CALL(func_sym->r);
/* fast call case */
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
func_call == FUNC_FASTCALLW) {
@ -402,7 +402,7 @@ void gfunc_call(int nb_args)
}
}
gcall_or_jmp(0);
if (args_size && func_sym->r != FUNC_STDCALL)
if (args_size && func_call != FUNC_STDCALL)
gadd_sp(args_size);
vtop--;
}
@ -423,7 +423,7 @@ void gfunc_prolog(CType *func_type)
CType *type;
sym = func_type->ref;
func_call = sym->r;
func_call = FUNC_CALL(sym->r);
addr = 8;
loc = 0;
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {

309
tcc.c
View File

@ -40,7 +40,7 @@
#include <time.h>
#ifdef _WIN32
#include <sys/timeb.h>
// #include <windows.h>
#include <windows.h>
#endif
#ifndef _WIN32
#include <sys/time.h>
@ -230,10 +230,24 @@ typedef struct AttributeDef {
int aligned;
int packed;
Section *section;
unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
unsigned char dllexport;
int func_attr; /* calling convention, exports, ... */
} AttributeDef;
/* -------------------------------------------------- */
/* gr: wrappers for casting sym->r for other purposes */
typedef struct {
unsigned
func_call : 8,
func_args : 8,
func_export : 1;
} func_attr_t;
#define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
#define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
#define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
#define INLINE_DEF(r) (*(int **)&(r))
/* -------------------------------------------------- */
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
@ -383,6 +397,9 @@ static CType char_pointer_type, func_old_type, int_type;
/* true if isid(c) || isnum(c) */
static unsigned char isidnum_table[256];
/* display some information during compilation */
static int verbose = 0;
/* compile with debug symbol (and use them if error during execution) */
static int do_debug = 0;
@ -723,14 +740,6 @@ static const char tcc_keywords[] =
#define TOK_UIDENT TOK_DEFINE
#ifdef _WIN32
int __stdcall GetModuleFileNameA(void *, char *, int);
void *__stdcall GetProcAddress(void *, const char *);
void *__stdcall GetModuleHandleA(const char *);
void *__stdcall LoadLibraryA(const char *);
int __stdcall FreeConsole(void);
int __stdcall VirtualProtect(void*,unsigned long,unsigned long,unsigned long*);
#define PAGE_EXECUTE_READWRITE 0x0040
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#ifndef __GNUC__
@ -758,6 +767,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
static char *pstrcpy(char *buf, int buf_size, const char *s);
static char *pstrcat(char *buf, int buf_size, const char *s);
static char *tcc_basename(const char *name);
static char *tcc_fileextension (const char *p);
static void next(void);
static void next_nomacro(void);
@ -858,10 +868,12 @@ int tcc_output_coff(TCCState *s1, FILE *f);
/* tccpe.c */
void *resolve_sym(TCCState *s1, const char *sym, int type);
int pe_load_def_file(struct TCCState *s1, FILE *fp);
void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
unsigned long pe_add_runtime(struct TCCState *s1);
int tcc_output_pe(struct TCCState *s1, const char *filename);
int pe_load_def_file(struct TCCState *s1, int fd);
int pe_test_res_file(void *v, int size);
int pe_load_res_file(struct TCCState *s1, int fd);
void pe_add_runtime(struct TCCState *s1);
void pe_guess_outfile(char *objfilename, int output_type);
int pe_output_file(struct TCCState *s1, const char *filename);
/* tccasm.c */
@ -1036,6 +1048,27 @@ static int strstart(const char *str, const char *val, const char **ptr)
return 1;
}
/* extract the basename of a file */
static char *tcc_basename(const char *name)
{
char *p = strchr(name, 0);
while (p > name
&& p[-1] != '/'
#ifdef _WIN32
&& p[-1] != '\\'
#endif
)
--p;
return p;
}
static char *tcc_fileextension (const char *name)
{
char *b = tcc_basename(name);
char *e = strrchr(b, '.');
return e ? e : strchr(b, 0);
}
#ifdef _WIN32
char *normalize_slashes(char *path)
{
@ -1162,6 +1195,16 @@ static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
*nb_ptr = nb;
}
static void dynarray_reset(void *pp, int *n)
{
void **p;
for (p = *(void***)pp; *n; ++p, --*n)
if (*p)
tcc_free(*p);
tcc_free(*(void**)pp);
*(void**)pp = NULL;
}
/* symbol allocator */
static Sym *__sym_malloc(void)
{
@ -1291,7 +1334,7 @@ static void put_extern_sym2(Sym *sym, Section *section,
unsigned long value, unsigned long size,
int can_add_underscore)
{
int sym_type, sym_bind, sh_num, info;
int sym_type, sym_bind, sh_num, info, other, attr;
Elf32_Sym *esym;
const char *name;
char buf1[256];
@ -1302,16 +1345,29 @@ static void put_extern_sym2(Sym *sym, Section *section,
sh_num = SHN_ABS;
else
sh_num = section->sh_num;
other = attr = 0;
if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
sym_type = STT_FUNC;
#ifdef TCC_TARGET_PE
if (sym->type.ref)
attr = sym->type.ref->r;
if (FUNC_EXPORT(attr))
other |= 1;
if (FUNC_CALL(attr) == FUNC_STDCALL)
other |= 2;
#endif
} else {
sym_type = STT_OBJECT;
}
if (sym->type.t & VT_STATIC)
sym_bind = STB_LOCAL;
else
sym_bind = STB_GLOBAL;
if (!sym->c) {
if ((sym->type.t & VT_BTYPE) == VT_FUNC)
sym_type = STT_FUNC;
else
sym_type = STT_OBJECT;
if (sym->type.t & VT_STATIC)
sym_bind = STB_LOCAL;
else
sym_bind = STB_GLOBAL;
name = get_tok_str(sym->v, NULL);
#ifdef CONFIG_TCC_BCHECK
if (do_bounds_check) {
@ -1342,18 +1398,26 @@ static void put_extern_sym2(Sym *sym, Section *section,
}
}
#endif
#ifdef TCC_TARGET_PE
if ((other & 2) && can_add_underscore) {
sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
name = buf1;
} else
#endif
if (tcc_state->leading_underscore && can_add_underscore) {
buf1[0] = '_';
pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
name = buf1;
}
info = ELF32_ST_INFO(sym_bind, sym_type);
sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
} else {
esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
esym->st_value = value;
esym->st_size = size;
esym->st_shndx = sh_num;
esym->st_other |= other;
}
}
@ -2868,7 +2932,7 @@ static void preprocess(int is_bof)
{
TCCState *s1 = tcc_state;
int size, i, c, n, saved_parse_flags;
char buf[1024], *q, *p;
char buf[1024], *q;
char buf1[1024];
BufferedFile *f;
Sym *s;
@ -2962,10 +3026,7 @@ static void preprocess(int is_bof)
} else {
if (c == '\"') {
/* first search in current dir if "header.h" */
size = 0;
p = strrchr(file->filename, '/');
if (p)
size = p + 1 - file->filename;
size = tcc_basename(file->filename) - file->filename;
if (size > sizeof(buf1) - 1)
size = sizeof(buf1) - 1;
memcpy(buf1, file->filename, size);
@ -4026,7 +4087,9 @@ static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
cstr_ccat(&cstr, ' ');
TOK_GET(t, st, cval);
cstr_cat(&cstr, get_tok_str(t, &cval));
#ifndef PP_NOSPACES
notfirst = 1;
#endif
}
cstr_ccat(&cstr, '\0');
#ifdef PP_DEBUG
@ -6112,7 +6175,7 @@ static int is_compatible_func(CType *type1, CType *type2)
if (!is_compatible_types(&s1->type, &s2->type))
return 0;
/* check func_call */
if (s1->r != s2->r)
if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
return 0;
/* XXX: not complete */
if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
@ -6569,12 +6632,12 @@ static void parse_attribute(AttributeDef *ad)
case TOK_CDECL1:
case TOK_CDECL2:
case TOK_CDECL3:
ad->func_call = FUNC_CDECL;
FUNC_CALL(ad->func_attr) = FUNC_CDECL;
break;
case TOK_STDCALL1:
case TOK_STDCALL2:
case TOK_STDCALL3:
ad->func_call = FUNC_STDCALL;
FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
break;
#ifdef TCC_TARGET_I386
case TOK_REGPARM1:
@ -6586,17 +6649,17 @@ static void parse_attribute(AttributeDef *ad)
else if (n < 0)
n = 0;
if (n > 0)
ad->func_call = FUNC_FASTCALL1 + n - 1;
FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
skip(')');
break;
case TOK_FASTCALL1:
case TOK_FASTCALL2:
case TOK_FASTCALL3:
ad->func_call = FUNC_FASTCALLW;
FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
break;
#endif
case TOK_DLLEXPORT:
ad->dllexport = 1;
FUNC_EXPORT(ad->func_attr) = 1;
break;
default:
if (tcc_state->warn_unsupported)
@ -6979,7 +7042,7 @@ static int parse_btype(CType *type, AttributeDef *ad)
}
the_end:
if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
error("signed and unsigned modifier");
error("signed and unsigned modifier");
if (tcc_state->char_is_unsigned) {
if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
t |= VT_UNSIGNED;
@ -7009,7 +7072,7 @@ static inline void convert_parameter_type(CType *pt)
static void post_type(CType *type, AttributeDef *ad)
{
int n, l, t1;
int n, l, t1, arg_size, align;
Sym **plast, *s, *first;
AttributeDef ad1;
CType pt;
@ -7020,6 +7083,7 @@ static void post_type(CType *type, AttributeDef *ad)
l = 0;
first = NULL;
plast = &first;
arg_size = 0;
if (tok != ')') {
for(;;) {
/* read param name and compute offset */
@ -7038,6 +7102,7 @@ static void post_type(CType *type, AttributeDef *ad)
type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
if ((pt.t & VT_BTYPE) == VT_VOID)
error("parameter declared as void");
arg_size += (type_size(&pt, &align) + 3) & ~3;
} else {
old_proto:
n = tok;
@ -7070,7 +7135,8 @@ static void post_type(CType *type, AttributeDef *ad)
type->t &= ~(VT_STORAGE | VT_CONSTANT);
post_type(type, ad);
/* we push a anonymous symbol which will contain the function prototype */
s = sym_push(SYM_FIELD, type, ad->func_call, l);
FUNC_ARGS(ad->func_attr) = arg_size;
s = sym_push(SYM_FIELD, type, ad->func_attr, l);
s->next = first;
type->t = t1 | VT_FUNC;
type->ref = s;
@ -7629,6 +7695,7 @@ static void unary(void)
next();
sa = s->next; /* first parameter */
nb_args = 0;
ret.r2 = VT_CONST;
/* compute first implicit argument if a structure is returned */
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
/* get some space for the returned structure */
@ -7643,7 +7710,6 @@ static void unary(void)
nb_args++;
} else {
ret.type = s->type;
ret.r2 = VT_CONST;
/* return in register */
if (is_float(ret.type.t)) {
ret.r = REG_FRET;
@ -8660,12 +8726,11 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
them as ((w)char *) expressions */
if ((tok == TOK_LSTR &&
#ifdef TCC_TARGET_PE
(t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) ||
(t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
#else
(t1->t & VT_BTYPE) == VT_INT) ||
(t1->t & VT_BTYPE) == VT_INT
#endif
(tok == TOK_STR &&
(t1->t & VT_BTYPE) == VT_BYTE)) {
) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
while (tok == TOK_STR || tok == TOK_LSTR) {
int cstr_len, ch;
CString *cstr;
@ -9166,9 +9231,9 @@ static void gen_inline_functions(void)
sym->c != 0) {
/* the function was used: generate its code and
convert it to a normal function */
str = (int *)sym->r;
str = INLINE_DEF(sym->r);
sym->r = VT_SYM | VT_CONST;
type->t &= ~VT_INLINE;
sym->type.t &= ~VT_INLINE;
macro_ptr = str;
next();
@ -9190,7 +9255,10 @@ static void gen_inline_functions(void)
if (((type->t & VT_BTYPE) == VT_FUNC) &&
(type->t & (VT_STATIC | VT_INLINE)) ==
(VT_STATIC | VT_INLINE)) {
str = (int *)sym->r;
//gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
continue;
str = INLINE_DEF(sym->r);
tok_str_free(str);
sym->r = 0; /* fail safe */
}
@ -9273,9 +9341,13 @@ static void decl(int l)
/* specific case: if not func_call defined, we put
the one of the prototype */
/* XXX: should have default value */
if (sym->type.ref->r != FUNC_CDECL &&
type.ref->r == FUNC_CDECL)
type.ref->r = sym->type.ref->r;
r = sym->type.ref->r;
if (FUNC_CALL(r) != FUNC_CDECL
&& FUNC_CALL(type.ref->r) == FUNC_CDECL)
FUNC_CALL(type.ref->r) = FUNC_CALL(r);
if (FUNC_EXPORT(r))
FUNC_EXPORT(type.ref->r) = 1;
if (!is_compatible_types(&sym->type, &type)) {
func_error1:
error("incompatible types for redefinition of '%s'",
@ -9317,7 +9389,7 @@ static void decl(int l)
}
tok_str_add(&func_str, -1);
tok_str_add(&func_str, 0);
sym->r = (int)func_str.str;
INLINE_DEF(sym->r) = func_str.str;
} else {
/* compute text section */
cur_text_section = ad.section;
@ -9325,11 +9397,6 @@ static void decl(int l)
cur_text_section = text_section;
sym->r = VT_SYM | VT_CONST;
gen_function(sym);
#ifdef TCC_TARGET_PE
if (ad.dllexport) {
((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
}
#endif
}
break;
} else {
@ -9341,8 +9408,8 @@ static void decl(int l)
} else if ((type.t & VT_BTYPE) == VT_FUNC) {
/* external function definition */
/* specific case for func_call attribute */
if (ad.func_call)
type.ref->r = ad.func_call;
if (ad.func_attr)
type.ref->r = ad.func_attr;
external_sym(v, &type, 0);
} else {
/* not lvalue if array */
@ -9891,9 +9958,9 @@ int tcc_relocate(TCCState *s1)
relocate_common_syms();
tcc_add_linker_symbols(s1);
#ifndef TCC_TARGET_PE
build_got_entries(s1);
#endif
/* compute relocation address : section are relocated in place. We
also alloc the bss space */
for(i = 1; i < s1->nb_sections; i++) {
@ -10118,27 +10185,15 @@ void tcc_delete(TCCState *s1)
tcc_free(s1->sections);
/* free loaded dlls array */
for(i = 0; i < s1->nb_loaded_dlls; i++)
tcc_free(s1->loaded_dlls[i]);
tcc_free(s1->loaded_dlls);
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
/* library paths */
for(i = 0; i < s1->nb_library_paths; i++)
tcc_free(s1->library_paths[i]);
tcc_free(s1->library_paths);
/* free library paths */
dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
/* cached includes */
for(i = 0; i < s1->nb_cached_includes; i++)
tcc_free(s1->cached_includes[i]);
tcc_free(s1->cached_includes);
for(i = 0; i < s1->nb_include_paths; i++)
tcc_free(s1->include_paths[i]);
tcc_free(s1->include_paths);
for(i = 0; i < s1->nb_sysinclude_paths; i++)
tcc_free(s1->sysinclude_paths[i]);
tcc_free(s1->sysinclude_paths);
/* free include paths */
dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
tcc_free(s1);
}
@ -10163,19 +10218,14 @@ int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
{
const char *ext, *filename1;
const char *ext;
Elf32_Ehdr ehdr;
int fd, ret;
BufferedFile *saved_file;
/* find source file type with extension */
filename1 = strrchr(filename, '/');
if (filename1)
filename1++;
else
filename1 = filename;
ext = strrchr(filename1, '.');
if (ext)
ext = tcc_fileextension(filename);
if (ext[0])
ext++;
/* open the file */
@ -10191,7 +10241,7 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
if (flags & AFF_PREPROCESS) {
ret = tcc_preprocess(s1);
} else if (!ext || !strcmp(ext, "c")) {
} else if (!ext[0] || !strcmp(ext, "c")) {
/* C file assumed */
ret = tcc_compile(s1);
} else
@ -10206,7 +10256,7 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#endif
#ifdef TCC_TARGET_PE
if (!strcmp(ext, "def")) {
ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
ret = pe_load_def_file(s1, file->fd);
} else
#endif
{
@ -10256,6 +10306,11 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
ret = tcc_load_coff(s1, fd);
} else
#endif
#ifdef TCC_TARGET_PE
if (pe_test_res_file(&ehdr, ret)) {
ret = pe_load_res_file(s1, fd);
} else
#endif
{
/* as GNU ld, consider it is an ld script if not recognized */
@ -10478,20 +10533,6 @@ int tcc_set_flag(TCCState *s, const char *flag_name, int value)
flag_name, value);
}
/* extract the basename of a file */
static char *tcc_basename(const char *name)
{
char *p = strchr(name, 0);
while (p > name
&& p[-1] != '/'
#ifdef _WIN32
&& p[-1] != '\\'
#endif
)
--p;
return p;
}
#if !defined(LIBTCC)
static int64_t getclock_us(void)
@ -10535,7 +10576,7 @@ void help(void)
" -shared generate a shared library\n"
" -static static linking\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -r relocatable output\n"
" -r generate (relocatable) object file\n"
"Debugger options:\n"
" -g generate runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
@ -10885,6 +10926,7 @@ int main(int argc, char **argv)
nb_libraries = 0;
reloc_output = 0;
print_search_dirs = 0;
ret = 0;
optind = parse_args(s, argc - 1, argv + 1) + 1;
@ -10915,30 +10957,28 @@ int main(int argc, char **argv)
if (!outfile) {
s->outfile = stdout;
} else {
s->outfile = fopen(outfile, "wb");
s->outfile = fopen(outfile, "w");
if (!s->outfile)
error("could not open '%s", outfile);
}
} else if (output_type != TCC_OUTPUT_MEMORY) {
if (!outfile) {
/* compute default outfile name */
pstrcpy(objfilename, sizeof(objfilename) - 1,
/* strip path */
tcc_basename(files[0]));
char *ext;
pstrcpy(objfilename, sizeof(objfilename), tcc_basename(files[0]));
ext = tcc_fileextension(objfilename);
#ifdef TCC_TARGET_PE
pe_guess_outfile(objfilename, output_type);
#else
if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
char *ext = strrchr(objfilename, '.');
if (!ext)
goto default_outfile;
/* add .o extension */
strcpy(ext + 1, "o");
} else {
default_outfile:
pstrcpy(objfilename, sizeof(objfilename), "a.out");
}
if (output_type == TCC_OUTPUT_DLL)
strcpy(ext, ".dll");
else
if (output_type == TCC_OUTPUT_EXE)
strcpy(ext, ".exe");
else
#endif
if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
strcpy(ext, ".o");
else
pstrcpy(objfilename, sizeof(objfilename), "a.out");
outfile = objfilename;
}
}
@ -10950,29 +10990,29 @@ int main(int argc, char **argv)
tcc_set_output_type(s, output_type);
/* compile or add each files or library */
for(i = 0;i < nb_files; i++) {
for(i = 0; i < nb_files && ret == 0; i++) {
const char *filename;
filename = files[i];
if (output_type == TCC_OUTPUT_PREPROCESS) {
tcc_add_file_internal(s, filename,
AFF_PRINT_ERROR | AFF_PREPROCESS);
if (tcc_add_file_internal(s, filename,
AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
ret = 1;
} else if (filename[0] == '-') {
if (tcc_add_library(s, filename + 2) < 0)
error("cannot find %s", filename);
} else {
if (filename[0] == '-') {
if (tcc_add_library(s, filename + 2) < 0)
error("cannot find %s", filename);
} else {
if (tcc_add_file(s, filename) < 0) {
ret = 1;
goto the_end;
}
}
if (tcc_add_file(s, filename) < 0)
ret = 1;
}
}
/* free all files */
tcc_free(files);
if (ret)
goto the_end;
if (do_bench) {
double total_time;
total_time = (double)(getclock_us() - start_time) / 1000000.0;
@ -10989,13 +11029,12 @@ int main(int argc, char **argv)
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (outfile)
fclose(s->outfile);
ret = 0;
} else if (s->output_type == TCC_OUTPUT_MEMORY) {
ret = tcc_run(s, argc - optind, argv + optind);
} else
#ifdef TCC_TARGET_PE
if (s->output_type != TCC_OUTPUT_OBJ) {
ret = tcc_output_pe(s, outfile);
ret = pe_output_file(s, outfile);
} else
#endif
{

161
tccelf.c
View File

@ -531,11 +531,11 @@ static void relocate_section(TCCState *s1, Section *s)
*(int *)ptr += s1->got_offsets[sym_index];
break;
#elif defined(TCC_TARGET_ARM)
case R_ARM_PC24:
case R_ARM_CALL:
case R_ARM_JUMP24:
case R_ARM_PLT32:
{
case R_ARM_PC24:
case R_ARM_CALL:
case R_ARM_JUMP24:
case R_ARM_PLT32:
{
int x;
x = (*(int *)ptr)&0xffffff;
(*(int *)ptr) &= 0xff000000;
@ -548,42 +548,42 @@ static void relocate_section(TCCState *s1, Section *s)
x >>= 2;
x &= 0xffffff;
(*(int *)ptr) |= x;
}
break;
case R_ARM_PREL31:
{
int x;
x = (*(int *)ptr) & 0x7fffffff;
(*(int *)ptr) &= 0x80000000;
x = (x * 2) / 2;
x += val - addr;
if((x^(x>>1))&0x40000000)
error("can't relocate value at %x",addr);
(*(int *)ptr) |= x & 0x7fffffff;
}
case R_ARM_ABS32:
*(int *)ptr += val;
break;
case R_ARM_BASE_PREL:
*(int *)ptr += s1->got->sh_addr - addr;
break;
case R_ARM_GOTOFF32:
}
break;
case R_ARM_PREL31:
{
int x;
x = (*(int *)ptr) & 0x7fffffff;
(*(int *)ptr) &= 0x80000000;
x = (x * 2) / 2;
x += val - addr;
if((x^(x>>1))&0x40000000)
error("can't relocate value at %x",addr);
(*(int *)ptr) |= x & 0x7fffffff;
}
case R_ARM_ABS32:
*(int *)ptr += val;
break;
case R_ARM_BASE_PREL:
*(int *)ptr += s1->got->sh_addr - addr;
break;
case R_ARM_GOTOFF32:
*(int *)ptr += val - s1->got->sh_addr;
break;
case R_ARM_GOT_BREL:
/* we load the got offset */
*(int *)ptr += s1->got_offsets[sym_index];
break;
case R_ARM_COPY:
case R_ARM_COPY:
break;
default:
fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
default:
fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
type,addr,(unsigned int )ptr,val);
break;
#elif defined(TCC_TARGET_C67)
case R_C60_32:
*(int *)ptr += val;
break;
case R_C60_32:
*(int *)ptr += val;
break;
case R_C60LO16:
{
uint32_t orig;
@ -603,7 +603,7 @@ static void relocate_section(TCCState *s1, Section *s)
case R_C60HI16:
break;
default:
fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
type,addr,(unsigned int )ptr,val);
break;
#else
@ -784,7 +784,7 @@ static void put_got_entry(TCCState *s1,
offset = plt->data_offset - 16;
}
#elif defined(TCC_TARGET_ARM)
if (reloc_type == R_ARM_JUMP_SLOT) {
if (reloc_type == R_ARM_JUMP_SLOT) {
Section *plt;
uint8_t *p;
@ -797,17 +797,17 @@ static void put_got_entry(TCCState *s1,
if (plt->data_offset == 0) {
/* first plt entry */
p = section_ptr_add(plt, 16);
put32(p , 0xe52de004);
put32(p + 4, 0xe59fe010);
put32(p + 8, 0xe08fe00e);
put32(p + 12, 0xe5bef008);
put32(p , 0xe52de004);
put32(p + 4, 0xe59fe010);
put32(p + 8, 0xe08fe00e);
put32(p + 12, 0xe5bef008);
}
p = section_ptr_add(plt, 16);
put32(p , 0xe59fc004);
put32(p+4, 0xe08fc00c);
put32(p+8, 0xe59cf000);
put32(p+12, s1->got->data_offset);
put32(p , 0xe59fc004);
put32(p+4, 0xe08fc00c);
put32(p+8, 0xe59cf000);
put32(p+12, s1->got->data_offset);
/* the symbol is modified so that it will be relocated to
the PLT */
@ -872,7 +872,7 @@ static void build_got_entries(TCCState *s1)
}
break;
#elif defined(TCC_TARGET_ARM)
case R_ARM_GOT_BREL:
case R_ARM_GOT_BREL:
case R_ARM_GOTOFF32:
case R_ARM_BASE_PREL:
case R_ARM_PLT32:
@ -891,7 +891,7 @@ static void build_got_entries(TCCState *s1)
}
break;
#elif defined(TCC_TARGET_C67)
case R_C60_GOT32:
case R_C60_GOT32:
case R_C60_GOTOFF:
case R_C60_GOTPC:
case R_C60_PLT32:
@ -1547,13 +1547,13 @@ int tcc_output_file(TCCState *s1, const char *filename)
p += 16;
}
#elif defined(TCC_TARGET_ARM)
int x;
x=s1->got->sh_addr - s1->plt->sh_addr - 12;
p +=16;
while (p < p_end) {
put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
p += 16;
}
int x;
x=s1->got->sh_addr - s1->plt->sh_addr - 12;
p +=16;
while (p < p_end) {
put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
p += 16;
}
#elif defined(TCC_TARGET_C67)
/* XXX: TODO */
#else
@ -1682,8 +1682,8 @@ int tcc_output_file(TCCState *s1, const char *filename)
#endif
#ifdef TCC_TARGET_ARM
#ifdef TCC_ARM_EABI
ehdr.e_ident[EI_OSABI] = 0;
ehdr.e_flags = 4 << 24;
ehdr.e_ident[EI_OSABI] = 0;
ehdr.e_flags = 4 << 24;
#else
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
#endif
@ -1859,7 +1859,7 @@ static int tcc_load_object_file(TCCState *s1,
if (sh->sh_type != SHT_PROGBITS &&
sh->sh_type != SHT_REL &&
#ifdef TCC_ARM_EABI
sh->sh_type != SHT_ARM_EXIDX &&
sh->sh_type != SHT_ARM_EXIDX &&
#endif
sh->sh_type != SHT_NOBITS)
continue;
@ -2022,16 +2022,16 @@ static int tcc_load_object_file(TCCState *s1,
return ret;
}
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
typedef struct ArchiveHeader {
char ar_name[16]; /* name of this member */
char ar_date[12]; /* file mtime */
char ar_uid[6]; /* owner uid; printed as decimal */
char ar_gid[6]; /* owner gid; printed as decimal */
char ar_mode[8]; /* file mode, printed as octal */
char ar_size[10]; /* file size, printed as decimal */
char ar_fmag[2]; /* should contain ARFMAG */
char ar_name[16]; /* name of this member */
char ar_date[12]; /* file mtime */
char ar_uid[6]; /* owner uid; printed as decimal */
char ar_gid[6]; /* owner gid; printed as decimal */
char ar_mode[8]; /* file mode, printed as octal */
char ar_size[10]; /* file size, printed as decimal */
char ar_fmag[2]; /* should contain ARFMAG */
} ArchiveHeader;
static int get_be32(const uint8_t *b)
@ -2056,26 +2056,26 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
ar_names = ar_index + nsyms * 4;
do {
bound = 0;
for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
sym_index = find_elf_sym(symtab_section, p);
if(sym_index) {
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
if(sym->st_shndx == SHN_UNDEF) {
off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
bound = 0;
for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
sym_index = find_elf_sym(symtab_section, p);
if(sym_index) {
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
if(sym->st_shndx == SHN_UNDEF) {
off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
#if 0
printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
#endif
++bound;
lseek(fd, off, SEEK_SET);
if(tcc_load_object_file(s1, fd, off) < 0) {
++bound;
lseek(fd, off, SEEK_SET);
if(tcc_load_object_file(s1, fd, off) < 0) {
fail:
ret = -1;
goto the_end;
}
}
}
}
}
}
}
} while(bound);
ret = 0;
the_end:
@ -2119,8 +2119,8 @@ static int tcc_load_archive(TCCState *s1, int fd)
size = (size + 1) & ~1;
if (!strcmp(ar_name, "/")) {
/* coff symbol table : we handle it */
if(s1->alacarte_link)
return tcc_load_alacarte(s1, fd, size);
if(s1->alacarte_link)
return tcc_load_alacarte(s1, fd, size);
} else if (!strcmp(ar_name, "//") ||
!strcmp(ar_name, "__.SYMDEF") ||
!strcmp(ar_name, "__.SYMDEF/") ||
@ -2146,7 +2146,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
Elf32_Sym *sym, *dynsym;
Elf32_Dyn *dt, *dynamic;
unsigned char *dynstr;
const char *name, *soname, *p;
const char *name, *soname;
DLLReference *dllref;
read(fd, &ehdr, sizeof(ehdr));
@ -2185,10 +2185,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
}
/* compute the real library name */
soname = filename;
p = strrchr(soname, '/');
if (p)
soname = p + 1;
soname = tcc_basename(filename);
for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
if (dt->d_tag == DT_SONAME) {

1717
tccpe.c

File diff suppressed because it is too large Load Diff

View File

@ -1,115 +1,126 @@
TinyCC-PE
---------
TinyCC-PE
---------
TinyCC (aka TCC) is a small but hyperfast C compiler,
written by Fabrice Bellard,
TinyCC (aka TCC) is a small but hyperfast C compiler,
written by Fabrice Bellard,
TinyCC-PE is the TinyCC compiler with an extension to
write PE executables for MS-Windows.
TinyCC-PE is the TinyCC compiler with an extension to
write PE executables for MS-Windows.
Features:
---------
Features:
---------
TinyCC-PE can produce console applications, native windows
GUI programs and DLL's.
TinyCC-PE can produce console applications, native windows
GUI programs and DLL's.
Most of the features pointed out by Fabrice Bellard for the
original version are still valid, i.e:
Most of the features pointed out by Fabrice Bellard for the
original version are still valid, i.e:
- SMALL! The package with ~400kb includes a complete C-compiler
with header files for console and GUI applications.
- SMALL! The package with ~400kb includes a complete C-compiler
with header files for console and GUI applications.
- With the -run switch you can run C-sources without any
linking directly from the command line.
- With the -run switch you can run C-sources without any
linking directly from the command line.
- TCC can of course compile itself.
- TCC can of course compile itself.
Compilation: (omit that if you use the binary ZIP package)
------------
You must use the MinGW and MSYS tools available at
http://www.mingw.org to compile TCC for Windows. Untar the TCC
archive and type in the MSYS shell:
./configure
make
make install
Compilation: (omit that if you use the binary ZIP package)
------------
You must use the MinGW and MSYS tools available at
http://www.mingw.org to compile TCC for Windows. Untar the TCC
archive and type in the MSYS shell:
./configure
make
make install
TCC is installed in c:\Program Files\tcc
TCC is installed in c:\Program Files\tcc
Installation: (from the binary ZIP package)
-------------
Just unzip the package to a directory anywhere on your computer.
Alternatively you can use win32\build-tcc.bat to compile TCC
with just gcc and ar from MINGW. To install, copy the entire
contents of the win32 directory to where you want.
Examples:
---------
Installation: (from the binary ZIP package)
-------------
For the 'Fibonacci' console example type from the command line:
tcc examples\fib.c
Just unzip the package to a directory anywhere on your computer.
For the 'Hello Windows' GUI example:
Examples:
---------
tcc examples\hello_win.c
For the 'Fibonacci' console example type from the command line:
tcc examples\fib.c
For the 'Hello Windows' GUI example:
tcc examples\hello_win.c
For the 'Hello DLL' example:
tcc -shared examples\dll.c
tcc examples\hello_dll.c examples\dll.def
For the 'Hello DLL' example:
Import Definitions:
-------------------
tcc -shared examples\dll.c
tcc examples\hello_dll.c examples\dll.def
TinyCC-PE searches and reads import definition files similar
to libraries.
The included 'tiny_impdef' program may be used to make .def files
for any DLL, e.g for an 'opengl32.def':
tiny_impdef.exe opengl32.dll
or to the same effect:
tcc -run tiny_impdef.c opengl32.dll
Import Definitions:
-------------------
Resource Files:
---------------
TinyCC-PE searches and reads import definition files similar
to libraries.
TinyCC-PE can now link windows resources in coff format as generated
by MINGW's windres.exe. For example:
The included 'tiny_impdef' program may be used to make .def files
for any DLL, e.g for an 'opengl32.def':
tiny_impdef.exe opengl32.dll
or to the same effect:
tcc -lkernel32 -run tiny_impdef.c opengl32.dll
windres -O coff app.rc -o appres.o
tcc app.c appres.o -o app.exe
Header Files:
-------------
Header Files:
-------------
The system header files, except '_mingw.h', are from the
2.0 mingw distribution. See also: http://www.mingw.org/
The system header files, except '_mingw.h', are from the
3.7 mingw distribution. See also: http://www.mingw.org/
Compile TCC:
------------
Compile TCC:
------------
With TCC itself just say:
With TCC itself just say:
tcc src\tcc.c -lkernel32 -o tcc.new.exe
tcc src\tcc.c -o tcc.new.exe
Other compilers like mingw-gcc or msvc work as well.
To make libtcc1.a, you need 'ar' from the mingw binutils.
Other compilers like mingw-gcc or msvc work as well.
To make libtcc1.a, you need 'ar' from the mingw binutils.
Documentation and License:
--------------------------
Documentation and License:
--------------------------
TCC is distributed under the GNU Lesser General Public License
(see COPYING file).
TCC is distributed under the GNU Lesser General Public License
(see COPYING file).
Please read the original tcc-doc.html to have all the features
of TCC. Also visit: http://fabrice.bellard.free.fr/tcc/
--------------------------------------------
09.Apr.2005 - grischka@users.sourceforge.net
Please read the original tcc-doc.html to have all the features
of TCC. Also visit: http://fabrice.bellard.free.fr/tcc/
--
grischka@users.sourceforge.net