From 1da71596897387594cbe4ba85d6c3c0e4272fabe Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Sat, 1 Aug 2020 19:44:49 +0200 Subject: [PATCH] Add arm64 dll support Most support was already present. arm64-link.c: - create_plt_entry: - remove DLLs unimplemented! - relocate: - Add TCC_OUTPUT_DLL for R_AARCH64_ABS64/R_AARCH64_ABS32/R_AARCH64_PREL32 tccelf.c: - prepare_dynamic_rel: - Add R_AARCH64_ABS64/R_AARCH64_ABS32/R_AARCH64_PREL32 - fill_got_entry: - Change 'TCC_TARGET_X86_64' into 'PTR_SIZE == 8' --- arm64-link.c | 40 ++++++++++++++++++++++++++++++++++++---- tccelf.c | 9 +++++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/arm64-link.c b/arm64-link.c index b8c9c0c..740993c 100644 --- a/arm64-link.c +++ b/arm64-link.c @@ -88,9 +88,6 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ uint8_t *p; unsigned plt_offset; - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_error("DLLs unimplemented!"); - if (plt->data_offset == 0) { section_ptr_add(plt, 32); } @@ -152,19 +149,54 @@ 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) { - int sym_index = ELFW(R_SYM)(rel->r_info); + int sym_index = ELFW(R_SYM)(rel->r_info), esym_index; #ifdef DEBUG_RELOC ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; #endif switch(type) { case R_AARCH64_ABS64: + 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_AARCH64_ABS64); + qrel->r_addend = rel->r_addend; + qrel++; + break; + } else { + qrel->r_info = ELFW(R_INFO)(0, R_AARCH64_RELATIVE); + qrel->r_addend = read64le(ptr) + val; + qrel++; + } + } add64le(ptr, val); return; case R_AARCH64_ABS32: + if (s1->output_type == TCC_OUTPUT_DLL) { + /* XXX: this logic may depend on TCC's codegen + now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */ + qrel->r_offset = rel->r_offset; + qrel->r_info = ELFW(R_INFO)(0, R_AARCH64_RELATIVE); + /* Use sign extension! */ + qrel->r_addend = (int)read32le(ptr) + val; + qrel++; + } add32le(ptr, val); return; case R_AARCH64_PREL32: + if (s1->output_type == TCC_OUTPUT_DLL) { + /* DLL relocation */ + esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; + if (esym_index) { + qrel->r_offset = rel->r_offset; + qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_PREL32); + /* Use sign extension! */ + qrel->r_addend = (int)read32le(ptr) + rel->r_addend; + qrel++; + break; + } + } write32le(ptr, val - addr); return; case R_AARCH64_MOVW_UABS_G0_NC: diff --git a/tccelf.c b/tccelf.c index ebbd15f..a940062 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1028,7 +1028,7 @@ 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) +#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || 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 +1046,9 @@ 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_ARM64) + case R_AARCH64_ABS32: + case R_AARCH64_ABS64: #endif count++; break; @@ -1053,6 +1056,8 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) case R_386_PC32: #elif defined(TCC_TARGET_X86_64) case R_X86_64_PC32: +#elif defined(TCC_TARGET_ARM64) + case R_AARCH64_PREL32: #endif if (get_sym_attr(s1, sym_index, 0)->dyn_index) count++; @@ -1553,7 +1558,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) if (0 == offset) return; section_reserve(s1->got, offset + PTR_SIZE); -#ifdef TCC_TARGET_X86_64 +#if PTR_SIZE == 8 write64le(s1->got->data + offset, sym->st_value); #else write32le(s1->got->data + offset, sym->st_value);