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
43 {43 {
44 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;44 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
45 x = (*(int *) ptr) & 0xffffff;45 x = (*(int *) ptr) & 0xffffff;
46 if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_ABS)
47 val = s1->plt->sh_addr;
48#ifdef DEBUG_RELOC46#ifdef DEBUG_RELOC
49 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);47 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
50#endif48#endif
@@ -140,8 +138,6 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add · 89 unmodified lines
140 }138 }
141 139
142 /* Compute final offset */140 /* Compute final offset */
143 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
144 x -= 4;
145 x += val - addr;141 x += val - addr;
146 if (!to_thumb && is_call) {142 if (!to_thumb && is_call) {
147 blx_bit = 0; /* bl -> blx */143 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
65 return;65 return;
66 case R_AARCH64_JUMP26:66 case R_AARCH64_JUMP26:
67 case R_AARCH64_CALL26:67 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;
76#ifdef DEBUG_RELOC68#ifdef DEBUG_RELOC
77 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,69 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
78 (char *) symtab_section->link->data + sym->st_name);70 (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
654 true and output error if undefined symbol. */654 true and output error if undefined symbol. */
655ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)655ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
656{656{
657 ElfW(Sym) *sym, *esym;657 ElfW(Sym) *sym;
658 int sym_bind, sh_num, sym_index;658 int sym_bind, sh_num;
659 const char *name;659 const char *name;
660 660
661 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {661 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
676 goto found;676 goto found;
677 }677 }
678#endif678#endif
679 } else if (s1->dynsym) {679 /* if dynamic symbol exist, it will be used in relocate_section */
680 /* if dynamic symbol exist, then use it */680 } else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
681 sym_index = find_elf_sym(s1->dynsym, name);681 goto found;
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 }
688 /* XXX: _fp_hw seems to be part of the ABI, so we ignore682 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
689 it */683 it */
690 if (!strcmp(name, "_fp_hw"))684 if (!strcmp(name, "_fp_hw"))
@@ -714,7 +708,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 23 unmodified lines
714 ElfW(Sym) *sym;708 ElfW(Sym) *sym;
715 int type, sym_index;709 int type, sym_index;
716 unsigned char *ptr;710 unsigned char *ptr;
717 addr_t val, addr;711 addr_t tgt, addr;
712 struct sym_attr *symattr;
718 713
719 relocate_init(sr);714 relocate_init(sr);
720 for_each_elem(sr, 0, rel, ElfW_Rel) {715 for_each_elem(sr, 0, rel, ElfW_Rel) {
@@ -722,14 +717,22 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 1 unmodified line
722 717
723 sym_index = ELFW(R_SYM)(rel->r_info);718 sym_index = ELFW(R_SYM)(rel->r_info);
724 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];719 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;
726#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)730#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
727 val += rel->r_addend;731 tgt += rel->r_addend;
728#endif732#endif
729 type = ELFW(R_TYPE)(rel->r_info);
730 addr = s->sh_addr + rel->r_offset;733 addr = s->sh_addr + rel->r_offset;
731 734
732 relocate(s1, rel, type, ptr, addr, val);735 relocate(s1, rel, type, ptr, addr, tgt);
733 }736 }
734 /* if the relocation is allocated, we change its symbol table */737 /* if the relocation is allocated, we change its symbol table */
735 if (sr->sh_flags & SHF_ALLOC)738 if (sr->sh_flags & SHF_ALLOC)
@@ -1030,7 +1033,6 @@ ST_FUNC void build_got_entries(TCCState *s1) · 294 unmodified lines
1030 ElfW_Rel *rel;1033 ElfW_Rel *rel;
1031 ElfW(Sym) *sym;1034 ElfW(Sym) *sym;
1032 int i, type, reloc_type, sym_index;1035 int i, type, reloc_type, sym_index;
1033 unsigned long ofs;
1034 1036
1035 for(i = 1; i < s1->nb_sections; i++) {1037 for(i = 1; i < s1->nb_sections; i++) {
1036 s = s1->sections[i];1038 s = s1->sections[i];
@@ -1075,38 +1077,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 38 unmodified lines
1075 reloc_type = R_JMP_SLOT;1077 reloc_type = R_JMP_SLOT;
1076 else1078 else
1077 reloc_type = R_GLOB_DAT;1079 reloc_type = R_GLOB_DAT;
1078 ofs = put_got_entry(s1, reloc_type, type, sym->st_size,1080 put_got_entry(s1, reloc_type, type, sym->st_size, sym->st_info,
1079 sym->st_info, sym_index);1081 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
1110 }1082 }
1111 }1083 }
1112}1084}
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
75 goto plt32pc32;75 goto plt32pc32;
76 76
77 case R_X86_64_PLT32:77 case R_X86_64_PLT32:
78 /* We've put the PLT slot offset into r_addend when generating78 /* fallthrough: val already holds the PLT slot address */
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. */
83 79
84 plt32pc32:80 plt32pc32:
85 {81 {

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