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:
124
tccelf.c
124
tccelf.c
@ -468,6 +468,7 @@ static void relocate_section(TCCState *s1, Section *s)
|
||||
|
||||
/* CPU specific */
|
||||
switch(type) {
|
||||
#if defined(TCC_TARGET_I386)
|
||||
case R_386_32:
|
||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||
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 */
|
||||
*(int *)ptr += s1->got_offsets[sym_index];
|
||||
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 */
|
||||
@ -646,6 +684,7 @@ static void put_got_entry(TCCState *s1,
|
||||
sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
|
||||
name = symtab_section->link->data + sym->st_name;
|
||||
offset = sym->st_value;
|
||||
#ifdef TCC_TARGET_I386
|
||||
if (reloc_type == R_386_JMP_SLOT) {
|
||||
Section *plt;
|
||||
uint8_t *p;
|
||||
@ -684,6 +723,40 @@ static void put_got_entry(TCCState *s1,
|
||||
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||
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,
|
||||
size, info, 0, sym->st_shndx, name);
|
||||
/* put a got entry */
|
||||
@ -717,6 +790,7 @@ static void build_got_entries(TCCState *s1)
|
||||
rel++) {
|
||||
type = ELF32_R_TYPE(rel->r_info);
|
||||
switch(type) {
|
||||
#if defined(TCC_TARGET_I386)
|
||||
case R_386_GOT32:
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOTPC:
|
||||
@ -735,6 +809,28 @@ static void build_got_entries(TCCState *s1)
|
||||
sym_index);
|
||||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
@ -916,9 +1012,6 @@ static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
|
||||
static char elf_interp[] = "/lib/ld-linux.so.2";
|
||||
#endif
|
||||
|
||||
#define ELF_START_ADDR 0x08048000
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
/* output an ELF file */
|
||||
/* XXX: suppress unneeded sections */
|
||||
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];
|
||||
type = ELF32_ST_TYPE(esym->st_info);
|
||||
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,
|
||||
sym - (Elf32_Sym *)symtab_section->data);
|
||||
} else if (type == STT_OBJECT) {
|
||||
@ -1017,7 +1110,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||
esym->st_info, 0,
|
||||
bss_section->sh_num, name);
|
||||
put_elf_reloc(s1->dynsym, bss_section,
|
||||
offset, R_386_COPY, index);
|
||||
offset, R_COPY, index);
|
||||
offset += esym->st_size;
|
||||
bss_section->data_offset = offset;
|
||||
}
|
||||
@ -1306,6 +1399,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||
p = s1->plt->data;
|
||||
p_end = p + s1->plt->data_offset;
|
||||
if (p < p_end) {
|
||||
#if defined(TCC_TARGET_I386)
|
||||
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
|
||||
put32(p + 8, get32(p + 8) + s1->got->sh_addr);
|
||||
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);
|
||||
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;
|
||||
#ifdef __FreeBSD__
|
||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
|
||||
#endif
|
||||
#ifdef TCC_TARGET_ARM
|
||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
|
||||
#endif
|
||||
switch(file_type) {
|
||||
default:
|
||||
@ -1428,7 +1536,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||
ehdr.e_type = ET_REL;
|
||||
break;
|
||||
}
|
||||
ehdr.e_machine = EM_386;
|
||||
ehdr.e_machine = EM_TCC_TARGET;
|
||||
ehdr.e_version = EV_CURRENT;
|
||||
ehdr.e_shoff = file_offset;
|
||||
ehdr.e_ehsize = sizeof(Elf32_Ehdr);
|
||||
@ -1543,7 +1651,7 @@ static int tcc_load_object_file(TCCState *s1,
|
||||
goto fail1;
|
||||
/* test CPU specific stuff */
|
||||
if (ehdr.e_ident[5] != ELFDATA2LSB ||
|
||||
ehdr.e_machine != EM_386) {
|
||||
ehdr.e_machine != EM_TCC_TARGET) {
|
||||
fail1:
|
||||
error_noabort("invalid object file");
|
||||
return -1;
|
||||
@ -1881,7 +1989,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
|
||||
|
||||
/* test CPU specific stuff */
|
||||
if (ehdr.e_ident[5] != ELFDATA2LSB ||
|
||||
ehdr.e_machine != EM_386) {
|
||||
ehdr.e_machine != EM_TCC_TARGET) {
|
||||
error_noabort("bad architecture");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user