History

Consolidate all relocations in relocate_section

Static relocation of functions in dynamic libraries must use the PLT entry as the target. Before this commit, it used to be done in 2 parts for ARM, with the offset of the PLT entry from the beginning of the PLT being put in the relocated place in build_got_entries () and then the address of the PLT being added in relocate_section. This led to code dealing with reading the offset of a bl instruction in build_got_entries. Furthermore, the addition of the address of the start of the PLT was done based on the relocation type which does not convey whether a PLT entry should be used to reach the symbol. This commit moves the decision to use the PLT as the target in relocate_section, therefore having the instruction aware code contained to the target-specific bit of that function (in <target>-link.c). Note that relocate_syms is *not* the right place to do this because two different relocations for the same symbol can make different decision. This is the case in tcc -run mode where the static and dynamic relocation are done by tcc. Storing the PLT entry address in the symbol's st_value field and relying on the specific relocation type being used for dynamic relocation would work but the PLT entry address would then appear in the static symbol table (symtab). This would also make the static symbol table entry differ from the dynamic symbol table entry.

Thomas Preud'homme committed 10 years ago

Commit 25927df1 parent 2c388004 files · +22 −66Browse files

Unified · Split

4 files
  1. arm-link.c +0 −4
  2. arm64-link.c +0 −8
  3. tccelf.c +21 −49
  4. x86_64-link.c +1 −5
arm-link.c+0−4
@@ -43,8 +43,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 42 unmodified lines
4343 {
4444 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
4545 x = (*(int *) ptr) & 0xffffff;
46− if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_ABS)
47− val = s1->plt->sh_addr;
4846 #ifdef DEBUG_RELOC
4947 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
5048 #endif
@@ -140,8 +138,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 89 unmodified lines
140138 }
141139
142140 /* Compute final offset */
143− if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
144− x -= 4;
145141 x += val - addr;
146142 if (!to_thumb && is_call) {
147143 blx_bit = 0; /* bl -> blx */
arm64-link.c+0−8
@@ -65,14 +65,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 64 unmodified lines
6565 return;
6666 case R_AARCH64_JUMP26:
6767 case R_AARCH64_CALL26:
68− /* This check must match the one in build_got_entries, testing
69− if we really need a PLT slot. */
70− if (sym->st_shndx == SHN_UNDEF ||
71− sym->st_shndx == SHN_ABS)
72− /* We've put the PLT slot offset into r_addend when generating
73− it, and that's what we must use as relocation value (adjusted
74− by section offset of course). */
75− val = s1->plt->sh_addr + rel->r_addend;
7668 #ifdef DEBUG_RELOC
7769 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
7870 (char *) symtab_section->link->data + sym->st_name);
tccelf.c+21−49
@@ -654,8 +654,8 @@ ST_FUNC void relocate_common_syms(void) · 653 unmodified lines
654654 true and output error if undefined symbol. */
655655 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
656656 {
657− ElfW(Sym) *sym, *esym;
658− int sym_bind, sh_num, sym_index;
657+ ElfW(Sym) *sym;
658+ int sym_bind, sh_num;
659659 const char *name;
660660
661661 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
@@ -676,15 +676,9 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) · 14 unmodified lines
676676 goto found;
677677 }
678678 #endif
679− } else if (s1->dynsym) {
680− /* if dynamic symbol exist, then use it */
681− sym_index = find_elf_sym(s1->dynsym, name);
682− if (sym_index) {
683− esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
684− sym->st_value = esym->st_value;
685− goto found;
686− }
687− }
679+ /* if dynamic symbol exist, it will be used in relocate_section */
680+ } else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
681+ goto found;
688682 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
689683 it */
690684 if (!strcmp(name, "_fp_hw"))
@@ -714,7 +708,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 23 unmodified lines
714708 ElfW(Sym) *sym;
715709 int type, sym_index;
716710 unsigned char *ptr;
717− addr_t val, addr;
711+ addr_t tgt, addr;
712+ struct sym_attr *symattr;
718713
719714 relocate_init(sr);
720715 for_each_elem(sr, 0, rel, ElfW_Rel) {
@@ -722,14 +717,22 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 1 unmodified line
722717
723718 sym_index = ELFW(R_SYM)(rel->r_info);
724719 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
725− val = sym->st_value;
720+ type = ELFW(R_TYPE)(rel->r_info);
721+ symattr = get_sym_attr(s1, sym_index, 0);
722+ tgt = sym->st_value;
723+ /* If static relocation to a dynamic symbol, relocate to PLT entry.
724+ Note 1: in tcc -run mode we go through PLT to avoid range issues
725+ Note 2: symbols compiled with libtcc and later added with
726+ tcc_add_symbol are not dynamic and thus have symattr NULL */
727+ if (relocs_info[type].gotplt_entry != NO_GOTPLT_ENTRY &&
728+ relocs_info[type].code_reloc && symattr && symattr->plt_offset)
729+ tgt = s1->plt->sh_addr + symattr->plt_offset;
726730 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
727− val += rel->r_addend;
731+ tgt += rel->r_addend;
728732 #endif
729− type = ELFW(R_TYPE)(rel->r_info);
730733 addr = s->sh_addr + rel->r_offset;
731734
732− relocate(s1, rel, type, ptr, addr, val);
735+ relocate(s1, rel, type, ptr, addr, tgt);
733736 }
734737 /* if the relocation is allocated, we change its symbol table */
735738 if (sr->sh_flags & SHF_ALLOC)
@@ -1030,7 +1033,6 @@ ST_FUNC void build_got_entries(TCCState *s1) · 294 unmodified lines
10301033 ElfW_Rel *rel;
10311034 ElfW(Sym) *sym;
10321035 int i, type, reloc_type, sym_index;
1033− unsigned long ofs;
10341036
10351037 for(i = 1; i < s1->nb_sections; i++) {
10361038 s = s1->sections[i];
@@ -1075,38 +1077,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 38 unmodified lines
10751077 reloc_type = R_JMP_SLOT;
10761078 else
10771079 reloc_type = R_GLOB_DAT;
1078− ofs = put_got_entry(s1, reloc_type, type, sym->st_size,
1079− sym->st_info, sym_index);
1080−
1081−#ifdef DEBUG_RELOC
1082− printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1083− (char *) symtab_section->link->data + sym->st_name, type,
1084− sym->st_shndx, ofs);
1085−#endif
1086−
1087−#if defined (TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
1088− /* We store the place of the generated PLT slot in our addend. */
1089− if (relocs_info[type].pltoff_addend)
1090− rel->r_addend += ofs;
1091−
1092−#elif defined (TCC_TARGET_ARM)
1093− if (type == R_ARM_PC24 || type == R_ARM_CALL ||
1094− type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
1095− addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1096− + rel->r_offset);
1097− /* x must be signed! */
1098− int x = *ptr & 0xffffff;
1099− x = (x << 8) >> 8;
1100− x <<= 2;
1101− x += ofs;
1102− x >>= 2;
1103−#ifdef DEBUG_RELOC
1104− printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1105− (*ptr & 0xff000000) | x, x);
1106−#endif
1107− *ptr = (*ptr & 0xff000000) | x;
1108− }
1109−#endif
1080+ put_got_entry(s1, reloc_type, type, sym->st_size, sym->st_info,
1081+ sym_index);
11101082 }
11111083 }
11121084 }
x86_64-link.c+1−5
@@ -75,11 +75,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 74 unmodified lines
7575 goto plt32pc32;
7676
7777 case R_X86_64_PLT32:
78− /* We've put the PLT slot offset into r_addend when generating
79− it, and that's what we must use as relocation value (adjusted
80− by section offset of course). */
81− val = s1->plt->sh_addr + rel->r_addend;
82− /* fallthrough. */
78+ /* fallthrough: val already holds the PLT slot address */
8379
8480 plt32pc32:
8581 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t