| @@ -654,8 +654,8 @@ ST_FUNC void relocate_common_syms(void) · 653 unmodified lines |
| 654 | 654 | true and output error if undefined symbol. */ |
| 655 | 655 | ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) |
| 656 | 656 | { |
| 657 | | − ElfW(Sym) *sym, *esym; |
| 658 | | − int sym_bind, sh_num, sym_index; |
| 657 | + ElfW(Sym) *sym; |
| 658 | + int sym_bind, sh_num; |
| 659 | 659 | const char *name; |
| 660 | 660 | |
| 661 | 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 | 676 | goto found; |
| 677 | 677 | } |
| 678 | 678 | #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; |
| 688 | 682 | /* XXX: _fp_hw seems to be part of the ABI, so we ignore |
| 689 | 683 | it */ |
| 690 | 684 | if (!strcmp(name, "_fp_hw")) |
| @@ -714,7 +708,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 23 unmodified lines |
| 714 | 708 | ElfW(Sym) *sym; |
| 715 | 709 | int type, sym_index; |
| 716 | 710 | unsigned char *ptr; |
| 717 | | − addr_t val, addr; |
| 711 | + addr_t tgt, addr; |
| 712 | + struct sym_attr *symattr; |
| 718 | 713 | |
| 719 | 714 | relocate_init(sr); |
| 720 | 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 | 718 | sym_index = ELFW(R_SYM)(rel->r_info); |
| 724 | 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 | 730 | #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) |
| 727 | | − val += rel->r_addend; |
| 731 | + tgt += rel->r_addend; |
| 728 | 732 | #endif |
| 729 | | − type = ELFW(R_TYPE)(rel->r_info); |
| 730 | 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 | 737 | /* if the relocation is allocated, we change its symbol table */ |
| 735 | 738 | if (sr->sh_flags & SHF_ALLOC) |
| @@ -1030,7 +1033,6 @@ ST_FUNC void build_got_entries(TCCState *s1) · 294 unmodified lines |
| 1030 | 1033 | ElfW_Rel *rel; |
| 1031 | 1034 | ElfW(Sym) *sym; |
| 1032 | 1035 | int i, type, reloc_type, sym_index; |
| 1033 | | − unsigned long ofs; |
| 1034 | 1036 | |
| 1035 | 1037 | for(i = 1; i < s1->nb_sections; i++) { |
| 1036 | 1038 | s = s1->sections[i]; |
| @@ -1075,38 +1077,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 38 unmodified lines |
| 1075 | 1077 | reloc_type = R_JMP_SLOT; |
| 1076 | 1078 | else |
| 1077 | 1079 | 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); |
| 1110 | 1082 | } |
| 1111 | 1083 | } |
| 1112 | 1084 | } |