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'
This commit is contained in:
herman ten brugge 2020-08-01 19:44:49 +02:00
parent d55a3f3362
commit 1da7159689
2 changed files with 43 additions and 6 deletions

View file

@ -88,9 +88,6 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
uint8_t *p; uint8_t *p;
unsigned plt_offset; unsigned plt_offset;
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_error("DLLs unimplemented!");
if (plt->data_offset == 0) { if (plt->data_offset == 0) {
section_ptr_add(plt, 32); 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) 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 #ifdef DEBUG_RELOC
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
#endif #endif
switch(type) { switch(type) {
case R_AARCH64_ABS64: 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); add64le(ptr, val);
return; return;
case R_AARCH64_ABS32: 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); add32le(ptr, val);
return; return;
case R_AARCH64_PREL32: 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); write32le(ptr, val - addr);
return; return;
case R_AARCH64_MOVW_UABS_G0_NC: case R_AARCH64_MOVW_UABS_G0_NC:

View file

@ -1028,7 +1028,7 @@ 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) #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || 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 +1046,9 @@ 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_ARM64)
case R_AARCH64_ABS32:
case R_AARCH64_ABS64:
#endif #endif
count++; count++;
break; break;
@ -1053,6 +1056,8 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
case R_386_PC32: case R_386_PC32:
#elif defined(TCC_TARGET_X86_64) #elif defined(TCC_TARGET_X86_64)
case R_X86_64_PC32: case R_X86_64_PC32:
#elif defined(TCC_TARGET_ARM64)
case R_AARCH64_PREL32:
#endif #endif
if (get_sym_attr(s1, sym_index, 0)->dyn_index) if (get_sym_attr(s1, sym_index, 0)->dyn_index)
count++; count++;
@ -1553,7 +1558,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
if (0 == offset) if (0 == offset)
return; return;
section_reserve(s1->got, offset + PTR_SIZE); section_reserve(s1->got, offset + PTR_SIZE);
#ifdef TCC_TARGET_X86_64 #if PTR_SIZE == 8
write64le(s1->got->data + offset, sym->st_value); write64le(s1->got->data + offset, sym->st_value);
#else #else
write32le(s1->got->data + offset, sym->st_value); write32le(s1->got->data + offset, sym->st_value);