summaryrefslogtreecommitdiff
path: root/arm64-link.c
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2020-08-14 23:04:13 +0100
committerThomas Preud'homme <robotux@celest.fr>2020-08-14 23:04:13 +0100
commitafd09586d7ead4f146ad7a7a471be34196b3c6bc (patch)
tree87854be29fb4264b979b700fa45445f58faa4c26 /arm64-link.c
parente2ccf3981d78dfeb390d22c74625b60310100abb (diff)
New upstream version 0.9.27+git20200814.62c30a4a
Diffstat (limited to 'arm64-link.c')
-rw-r--r--arm64-link.c62
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;