diff options
author | Thomas Preud'homme <robotux@celest.fr> | 2020-08-14 23:04:13 +0100 |
---|---|---|
committer | Thomas Preud'homme <robotux@celest.fr> | 2020-08-14 23:04:13 +0100 |
commit | afd09586d7ead4f146ad7a7a471be34196b3c6bc (patch) | |
tree | 87854be29fb4264b979b700fa45445f58faa4c26 /arm64-link.c | |
parent | e2ccf3981d78dfeb390d22c74625b60310100abb (diff) |
New upstream version 0.9.27+git20200814.62c30a4a
Diffstat (limited to 'arm64-link.c')
-rw-r--r-- | arm64-link.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/arm64-link.c b/arm64-link.c index 59322c5..740993c 100644 --- a/arm64-link.c +++ b/arm64-link.c @@ -12,7 +12,7 @@ #define R_NUM R_AARCH64_NUM #define ELF_START_ADDR 0x00400000 -#define ELF_PAGE_SIZE 0x1000 +#define ELF_PAGE_SIZE 0x10000 #define PCRELATIVE_DLLPLT 1 #define RELOCATE_DLLPLT 1 @@ -37,6 +37,7 @@ int code_reloc (int reloc_type) case R_AARCH64_ADD_ABS_LO12_NC: case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_GLOB_DAT: case R_AARCH64_COPY: return 0; @@ -46,8 +47,6 @@ int code_reloc (int reloc_type) case R_AARCH64_JUMP_SLOT: return 1; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -64,6 +63,7 @@ int gotplt_entry_type (int reloc_type) case R_AARCH64_MOVW_UABS_G3: case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_GLOB_DAT: case R_AARCH64_JUMP_SLOT: case R_AARCH64_COPY: @@ -79,8 +79,6 @@ int gotplt_entry_type (int reloc_type) case R_AARCH64_LD64_GOT_LO12_NC: return ALWAYS_GOTPLT_ENTRY; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -90,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,23 +147,56 @@ ST_FUNC void relocate_plt(TCCState *s1) } } -void relocate_init(Section *sr) {} - 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: - write64le(ptr, val); + 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: - write32le(ptr, val); + 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: @@ -199,6 +227,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t write32le(ptr, ((read32le(ptr) & 0xffc003ff) | (val & 0xfff) << 10)); return; + case R_AARCH64_LDST64_ABS_LO12_NC: + write32le(ptr, ((read32le(ptr) & 0xffc003ff) | + (val & 0xff8) << 7)); + return; case R_AARCH64_JUMP26: case R_AARCH64_CALL26: #ifdef DEBUG_RELOC @@ -215,7 +247,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t case R_AARCH64_ADR_GOT_PAGE: { uint64_t off = (((s1->got->sh_addr + - s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12)); + get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12)); if ((off + ((uint64_t)1 << 20)) >> 21) tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed"); write32le(ptr, ((read32le(ptr) & 0x9f00001f) | @@ -226,7 +258,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t write32le(ptr, ((read32le(ptr) & 0xfff803ff) | ((s1->got->sh_addr + - s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7)); + get_sym_attr(s1, sym_index, 0)->got_offset) & 0xff8) << 7)); return; case R_AARCH64_COPY: return; |