mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-29 06:10:09 +08:00
Add arm dll support
Most support was already present. arm-link.c: - set RELOCATE_DLLPLT to 1 - create_plt_entry: - remove DLLs unimplemented! - leave code gen to relocate_plt. only set got_offset - relocate_plt: - create code for got entry - relocate: - Add TCC_OUTPUT_DLL for R_ARM_ABS32 tccelf.c: - prepare_dynamic_rel: - Add R_ARM_ABS32 - alloc_sec_names: - Always add SHT_ARM_ATTRIBUTES section - New function create_arm_attribute_section - elf_output_file: - call create_arm_attribute_section
This commit is contained in:
parent
1da7159689
commit
b8fb2b02d9
35
arm-link.c
35
arm-link.c
@ -16,7 +16,7 @@
|
|||||||
#define ELF_PAGE_SIZE 0x1000
|
#define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
#define PCRELATIVE_DLLPLT 1
|
#define PCRELATIVE_DLLPLT 1
|
||||||
#define RELOCATE_DLLPLT 0
|
#define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
enum float_abi {
|
enum float_abi {
|
||||||
ARM_SOFTFP_FLOAT,
|
ARM_SOFTFP_FLOAT,
|
||||||
@ -107,8 +107,6 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
|
|
||||||
/* when building a DLL, GOT entry accesses must be done relative to
|
/* when building a DLL, GOT entry accesses must be done relative to
|
||||||
start of GOT (see x86_64 example above) */
|
start of GOT (see x86_64 example above) */
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_error("DLLs unimplemented!");
|
|
||||||
|
|
||||||
/* empty PLT: create PLT0 entry that push address of call site and
|
/* empty PLT: create PLT0 entry that push address of call site and
|
||||||
jump to ld.so resolution routine (GOT + 8) */
|
jump to ld.so resolution routine (GOT + 8) */
|
||||||
@ -127,13 +125,9 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
write32le(p, 0x4778); /* bx pc */
|
write32le(p, 0x4778); /* bx pc */
|
||||||
write32le(p+2, 0x46c0); /* nop */
|
write32le(p+2, 0x46c0); /* nop */
|
||||||
}
|
}
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(plt, 12);
|
||||||
/* Jump to GOT entry where ld.so initially put address of PLT0 */
|
/* save GOT offset for relocate_plt */
|
||||||
write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] */
|
write32le(p + 4, got_offset);
|
||||||
write32le(p+4, 0xe08fc00c); /* add ip, pc, ip */
|
|
||||||
write32le(p+8, 0xe59cf000); /* ldr pc, [ip] */
|
|
||||||
/* p + 12 contains offset to GOT entry once patched by relocate_plt */
|
|
||||||
write32le(p+12, got_offset);
|
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +148,13 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
write32le(s1->plt->data + 16, x - 16);
|
write32le(s1->plt->data + 16, x - 16);
|
||||||
p += 20;
|
p += 20;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
|
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
||||||
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
||||||
p += 4;
|
p += 4;
|
||||||
add32le(p + 12, x + (s1->plt->data - p));
|
write32le(p, 0xe28fc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000
|
||||||
p += 16;
|
write32le(p + 4, 0xe28cca00 | ((off >> 12) & 0xff)); // add ip, ip, #0xNN000
|
||||||
|
write32le(p + 8, 0xe5bcf000 | (off & 0xfff)); // ldr pc, [ip, #0xNNN]!
|
||||||
|
p += 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +163,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int sym_index;
|
int sym_index, esym_index;
|
||||||
|
|
||||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
@ -348,6 +345,18 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
(*(int *)ptr) |= x & 0x7fffffff;
|
(*(int *)ptr) |= x & 0x7fffffff;
|
||||||
}
|
}
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||||
|
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
||||||
|
qrel->r_offset = rel->r_offset;
|
||||||
|
if (esym_index) {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_ARM_ABS32);
|
||||||
|
qrel++;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
qrel->r_info = ELFW(R_INFO)(0, R_ARM_RELATIVE);
|
||||||
|
qrel++;
|
||||||
|
}
|
||||||
|
}
|
||||||
*(int *)ptr += val;
|
*(int *)ptr += val;
|
||||||
return;
|
return;
|
||||||
case R_ARM_REL32:
|
case R_ARM_REL32:
|
||||||
|
51
tccelf.c
51
tccelf.c
@ -1028,7 +1028,8 @@ static void relocate_rel(TCCState *s1, Section *sr)
|
|||||||
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
|
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \
|
||||||
|
defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64)
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
int sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
@ -1046,6 +1047,8 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
|||||||
case R_X86_64_32:
|
case R_X86_64_32:
|
||||||
case R_X86_64_32S:
|
case R_X86_64_32S:
|
||||||
case R_X86_64_64:
|
case R_X86_64_64:
|
||||||
|
#elif defined(TCC_TARGET_ARM)
|
||||||
|
case R_ARM_ABS32:
|
||||||
#elif defined(TCC_TARGET_ARM64)
|
#elif defined(TCC_TARGET_ARM64)
|
||||||
case R_AARCH64_ABS32:
|
case R_AARCH64_ABS32:
|
||||||
case R_AARCH64_ABS64:
|
case R_AARCH64_ABS64:
|
||||||
@ -1779,7 +1782,11 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
|
|||||||
if ((s1->do_debug && s->sh_type != SHT_RELX) ||
|
if ((s1->do_debug && s->sh_type != SHT_RELX) ||
|
||||||
file_type == TCC_OUTPUT_OBJ ||
|
file_type == TCC_OUTPUT_OBJ ||
|
||||||
(s->sh_flags & SHF_ALLOC) ||
|
(s->sh_flags & SHF_ALLOC) ||
|
||||||
i == (s1->nb_sections - 1)) {
|
i == (s1->nb_sections - 1)
|
||||||
|
#ifdef TCC_TARGET_ARM
|
||||||
|
|| s->sh_type == SHT_ARM_ATTRIBUTES
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
/* we output all sections if debug or object file */
|
/* we output all sections if debug or object file */
|
||||||
s->sh_size = s->data_offset;
|
s->sh_size = s->data_offset;
|
||||||
}
|
}
|
||||||
@ -2339,6 +2346,42 @@ static void tidy_section_headers(TCCState *s1, int *sec_order)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_ARM
|
||||||
|
static void create_arm_attribute_section(TCCState *s1)
|
||||||
|
{
|
||||||
|
// Needed for DLL support.
|
||||||
|
static const unsigned char arm_attr[] = {
|
||||||
|
0x41, // 'A'
|
||||||
|
0x2c, 0x00, 0x00, 0x00, // size 0x2c
|
||||||
|
'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi"
|
||||||
|
0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22
|
||||||
|
0x05, 0x36, 0x00, // 'CPU_name', "6"
|
||||||
|
0x06, 0x06, // 'CPU_arch', 'v6'
|
||||||
|
0x08, 0x01, // 'ARM_ISA_use', 'Yes'
|
||||||
|
0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1'
|
||||||
|
0x0a, 0x02, // 'FP_arch', 'VFPv2'
|
||||||
|
0x12, 0x04, // 'ABI_PCS_wchar_t', 4
|
||||||
|
0x14, 0x01, // 'ABI_FP_denormal', 'Needed'
|
||||||
|
0x15, 0x01, // 'ABI_FP_exceptions', 'Needed'
|
||||||
|
0x17, 0x03, // 'ABI_FP_number_model', 'IEEE 754'
|
||||||
|
0x18, 0x01, // 'ABI_align_needed', '8-byte'
|
||||||
|
0x19, 0x01, // 'ABI_align_preserved', '8-byte, except leaf SP'
|
||||||
|
0x1a, 0x02, // 'ABI_enum_size', 'int'
|
||||||
|
0x1c, 0x01, // 'ABI_VFP_args', 'VFP registers'
|
||||||
|
0x22, 0x01 // 'CPU_unaligned_access', 'v6'
|
||||||
|
};
|
||||||
|
Section *attr = new_section(s1, ".ARM.attributes", SHT_ARM_ATTRIBUTES, 0);
|
||||||
|
unsigned char *ptr = section_ptr_add(attr, sizeof(arm_attr));
|
||||||
|
attr->sh_addralign = 1;
|
||||||
|
memcpy(ptr, arm_attr, sizeof(arm_attr));
|
||||||
|
if (s1->float_abi != ARM_HARD_FLOAT) {
|
||||||
|
ptr[26] = 0x00; // 'FP_arch', 'No'
|
||||||
|
ptr[41] = 0x1e; // 'ABI_optimization_goals'
|
||||||
|
ptr[42] = 0x06; // 'Aggressive Debug'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Output an elf, coff or binary file */
|
/* Output an elf, coff or binary file */
|
||||||
/* XXX: suppress unneeded sections */
|
/* XXX: suppress unneeded sections */
|
||||||
static int elf_output_file(TCCState *s1, const char *filename)
|
static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
@ -2348,6 +2391,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
ElfW(Phdr) *phdr;
|
ElfW(Phdr) *phdr;
|
||||||
Section *strsec, *interp, *dynamic, *dynstr;
|
Section *strsec, *interp, *dynamic, *dynstr;
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_ARM
|
||||||
|
create_arm_attribute_section (s1);
|
||||||
|
#endif
|
||||||
|
|
||||||
file_type = s1->output_type;
|
file_type = s1->output_type;
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user