aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arm-link.c4
-rw-r--r--arm64-link.c8
-rw-r--r--tccelf.c70
-rw-r--r--x86_64-link.c6
4 files changed, 22 insertions, 66 deletions
diff --git a/arm-link.c b/arm-link.c
index 7d94048..396c2c0 100644
--- a/arm-link.c
+++ b/arm-link.c
@@ -43,8 +43,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
{
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
x = (*(int *) ptr) & 0xffffff;
- if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_ABS)
- val = s1->plt->sh_addr;
#ifdef DEBUG_RELOC
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
#endif
@@ -140,8 +138,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
}
/* Compute final offset */
- if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
- x -= 4;
x += val - addr;
if (!to_thumb && is_call) {
blx_bit = 0; /* bl -> blx */
diff --git a/arm64-link.c b/arm64-link.c
index 9122eff..581f1ee 100644
--- a/arm64-link.c
+++ b/arm64-link.c
@@ -65,14 +65,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
return;
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
- /* This check must match the one in build_got_entries, testing
- if we really need a PLT slot. */
- if (sym->st_shndx == SHN_UNDEF ||
- sym->st_shndx == SHN_ABS)
- /* We've put the PLT slot offset into r_addend when generating
- it, and that's what we must use as relocation value (adjusted
- by section offset of course). */
- val = s1->plt->sh_addr + rel->r_addend;
#ifdef DEBUG_RELOC
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
(char *) symtab_section->link->data + sym->st_name);
diff --git a/tccelf.c b/tccelf.c
index e652351..f2210a3 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -654,8 +654,8 @@ ST_FUNC void relocate_common_syms(void)
true and output error if undefined symbol. */
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
{
- ElfW(Sym) *sym, *esym;
- int sym_bind, sh_num, sym_index;
+ ElfW(Sym) *sym;
+ int sym_bind, sh_num;
const char *name;
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
@@ -676,15 +676,9 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
goto found;
}
#endif
- } else if (s1->dynsym) {
- /* if dynamic symbol exist, then use it */
- sym_index = find_elf_sym(s1->dynsym, name);
- if (sym_index) {
- esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
- sym->st_value = esym->st_value;
- goto found;
- }
- }
+ /* if dynamic symbol exist, it will be used in relocate_section */
+ } else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
+ goto found;
/* XXX: _fp_hw seems to be part of the ABI, so we ignore
it */
if (!strcmp(name, "_fp_hw"))
@@ -714,7 +708,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
ElfW(Sym) *sym;
int type, sym_index;
unsigned char *ptr;
- addr_t val, addr;
+ addr_t tgt, addr;
+ struct sym_attr *symattr;
relocate_init(sr);
for_each_elem(sr, 0, rel, ElfW_Rel) {
@@ -722,14 +717,22 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- val = sym->st_value;
+ type = ELFW(R_TYPE)(rel->r_info);
+ symattr = get_sym_attr(s1, sym_index, 0);
+ tgt = sym->st_value;
+ /* If static relocation to a dynamic symbol, relocate to PLT entry.
+ Note 1: in tcc -run mode we go through PLT to avoid range issues
+ Note 2: symbols compiled with libtcc and later added with
+ tcc_add_symbol are not dynamic and thus have symattr NULL */
+ if (relocs_info[type].gotplt_entry != NO_GOTPLT_ENTRY &&
+ relocs_info[type].code_reloc && symattr && symattr->plt_offset)
+ tgt = s1->plt->sh_addr + symattr->plt_offset;
#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
- val += rel->r_addend;
+ tgt += rel->r_addend;
#endif
- type = ELFW(R_TYPE)(rel->r_info);
addr = s->sh_addr + rel->r_offset;
- relocate(s1, rel, type, ptr, addr, val);
+ relocate(s1, rel, type, ptr, addr, tgt);
}
/* if the relocation is allocated, we change its symbol table */
if (sr->sh_flags & SHF_ALLOC)
@@ -1030,7 +1033,6 @@ ST_FUNC void build_got_entries(TCCState *s1)
ElfW_Rel *rel;
ElfW(Sym) *sym;
int i, type, reloc_type, sym_index;
- unsigned long ofs;
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
@@ -1075,38 +1077,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
reloc_type = R_JMP_SLOT;
else
reloc_type = R_GLOB_DAT;
- ofs = put_got_entry(s1, reloc_type, type, sym->st_size,
- sym->st_info, sym_index);
-
-#ifdef DEBUG_RELOC
- printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
- (char *) symtab_section->link->data + sym->st_name, type,
- sym->st_shndx, ofs);
-#endif
-
-#if defined (TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
- /* We store the place of the generated PLT slot in our addend. */
- if (relocs_info[type].pltoff_addend)
- rel->r_addend += ofs;
-
-#elif defined (TCC_TARGET_ARM)
- if (type == R_ARM_PC24 || type == R_ARM_CALL ||
- type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
- addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
- + rel->r_offset);
- /* x must be signed! */
- int x = *ptr & 0xffffff;
- x = (x << 8) >> 8;
- x <<= 2;
- x += ofs;
- x >>= 2;
-#ifdef DEBUG_RELOC
- printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
- (*ptr & 0xff000000) | x, x);
-#endif
- *ptr = (*ptr & 0xff000000) | x;
- }
-#endif
+ put_got_entry(s1, reloc_type, type, sym->st_size, sym->st_info,
+ sym_index);
}
}
}
diff --git a/x86_64-link.c b/x86_64-link.c
index 5f8c504..a526865 100644
--- a/x86_64-link.c
+++ b/x86_64-link.c
@@ -75,11 +75,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
goto plt32pc32;
case R_X86_64_PLT32:
- /* We've put the PLT slot offset into r_addend when generating
- it, and that's what we must use as relocation value (adjusted
- by section offset of course). */
- val = s1->plt->sh_addr + rel->r_addend;
- /* fallthrough. */
+ /* fallthrough: val already holds the PLT slot address */
plt32pc32:
{