mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-15 05:20:06 +08:00
ARM target support (Daniel Glockner) - allow unsigned char as default on ARM (Daniel Glockner) - fixed small ld script support (Daniel Glockner)
This commit is contained in:
parent
44cea6aee9
commit
4df5bd2eb0
12
i386-gen.c
12
i386-gen.c
@ -70,8 +70,18 @@ int reg_classes[NB_REGS] = {
|
|||||||
/* maximum alignment (for aligned attribute support) */
|
/* maximum alignment (for aligned attribute support) */
|
||||||
#define MAX_ALIGN 8
|
#define MAX_ALIGN 8
|
||||||
|
|
||||||
|
/******************************************************/
|
||||||
|
/* ELF defines */
|
||||||
|
|
||||||
|
#define EM_TCC_TARGET EM_386
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
/* relocation type for 32 bit data relocation */
|
||||||
#define R_DATA_32 R_386_32
|
#define R_DATA_32 R_386_32
|
||||||
|
#define R_JMP_SLOT R_386_JMP_SLOT
|
||||||
|
#define R_COPY R_386_COPY
|
||||||
|
|
||||||
|
#define ELF_START_ADDR 0x08048000
|
||||||
|
#define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
|
|
||||||
|
104
tcc.c
104
tcc.c
@ -61,18 +61,21 @@
|
|||||||
|
|
||||||
/* target selection */
|
/* target selection */
|
||||||
//#define TCC_TARGET_I386 /* i386 code generator */
|
//#define TCC_TARGET_I386 /* i386 code generator */
|
||||||
|
//#define TCC_TARGET_ARM /* ARMv4 code generator */
|
||||||
|
|
||||||
/* default target is I386 */
|
/* default target is I386 */
|
||||||
#if !defined(TCC_TARGET_I386)
|
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM)
|
||||||
#define TCC_TARGET_I386
|
#define TCC_TARGET_I386
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(WIN32) && !defined(TCC_UCLIBC)
|
#if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM)
|
||||||
#define CONFIG_TCC_BCHECK /* enable bound checking code */
|
#define CONFIG_TCC_BCHECK /* enable bound checking code */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* define it to include assembler support */
|
/* define it to include assembler support */
|
||||||
|
#if !defined(TCC_TARGET_ARM)
|
||||||
#define CONFIG_TCC_ASM
|
#define CONFIG_TCC_ASM
|
||||||
|
#endif
|
||||||
|
|
||||||
/* path to find crt1.o, crti.o and crtn.o. Only needed when generating
|
/* path to find crt1.o, crti.o and crtn.o. Only needed when generating
|
||||||
executables or dlls */
|
executables or dlls */
|
||||||
@ -471,6 +474,7 @@ struct TCCState {
|
|||||||
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
||||||
#define VT_CONSTANT 0x0800 /* const modifier */
|
#define VT_CONSTANT 0x0800 /* const modifier */
|
||||||
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
||||||
|
#define VT_SIGNED 0x2000 /* signed type */
|
||||||
|
|
||||||
/* storage */
|
/* storage */
|
||||||
#define VT_EXTERN 0x00000080 /* extern definition */
|
#define VT_EXTERN 0x00000080 /* extern definition */
|
||||||
@ -684,6 +688,7 @@ void vpop(void);
|
|||||||
void vswap(void);
|
void vswap(void);
|
||||||
void vdup(void);
|
void vdup(void);
|
||||||
int get_reg(int rc);
|
int get_reg(int rc);
|
||||||
|
int get_reg_ex(int rc,int rc2);
|
||||||
|
|
||||||
static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
||||||
const int *macro_str, int can_read_stream);
|
const int *macro_str, int can_read_stream);
|
||||||
@ -704,8 +709,11 @@ static int parse_btype(CType *type, AttributeDef *ad);
|
|||||||
static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
||||||
static int is_compatible_types(CType *type1, CType *type2);
|
static int is_compatible_types(CType *type1, CType *type2);
|
||||||
|
|
||||||
|
int ieee_finite(double d);
|
||||||
void error(const char *fmt, ...);
|
void error(const char *fmt, ...);
|
||||||
void vpushi(int v);
|
void vpushi(int v);
|
||||||
|
void vrott(int n);
|
||||||
|
static void vpush_global_sym(CType *type, int v);
|
||||||
void vset(CType *type, int r, int v);
|
void vset(CType *type, int r, int v);
|
||||||
void type_to_str(char *buf, int buf_size,
|
void type_to_str(char *buf, int buf_size,
|
||||||
CType *type, const char *varstr);
|
CType *type, const char *varstr);
|
||||||
@ -785,6 +793,10 @@ static inline int is_float(int t)
|
|||||||
#include "i386-gen.c"
|
#include "i386-gen.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_ARM
|
||||||
|
#include "arm-gen.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_STATIC
|
#ifdef CONFIG_TCC_STATIC
|
||||||
|
|
||||||
#define RTLD_LAZY 0x001
|
#define RTLD_LAZY 0x001
|
||||||
@ -2220,15 +2232,18 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
|||||||
case TOK_CDOUBLE:
|
case TOK_CDOUBLE:
|
||||||
case TOK_CLLONG:
|
case TOK_CLLONG:
|
||||||
case TOK_CULLONG:
|
case TOK_CULLONG:
|
||||||
|
#if LDOUBLE_SIZE == 8
|
||||||
|
case TOK_CLDOUBLE:
|
||||||
|
#endif
|
||||||
str[len++] = cv->tab[0];
|
str[len++] = cv->tab[0];
|
||||||
str[len++] = cv->tab[1];
|
str[len++] = cv->tab[1];
|
||||||
break;
|
break;
|
||||||
case TOK_CLDOUBLE:
|
|
||||||
#if LDOUBLE_SIZE == 12
|
#if LDOUBLE_SIZE == 12
|
||||||
|
case TOK_CLDOUBLE:
|
||||||
str[len++] = cv->tab[0];
|
str[len++] = cv->tab[0];
|
||||||
str[len++] = cv->tab[1];
|
str[len++] = cv->tab[1];
|
||||||
str[len++] = cv->tab[2];
|
str[len++] = cv->tab[2];
|
||||||
#else
|
#elif LDOUBLE_SIZE != 8
|
||||||
#error add long double size support
|
#error add long double size support
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@ -2257,6 +2272,10 @@ static void tok_str_add_tok(TokenString *s)
|
|||||||
cv.tab[0] = p[0]; \
|
cv.tab[0] = p[0]; \
|
||||||
cv.tab[1] = p[1]; \
|
cv.tab[1] = p[1]; \
|
||||||
cv.tab[2] = p[2];
|
cv.tab[2] = p[2];
|
||||||
|
#elif LDOUBLE_SIZE == 8
|
||||||
|
#define LDOUBLE_GET(p, cv) \
|
||||||
|
cv.tab[0] = p[0]; \
|
||||||
|
cv.tab[1] = p[1];
|
||||||
#else
|
#else
|
||||||
#error add long double size support
|
#error add long double size support
|
||||||
#endif
|
#endif
|
||||||
@ -4335,6 +4354,29 @@ void save_reg(int r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find a register of class 'rc2' with at most one reference on stack.
|
||||||
|
* If none, call get_reg(rc) */
|
||||||
|
int get_reg_ex(int rc, int rc2)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
SValue *p;
|
||||||
|
|
||||||
|
for(r=0;r<NB_REGS;r++) {
|
||||||
|
if (reg_classes[r] & rc2) {
|
||||||
|
int n;
|
||||||
|
n=0;
|
||||||
|
for(p = vstack; p <= vtop; p++) {
|
||||||
|
if ((p->r & VT_VALMASK) == r ||
|
||||||
|
(p->r2 & VT_VALMASK) == r)
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (n <= 1)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return get_reg(rc);
|
||||||
|
}
|
||||||
|
|
||||||
/* find a free register of class 'rc'. If none, save one register */
|
/* find a free register of class 'rc'. If none, save one register */
|
||||||
int get_reg(int rc)
|
int get_reg(int rc)
|
||||||
{
|
{
|
||||||
@ -4905,10 +4947,13 @@ void gen_opl(int op)
|
|||||||
if (a == 0) {
|
if (a == 0) {
|
||||||
b = gtst(0, 0);
|
b = gtst(0, 0);
|
||||||
} else {
|
} else {
|
||||||
#ifdef TCC_TARGET_I386
|
#if defined(TCC_TARGET_I386)
|
||||||
b = psym(0x850f, 0);
|
b = psym(0x850f, 0);
|
||||||
|
#elif defined(TCC_TARGET_ARM)
|
||||||
|
b = ind;
|
||||||
|
o(0x1A000000 | encbranch(ind, 0, 1));
|
||||||
#else
|
#else
|
||||||
error("not implemented");
|
#error not supported
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5447,7 +5492,11 @@ static void gen_cast(CType *type)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
do_itof:
|
do_itof:
|
||||||
|
#if !defined(TCC_TARGET_ARM)
|
||||||
gen_cvt_itof1(dbt);
|
gen_cvt_itof1(dbt);
|
||||||
|
#else
|
||||||
|
gen_cvt_itof(dbt);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else if (sf) {
|
} else if (sf) {
|
||||||
/* convert fp to int */
|
/* convert fp to int */
|
||||||
@ -6302,6 +6351,9 @@ static int parse_btype(CType *type, AttributeDef *ad)
|
|||||||
case TOK_SIGNED2:
|
case TOK_SIGNED2:
|
||||||
case TOK_SIGNED3:
|
case TOK_SIGNED3:
|
||||||
typespec_found = 1;
|
typespec_found = 1;
|
||||||
|
t |= VT_SIGNED;
|
||||||
|
next();
|
||||||
|
break;
|
||||||
case TOK_REGISTER:
|
case TOK_REGISTER:
|
||||||
case TOK_AUTO:
|
case TOK_AUTO:
|
||||||
case TOK_RESTRICT1:
|
case TOK_RESTRICT1:
|
||||||
@ -6361,6 +6413,14 @@ static int parse_btype(CType *type, AttributeDef *ad)
|
|||||||
type_found = 1;
|
type_found = 1;
|
||||||
}
|
}
|
||||||
the_end:
|
the_end:
|
||||||
|
if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
|
||||||
|
error("signed and unsigned modifier");
|
||||||
|
#ifdef CHAR_IS_UNSIGNED
|
||||||
|
if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
|
||||||
|
t |= VT_UNSIGNED;
|
||||||
|
#endif
|
||||||
|
t &= ~VT_SIGNED;
|
||||||
|
|
||||||
/* long is never used as type */
|
/* long is never used as type */
|
||||||
if ((t & VT_BTYPE) == VT_LONG)
|
if ((t & VT_BTYPE) == VT_LONG)
|
||||||
t = (t & ~VT_BTYPE) | VT_INT;
|
t = (t & ~VT_BTYPE) | VT_INT;
|
||||||
@ -8838,7 +8898,9 @@ void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
|||||||
|
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_I386
|
||||||
#include "i386-asm.c"
|
#include "i386-asm.c"
|
||||||
|
#endif
|
||||||
#include "tccasm.c"
|
#include "tccasm.c"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -9013,7 +9075,14 @@ static int rt_get_caller_pc(unsigned long *paddr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error add arch specific rt_get_caller_pc()
|
|
||||||
|
#warning add arch specific rt_get_caller_pc()
|
||||||
|
|
||||||
|
static int rt_get_caller_pc(unsigned long *paddr,
|
||||||
|
ucontext_t *uc, int level)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* emit a run time error at position 'pc' */
|
/* emit a run time error at position 'pc' */
|
||||||
@ -9207,6 +9276,19 @@ TCCState *tcc_new(void)
|
|||||||
#if defined(TCC_TARGET_I386)
|
#if defined(TCC_TARGET_I386)
|
||||||
tcc_define_symbol(s, "__i386__", NULL);
|
tcc_define_symbol(s, "__i386__", NULL);
|
||||||
#endif
|
#endif
|
||||||
|
#if 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);
|
||||||
|
tcc_define_symbol(s, "arm_elf", NULL);
|
||||||
|
tcc_define_symbol(s, "__arm__", NULL);
|
||||||
|
tcc_define_symbol(s, "__arm", NULL);
|
||||||
|
tcc_define_symbol(s, "arm", NULL);
|
||||||
|
tcc_define_symbol(s, "__APCS_32__", NULL);
|
||||||
|
#endif
|
||||||
|
#ifdef CHAR_IS_UNSIGNED
|
||||||
|
tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
|
||||||
|
#endif
|
||||||
#if defined(linux)
|
#if defined(linux)
|
||||||
tcc_define_symbol(s, "__linux__", NULL);
|
tcc_define_symbol(s, "__linux__", NULL);
|
||||||
tcc_define_symbol(s, "linux", NULL);
|
tcc_define_symbol(s, "linux", NULL);
|
||||||
@ -9359,11 +9441,14 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
{
|
{
|
||||||
fd = file->fd;
|
fd = file->fd;
|
||||||
/* assume executable format: auto guess file type */
|
/* assume executable format: auto guess file type */
|
||||||
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
|
ret = read(fd, &ehdr, sizeof(ehdr));
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
if (ret <= 0) {
|
||||||
error_noabort("could not read header");
|
error_noabort("could not read header");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
} else if (ret != sizeof(ehdr)) {
|
||||||
|
goto try_load_script;
|
||||||
}
|
}
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
if (ehdr.e_ident[0] == ELFMAG0 &&
|
if (ehdr.e_ident[0] == ELFMAG0 &&
|
||||||
ehdr.e_ident[1] == ELFMAG1 &&
|
ehdr.e_ident[1] == ELFMAG1 &&
|
||||||
@ -9393,6 +9478,7 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
ret = tcc_load_archive(s1, fd);
|
ret = tcc_load_archive(s1, fd);
|
||||||
} else {
|
} else {
|
||||||
/* as GNU ld, consider it is an ld script if not recognized */
|
/* as GNU ld, consider it is an ld script if not recognized */
|
||||||
|
try_load_script:
|
||||||
ret = tcc_load_ldscript(s1);
|
ret = tcc_load_ldscript(s1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_noabort("unrecognized file type");
|
error_noabort("unrecognized file type");
|
||||||
|
124
tccelf.c
124
tccelf.c
@ -468,6 +468,7 @@ static void relocate_section(TCCState *s1, Section *s)
|
|||||||
|
|
||||||
/* CPU specific */
|
/* CPU specific */
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
#if defined(TCC_TARGET_I386)
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||||
esym_index = s1->symtab_to_dynsym[sym_index];
|
esym_index = s1->symtab_to_dynsym[sym_index];
|
||||||
@ -513,6 +514,43 @@ static void relocate_section(TCCState *s1, Section *s)
|
|||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
*(int *)ptr += s1->got_offsets[sym_index];
|
*(int *)ptr += s1->got_offsets[sym_index];
|
||||||
break;
|
break;
|
||||||
|
#elif defined(TCC_TARGET_ARM)
|
||||||
|
case R_ARM_PC24:
|
||||||
|
case R_ARM_PLT32:
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
x = (*(int *)ptr)&0xffffff;
|
||||||
|
(*(int *)ptr) &= 0xff000000;
|
||||||
|
if (x & 0x800000)
|
||||||
|
x -= 0x1000000;
|
||||||
|
x *= 4;
|
||||||
|
x += val - addr;
|
||||||
|
if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
|
||||||
|
error("can't relocate value at %x",addr);
|
||||||
|
x >>= 2;
|
||||||
|
x &= 0xffffff;
|
||||||
|
(*(int *)ptr) |= x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case R_ARM_ABS32:
|
||||||
|
*(int *)ptr += val;
|
||||||
|
break;
|
||||||
|
case R_ARM_GOTPC:
|
||||||
|
*(int *)ptr += s1->got->sh_addr - addr;
|
||||||
|
break;
|
||||||
|
case R_ARM_GOT32:
|
||||||
|
/* we load the got offset */
|
||||||
|
*(int *)ptr += s1->got_offsets[sym_index];
|
||||||
|
break;
|
||||||
|
case R_ARM_COPY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
|
||||||
|
type,addr,(unsigned int )ptr,val);
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
#error unsupported processor
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if the relocation is allocated, we change its symbol table */
|
/* if the relocation is allocated, we change its symbol table */
|
||||||
@ -646,6 +684,7 @@ static void put_got_entry(TCCState *s1,
|
|||||||
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||||
name = symtab_section->link->data + sym->st_name;
|
name = symtab_section->link->data + sym->st_name;
|
||||||
offset = sym->st_value;
|
offset = sym->st_value;
|
||||||
|
#ifdef TCC_TARGET_I386
|
||||||
if (reloc_type == R_386_JMP_SLOT) {
|
if (reloc_type == R_386_JMP_SLOT) {
|
||||||
Section *plt;
|
Section *plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
@ -684,6 +723,40 @@ static void put_got_entry(TCCState *s1,
|
|||||||
if (s1->output_type == TCC_OUTPUT_EXE)
|
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||||
offset = plt->data_offset - 16;
|
offset = plt->data_offset - 16;
|
||||||
}
|
}
|
||||||
|
#elif defined(TCC_TARGET_ARM)
|
||||||
|
if (reloc_type == R_ARM_JUMP_SLOT) {
|
||||||
|
Section *plt;
|
||||||
|
uint8_t *p;
|
||||||
|
|
||||||
|
/* if we build a DLL, we add a %ebx offset */
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
error("DLLs unimplemented!");
|
||||||
|
|
||||||
|
/* add a PLT entry */
|
||||||
|
plt = s1->plt;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = section_ptr_add(plt, 16);
|
||||||
|
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 */
|
||||||
|
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||||
|
offset = plt->data_offset - 16;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error unsupported CPU
|
||||||
|
#endif
|
||||||
index = put_elf_sym(s1->dynsym, offset,
|
index = put_elf_sym(s1->dynsym, offset,
|
||||||
size, info, 0, sym->st_shndx, name);
|
size, info, 0, sym->st_shndx, name);
|
||||||
/* put a got entry */
|
/* put a got entry */
|
||||||
@ -717,6 +790,7 @@ static void build_got_entries(TCCState *s1)
|
|||||||
rel++) {
|
rel++) {
|
||||||
type = ELF32_R_TYPE(rel->r_info);
|
type = ELF32_R_TYPE(rel->r_info);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
#if defined(TCC_TARGET_I386)
|
||||||
case R_386_GOT32:
|
case R_386_GOT32:
|
||||||
case R_386_GOTOFF:
|
case R_386_GOTOFF:
|
||||||
case R_386_GOTPC:
|
case R_386_GOTPC:
|
||||||
@ -735,6 +809,28 @@ static void build_got_entries(TCCState *s1)
|
|||||||
sym_index);
|
sym_index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#elif defined(TCC_TARGET_ARM)
|
||||||
|
case R_ARM_GOT32:
|
||||||
|
case R_ARM_GOTOFF:
|
||||||
|
case R_ARM_GOTPC:
|
||||||
|
case R_ARM_PLT32:
|
||||||
|
if (!s1->got)
|
||||||
|
build_got(s1);
|
||||||
|
if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
|
||||||
|
sym_index = ELF32_R_SYM(rel->r_info);
|
||||||
|
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||||
|
/* look at the symbol got offset. If none, then add one */
|
||||||
|
if (type == R_ARM_GOT32)
|
||||||
|
reloc_type = R_ARM_GLOB_DAT;
|
||||||
|
else
|
||||||
|
reloc_type = R_ARM_JUMP_SLOT;
|
||||||
|
put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
|
||||||
|
sym_index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
#error unsupported CPU
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -916,9 +1012,6 @@ static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
|
|||||||
static char elf_interp[] = "/lib/ld-linux.so.2";
|
static char elf_interp[] = "/lib/ld-linux.so.2";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ELF_START_ADDR 0x08048000
|
|
||||||
#define ELF_PAGE_SIZE 0x1000
|
|
||||||
|
|
||||||
/* output an ELF file */
|
/* output an ELF file */
|
||||||
/* XXX: suppress unneeded sections */
|
/* XXX: suppress unneeded sections */
|
||||||
int tcc_output_file(TCCState *s1, const char *filename)
|
int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
@ -1005,7 +1098,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
|||||||
esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
|
esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
|
||||||
type = ELF32_ST_TYPE(esym->st_info);
|
type = ELF32_ST_TYPE(esym->st_info);
|
||||||
if (type == STT_FUNC) {
|
if (type == STT_FUNC) {
|
||||||
put_got_entry(s1, R_386_JMP_SLOT, esym->st_size,
|
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
|
||||||
esym->st_info,
|
esym->st_info,
|
||||||
sym - (Elf32_Sym *)symtab_section->data);
|
sym - (Elf32_Sym *)symtab_section->data);
|
||||||
} else if (type == STT_OBJECT) {
|
} else if (type == STT_OBJECT) {
|
||||||
@ -1017,7 +1110,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
|||||||
esym->st_info, 0,
|
esym->st_info, 0,
|
||||||
bss_section->sh_num, name);
|
bss_section->sh_num, name);
|
||||||
put_elf_reloc(s1->dynsym, bss_section,
|
put_elf_reloc(s1->dynsym, bss_section,
|
||||||
offset, R_386_COPY, index);
|
offset, R_COPY, index);
|
||||||
offset += esym->st_size;
|
offset += esym->st_size;
|
||||||
bss_section->data_offset = offset;
|
bss_section->data_offset = offset;
|
||||||
}
|
}
|
||||||
@ -1306,6 +1399,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
|||||||
p = s1->plt->data;
|
p = s1->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + s1->plt->data_offset;
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
|
#if defined(TCC_TARGET_I386)
|
||||||
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
|
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
|
||||||
put32(p + 8, get32(p + 8) + s1->got->sh_addr);
|
put32(p + 8, get32(p + 8) + s1->got->sh_addr);
|
||||||
p += 16;
|
p += 16;
|
||||||
@ -1313,6 +1407,17 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
|||||||
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
|
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
|
||||||
p += 16;
|
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;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error unsupported CPU
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1415,6 +1520,9 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
|||||||
ehdr.e_ident[6] = EV_CURRENT;
|
ehdr.e_ident[6] = EV_CURRENT;
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
|
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
|
||||||
|
#endif
|
||||||
|
#ifdef TCC_TARGET_ARM
|
||||||
|
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
|
||||||
#endif
|
#endif
|
||||||
switch(file_type) {
|
switch(file_type) {
|
||||||
default:
|
default:
|
||||||
@ -1428,7 +1536,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
|||||||
ehdr.e_type = ET_REL;
|
ehdr.e_type = ET_REL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ehdr.e_machine = EM_386;
|
ehdr.e_machine = EM_TCC_TARGET;
|
||||||
ehdr.e_version = EV_CURRENT;
|
ehdr.e_version = EV_CURRENT;
|
||||||
ehdr.e_shoff = file_offset;
|
ehdr.e_shoff = file_offset;
|
||||||
ehdr.e_ehsize = sizeof(Elf32_Ehdr);
|
ehdr.e_ehsize = sizeof(Elf32_Ehdr);
|
||||||
@ -1543,7 +1651,7 @@ static int tcc_load_object_file(TCCState *s1,
|
|||||||
goto fail1;
|
goto fail1;
|
||||||
/* test CPU specific stuff */
|
/* test CPU specific stuff */
|
||||||
if (ehdr.e_ident[5] != ELFDATA2LSB ||
|
if (ehdr.e_ident[5] != ELFDATA2LSB ||
|
||||||
ehdr.e_machine != EM_386) {
|
ehdr.e_machine != EM_TCC_TARGET) {
|
||||||
fail1:
|
fail1:
|
||||||
error_noabort("invalid object file");
|
error_noabort("invalid object file");
|
||||||
return -1;
|
return -1;
|
||||||
@ -1881,7 +1989,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
|
|||||||
|
|
||||||
/* test CPU specific stuff */
|
/* test CPU specific stuff */
|
||||||
if (ehdr.e_ident[5] != ELFDATA2LSB ||
|
if (ehdr.e_ident[5] != ELFDATA2LSB ||
|
||||||
ehdr.e_machine != EM_386) {
|
ehdr.e_machine != EM_TCC_TARGET) {
|
||||||
error_noabort("bad architecture");
|
error_noabort("bad architecture");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
11
tcctok.h
11
tcctok.h
@ -111,9 +111,20 @@
|
|||||||
DEF(TOK___moddi3, "__moddi3")
|
DEF(TOK___moddi3, "__moddi3")
|
||||||
DEF(TOK___udivdi3, "__udivdi3")
|
DEF(TOK___udivdi3, "__udivdi3")
|
||||||
DEF(TOK___umoddi3, "__umoddi3")
|
DEF(TOK___umoddi3, "__umoddi3")
|
||||||
|
#ifdef TCC_TARGET_ARM
|
||||||
|
DEF(TOK___divsi3, "__divsi3")
|
||||||
|
DEF(TOK___modsi3, "__modsi3")
|
||||||
|
DEF(TOK___udivsi3, "__udivsi3")
|
||||||
|
DEF(TOK___umodsi3, "__umodsi3")
|
||||||
|
DEF(TOK___sardi3, "__ashrdi3")
|
||||||
|
DEF(TOK___shrdi3, "__lshrdi3")
|
||||||
|
DEF(TOK___shldi3, "__ashldi3")
|
||||||
|
#else
|
||||||
|
/* XXX: same names on i386 ? */
|
||||||
DEF(TOK___sardi3, "__sardi3")
|
DEF(TOK___sardi3, "__sardi3")
|
||||||
DEF(TOK___shrdi3, "__shrdi3")
|
DEF(TOK___shrdi3, "__shrdi3")
|
||||||
DEF(TOK___shldi3, "__shldi3")
|
DEF(TOK___shldi3, "__shldi3")
|
||||||
|
#endif
|
||||||
DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
|
DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
|
||||||
DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
|
DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
|
||||||
DEF(TOK___ulltof, "__ulltof")
|
DEF(TOK___ulltof, "__ulltof")
|
||||||
|
Loading…
Reference in New Issue
Block a user