mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-13 05:10:07 +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 PCRELATIVE_DLLPLT 1
|
||||
#define RELOCATE_DLLPLT 0
|
||||
#define RELOCATE_DLLPLT 1
|
||||
|
||||
enum float_abi {
|
||||
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
|
||||
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
|
||||
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+2, 0x46c0); /* nop */
|
||||
}
|
||||
p = section_ptr_add(plt, 16);
|
||||
/* Jump to GOT entry where ld.so initially put address of PLT0 */
|
||||
write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] */
|
||||
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);
|
||||
p = section_ptr_add(plt, 12);
|
||||
/* save GOT offset for relocate_plt */
|
||||
write32le(p + 4, got_offset);
|
||||
return plt_offset;
|
||||
}
|
||||
|
||||
@ -154,10 +148,13 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||
write32le(s1->plt->data + 16, x - 16);
|
||||
p += 20;
|
||||
while (p < p_end) {
|
||||
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
||||
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
||||
p += 4;
|
||||
add32le(p + 12, x + (s1->plt->data - p));
|
||||
p += 16;
|
||||
write32le(p, 0xe28fc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000
|
||||
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)
|
||||
{
|
||||
ElfW(Sym) *sym;
|
||||
int sym_index;
|
||||
int sym_index, esym_index;
|
||||
|
||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||
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_32S:
|
||||
case R_X86_64_64:
|
||||
#elif defined(TCC_TARGET_ARM)
|
||||
case R_ARM_ABS32:
|
||||
#elif defined(TCC_TARGET_ARM64)
|
||||
case R_AARCH64_ABS32:
|
||||
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) ||
|
||||
file_type == TCC_OUTPUT_OBJ ||
|
||||
(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 */
|
||||
s->sh_size = s->data_offset;
|
||||
}
|
||||
@ -2339,6 +2346,42 @@ static void tidy_section_headers(TCCState *s1, int *sec_order)
|
||||
}
|
||||
#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 */
|
||||
/* XXX: suppress unneeded sections */
|
||||
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;
|
||||
Section *strsec, *interp, *dynamic, *dynstr;
|
||||
|
||||
#ifdef TCC_TARGET_ARM
|
||||
create_arm_attribute_section (s1);
|
||||
#endif
|
||||
|
||||
file_type = s1->output_type;
|
||||
s1->nb_errors = 0;
|
||||
ret = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user