mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-26 08:00:09 +08:00
initial PE format support
This commit is contained in:
parent
bdd09709d7
commit
2c538d7a2b
5
Makefile
5
Makefile
@ -20,7 +20,7 @@ endif
|
|||||||
|
|
||||||
DISAS=objdump -d
|
DISAS=objdump -d
|
||||||
INSTALL=install
|
INSTALL=install
|
||||||
PROGS=tcc$(EXESUF) c67-tcc$(EXESUF) arm-tcc$(EXESUF)
|
PROGS=tcc$(EXESUF) c67-tcc$(EXESUF) arm-tcc$(EXESUF) i386-win32-tcc$(EXESUF)
|
||||||
# run local version of tcc with local libraries and includes
|
# run local version of tcc with local libraries and includes
|
||||||
TCC=./tcc -B. -I.
|
TCC=./tcc -B. -I.
|
||||||
|
|
||||||
@ -125,6 +125,9 @@ c67-tcc$(EXESUF): tcc.c c67-gen.c tccelf.c tccasm.c tcctok.h libtcc.h tcccoff.c
|
|||||||
arm-tcc$(EXESUF): tcc.c arm-gen.c tccelf.c tccasm.c tcctok.h libtcc.h Makefile
|
arm-tcc$(EXESUF): tcc.c arm-gen.c tccelf.c tccasm.c tcctok.h libtcc.h Makefile
|
||||||
$(CC) $(CFLAGS) -DTCC_TARGET_ARM -o $@ $< $(LIBS)
|
$(CC) $(CFLAGS) -DTCC_TARGET_ARM -o $@ $< $(LIBS)
|
||||||
|
|
||||||
|
i386-win32-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h tccpe.c Makefile
|
||||||
|
$(CC) $(CFLAGS) -DTCC_TARGET_PE -o $@ $< $(LIBS)
|
||||||
|
|
||||||
# TinyCC runtime libraries
|
# TinyCC runtime libraries
|
||||||
libtcc1.o: libtcc1.c
|
libtcc1.o: libtcc1.c
|
||||||
$(CC) -O2 -Wall -c -o $@ $<
|
$(CC) -O2 -Wall -c -o $@ $<
|
||||||
|
100
tcc.c
100
tcc.c
@ -35,13 +35,11 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
#define CONFIG_TCC_STATIC
|
|
||||||
#endif
|
#endif
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -52,9 +50,7 @@
|
|||||||
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "stab.h"
|
#include "stab.h"
|
||||||
#ifndef CONFIG_TCC_STATIC
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#endif
|
|
||||||
#ifndef O_BINARY
|
#ifndef O_BINARY
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
@ -218,6 +214,7 @@ typedef struct AttributeDef {
|
|||||||
int packed;
|
int packed;
|
||||||
Section *section;
|
Section *section;
|
||||||
unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
|
unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
|
||||||
|
unsigned char dllexport;
|
||||||
} AttributeDef;
|
} AttributeDef;
|
||||||
|
|
||||||
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
||||||
@ -719,6 +716,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||||||
|
|
||||||
static char *pstrcpy(char *buf, int buf_size, const char *s);
|
static char *pstrcpy(char *buf, int buf_size, const char *s);
|
||||||
static char *pstrcat(char *buf, int buf_size, const char *s);
|
static char *pstrcat(char *buf, int buf_size, const char *s);
|
||||||
|
static const char *tcc_basename(const char *name);
|
||||||
|
|
||||||
static void next(void);
|
static void next(void);
|
||||||
static void next_nomacro(void);
|
static void next_nomacro(void);
|
||||||
@ -809,6 +807,13 @@ static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
|
|||||||
/* tcccoff.c */
|
/* tcccoff.c */
|
||||||
int tcc_output_coff(TCCState *s1, FILE *f);
|
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);
|
||||||
|
|
||||||
/* tccasm.c */
|
/* tccasm.c */
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
@ -902,7 +907,7 @@ static TCCSyms tcc_syms[] = {
|
|||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
void *dlsym(void *handle, const char *symbol)
|
void *resolve_sym(TCCState *s1, const char *symbol, int type)
|
||||||
{
|
{
|
||||||
TCCSyms *p;
|
TCCSyms *p;
|
||||||
p = tcc_syms;
|
p = tcc_syms;
|
||||||
@ -914,6 +919,15 @@ void *dlsym(void *handle, const char *symbol)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif !defined(WIN32)
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
void *resolve_sym(TCCState *s1, const char *sym, int type)
|
||||||
|
{
|
||||||
|
return dlsym(RTLD_DEFAULT, sym);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
@ -6290,6 +6304,9 @@ static void parse_attribute(AttributeDef *ad)
|
|||||||
skip(')');
|
skip(')');
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case TOK_DLLEXPORT:
|
||||||
|
ad->dllexport = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (tcc_state->warn_unsupported)
|
if (tcc_state->warn_unsupported)
|
||||||
warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
||||||
@ -9195,6 +9212,10 @@ static void asm_global_instr(void)
|
|||||||
#include "tcccoff.c"
|
#include "tcccoff.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
#include "tccpe.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* print the position in the source file of PC value 'pc' by reading
|
/* print the position in the source file of PC value 'pc' by reading
|
||||||
the stabs debug information */
|
the stabs debug information */
|
||||||
static void rt_printline(unsigned long wanted_pc)
|
static void rt_printline(unsigned long wanted_pc)
|
||||||
@ -9442,7 +9463,11 @@ int tcc_relocate(TCCState *s1)
|
|||||||
|
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
pe_add_runtime(s1);
|
||||||
|
#else
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
|
#endif
|
||||||
|
|
||||||
relocate_common_syms();
|
relocate_common_syms();
|
||||||
|
|
||||||
@ -9588,9 +9613,17 @@ TCCState *tcc_new(void)
|
|||||||
tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
|
tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
|
||||||
|
|
||||||
/* default library paths */
|
/* default library paths */
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
|
||||||
|
tcc_add_library_path(s, buf);
|
||||||
|
}
|
||||||
|
#else
|
||||||
tcc_add_library_path(s, "/usr/local/lib");
|
tcc_add_library_path(s, "/usr/local/lib");
|
||||||
tcc_add_library_path(s, "/usr/lib");
|
tcc_add_library_path(s, "/usr/lib");
|
||||||
tcc_add_library_path(s, "/lib");
|
tcc_add_library_path(s, "/lib");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* no section zero */
|
/* no section zero */
|
||||||
dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
|
dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
|
||||||
@ -9727,6 +9760,11 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
/* non preprocessed assembler */
|
/* non preprocessed assembler */
|
||||||
ret = tcc_assemble(s1, 0);
|
ret = tcc_assemble(s1, 0);
|
||||||
} else
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
if (!strcmp(ext, "def")) {
|
||||||
|
ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
|
||||||
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
fd = file->fd;
|
fd = file->fd;
|
||||||
@ -9749,12 +9787,16 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
ret = tcc_load_object_file(s1, fd, 0);
|
ret = tcc_load_object_file(s1, fd, 0);
|
||||||
} else if (ehdr.e_type == ET_DYN) {
|
} else if (ehdr.e_type == ET_DYN) {
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
ret = -1;
|
||||||
|
#else
|
||||||
void *h;
|
void *h;
|
||||||
h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
|
h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
|
||||||
if (h)
|
if (h)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
else
|
else
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ret = tcc_load_dll(s1, fd, filename,
|
ret = tcc_load_dll(s1, fd, filename,
|
||||||
(flags & AFF_REFERENCED_DLL) != 0);
|
(flags & AFF_REFERENCED_DLL) != 0);
|
||||||
@ -9830,7 +9872,11 @@ int tcc_add_library(TCCState *s, const char *libraryname)
|
|||||||
|
|
||||||
/* first we look for the dynamic library if not static linking */
|
/* first we look for the dynamic library if not static linking */
|
||||||
if (!s->static_link) {
|
if (!s->static_link) {
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
snprintf(buf, sizeof(buf), "%s.def", libraryname);
|
||||||
|
#else
|
||||||
snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
|
snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
|
||||||
|
#endif
|
||||||
if (tcc_add_dll(s, buf, 0) == 0)
|
if (tcc_add_dll(s, buf, 0) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -9855,17 +9901,23 @@ int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
|
|||||||
|
|
||||||
int tcc_set_output_type(TCCState *s, int output_type)
|
int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
|
||||||
|
|
||||||
s->output_type = output_type;
|
s->output_type = output_type;
|
||||||
|
|
||||||
if (!s->nostdinc) {
|
if (!s->nostdinc) {
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
/* default include paths */
|
/* default include paths */
|
||||||
/* XXX: reverse order needed if -isystem support */
|
/* XXX: reverse order needed if -isystem support */
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
tcc_add_sysinclude_path(s, "/usr/local/include");
|
tcc_add_sysinclude_path(s, "/usr/local/include");
|
||||||
tcc_add_sysinclude_path(s, "/usr/include");
|
tcc_add_sysinclude_path(s, "/usr/include");
|
||||||
|
#endif
|
||||||
snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
|
snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
|
||||||
tcc_add_sysinclude_path(s, buf);
|
tcc_add_sysinclude_path(s, buf);
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
|
||||||
|
tcc_add_sysinclude_path(s, buf);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if bound checking, then add corresponding sections */
|
/* if bound checking, then add corresponding sections */
|
||||||
@ -9898,12 +9950,14 @@ int tcc_set_output_type(TCCState *s, int output_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* add libc crt1/crti objects */
|
/* add libc crt1/crti objects */
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
|
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
|
||||||
!s->nostdlib) {
|
!s->nostdlib) {
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
if (output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
|
tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
|
||||||
tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
|
tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10013,7 +10067,7 @@ static int64_t getclock_us(void)
|
|||||||
|
|
||||||
void help(void)
|
void help(void)
|
||||||
{
|
{
|
||||||
printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2004 Fabrice Bellard\n"
|
printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
|
||||||
"usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
|
"usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
|
||||||
" [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
|
" [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
|
||||||
" [infile1 infile2...] [-run infile args...]\n"
|
" [infile1 infile2...] [-run infile args...]\n"
|
||||||
@ -10370,6 +10424,22 @@ int main(int argc, char **argv)
|
|||||||
char objfilename[1024];
|
char objfilename[1024];
|
||||||
int64_t start_time = 0;
|
int64_t start_time = 0;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* on win32, we suppose the lib and includes are at the location
|
||||||
|
of 'tcc.exe' */
|
||||||
|
{
|
||||||
|
static char path[1024];
|
||||||
|
|
||||||
|
GetModuleFileNameA(NULL, path, sizeof path);
|
||||||
|
p = d = strlwr(path);
|
||||||
|
while (*d)
|
||||||
|
if (*d++ == '\\')
|
||||||
|
(p = d)[-1] = '/';
|
||||||
|
*p = '\0';
|
||||||
|
tcc_lib_path = path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
s = tcc_new();
|
s = tcc_new();
|
||||||
output_type = TCC_OUTPUT_EXE;
|
output_type = TCC_OUTPUT_EXE;
|
||||||
outfile = NULL;
|
outfile = NULL;
|
||||||
@ -10461,11 +10531,17 @@ int main(int argc, char **argv)
|
|||||||
total_bytes / total_time / 1000000.0);
|
total_bytes / total_time / 1000000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->output_type != TCC_OUTPUT_MEMORY) {
|
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);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
tcc_output_file(s, outfile);
|
tcc_output_file(s, outfile);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
|
||||||
ret = tcc_run(s, argc - optind, argv + optind);
|
|
||||||
}
|
}
|
||||||
the_end:
|
the_end:
|
||||||
/* XXX: cannot do it with bound checking because of the malloc hooks */
|
/* XXX: cannot do it with bound checking because of the malloc hooks */
|
||||||
|
7
tccelf.c
7
tccelf.c
@ -385,11 +385,6 @@ static void relocate_common_syms(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *resolve_sym(const char *sym)
|
|
||||||
{
|
|
||||||
return dlsym(RTLD_DEFAULT, sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* relocate symbol table, resolve undefined symbols if do_resolve is
|
/* relocate symbol table, resolve undefined symbols if do_resolve is
|
||||||
true and output error if undefined symbol. */
|
true and output error if undefined symbol. */
|
||||||
static void relocate_syms(TCCState *s1, int do_resolve)
|
static void relocate_syms(TCCState *s1, int do_resolve)
|
||||||
@ -408,7 +403,7 @@ static void relocate_syms(TCCState *s1, int do_resolve)
|
|||||||
name = strtab_section->data + sym->st_name;
|
name = strtab_section->data + sym->st_name;
|
||||||
if (do_resolve) {
|
if (do_resolve) {
|
||||||
name = symtab_section->link->data + sym->st_name;
|
name = symtab_section->link->data + sym->st_name;
|
||||||
addr = (unsigned long)resolve_sym(name);
|
addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info));
|
||||||
if (addr) {
|
if (addr) {
|
||||||
sym->st_value = addr;
|
sym->st_value = addr;
|
||||||
goto found;
|
goto found;
|
||||||
|
1
tcctok.h
1
tcctok.h
@ -100,6 +100,7 @@
|
|||||||
DEF(TOK_STDCALL1, "stdcall")
|
DEF(TOK_STDCALL1, "stdcall")
|
||||||
DEF(TOK_STDCALL2, "__stdcall")
|
DEF(TOK_STDCALL2, "__stdcall")
|
||||||
DEF(TOK_STDCALL3, "__stdcall__")
|
DEF(TOK_STDCALL3, "__stdcall__")
|
||||||
|
DEF(TOK_DLLEXPORT, "dllexport")
|
||||||
DEF(TOK_NORETURN1, "noreturn")
|
DEF(TOK_NORETURN1, "noreturn")
|
||||||
DEF(TOK_NORETURN2, "__noreturn__")
|
DEF(TOK_NORETURN2, "__noreturn__")
|
||||||
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
|
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
|
||||||
|
Loading…
Reference in New Issue
Block a user