Some symbol (such as __gmon_start__ but this one does not matter to tcc) can have both a R_386_GOT32 and R_386_PLT32 relocation. It is thus not enough to test if a GOT reloc was already done when deciding whether to return early from put_got_entry.
Unified · Split
| @@ -1008,7 +1008,7 @@ static void put_got_entry(TCCState *s1, · 1007 unmodified lines | ||
| 1008 | 1008 | int reloc_type, unsigned long size, int info, |
| 1009 | 1009 | int sym_index) |
| 1010 | 1010 | { |
| 1011 | − int index; | |
| 1011 | + int index, need_plt_entry, got_entry_present = 0; | |
| 1012 | 1012 | const char *name; |
| 1013 | 1013 | ElfW(Sym) *sym; |
| 1014 | 1014 | unsigned long offset; |
| @@ -1017,25 +1017,38 @@ static void put_got_entry(TCCState *s1, · 2 unmodified lines | ||
| 1017 | 1017 | if (!s1->got) |
| 1018 | 1018 | build_got(s1); |
| 1019 | 1019 | |
| 1020 | + need_plt_entry = s1->dynsym && | |
| 1021 | +#ifdef TCC_TARGET_X86_64 | |
| 1022 | + (reloc_type == R_X86_64_JUMP_SLOT); | |
| 1023 | +#elif defined(TCC_TARGET_I386) | |
| 1024 | + (reloc_type == R_386_JMP_SLOT); | |
| 1025 | +#elif defined(TCC_TARGET_ARM) | |
| 1026 | + (reloc_type == R_ARM_JUMP_SLOT); | |
| 1027 | +#else | |
| 1028 | + 0; | |
| 1029 | +#endif | |
| 1030 | + | |
| 1020 | 1031 | /* if a got entry already exists for that symbol, no need to add one */ |
| 1021 | 1032 | if (sym_index < s1->nb_sym_attrs && |
| 1022 | − s1->sym_attrs[sym_index].got_offset) | |
| 1023 | − return; | |
| 1033 | + s1->sym_attrs[sym_index].got_offset) { | |
| 1034 | + if (!need_plt_entry) | |
| 1035 | + return; | |
| 1036 | + else | |
| 1037 | + got_entry_present = 1; | |
| 1038 | + } | |
| 1024 | 1039 | |
| 1025 | 1040 | alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset; |
| 1026 | 1041 | |
| 1027 | 1042 | if (s1->dynsym) { |
| 1028 | 1043 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 1029 | 1044 | name = (char *) symtab_section->link->data + sym->st_name; |
| 1045 | + if (!find_elf_sym(s1->dynsym, name)) | |
| 1046 | + need_plt_entry = 1; | |
| 1047 | + else | |
| 1048 | + return; | |
| 1030 | 1049 | offset = sym->st_value; |
| 1031 | 1050 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
| 1032 | − if (reloc_type == | |
| 1033 | −#ifdef TCC_TARGET_X86_64 | |
| 1034 | − R_X86_64_JUMP_SLOT | |
| 1035 | −#else | |
| 1036 | − R_386_JMP_SLOT | |
| 1037 | −#endif | |
| 1038 | − ) { | |
| 1051 | + if (need_plt_entry) { | |
| 1039 | 1052 | Section *plt; |
| 1040 | 1053 | uint8_t *p; |
| 1041 | 1054 | int modrm; |
| @@ -1080,7 +1093,7 @@ static void put_got_entry(TCCState *s1, · 38 unmodified lines | ||
| 1080 | 1093 | offset = plt->data_offset - 16; |
| 1081 | 1094 | } |
| 1082 | 1095 | #elif defined(TCC_TARGET_ARM) |
| 1083 | − if (reloc_type == R_ARM_JUMP_SLOT) { | |
| 1096 | + if (need_plt_entry) { | |
| 1084 | 1097 | Section *plt; |
| 1085 | 1098 | uint8_t *p; |
| 1086 | 1099 | |
| @@ -1123,6 +1136,13 @@ static void put_got_entry(TCCState *s1, · 36 unmodified lines | ||
| 1123 | 1136 | #endif |
| 1124 | 1137 | index = put_elf_sym(s1->dynsym, offset, |
| 1125 | 1138 | size, info, 0, sym->st_shndx, name); |
| 1139 | + if (got_entry_present) { | |
| 1140 | + put_elf_reloc(s1->dynsym, s1->got, | |
| 1141 | + s1->sym_attrs[sym_index].got_offset, | |
| 1142 | + reloc_type, index); | |
| 1143 | + return; | |
| 1144 | + } | |
| 1145 | + | |
| 1126 | 1146 | /* put a got entry */ |
| 1127 | 1147 | put_elf_reloc(s1->dynsym, s1->got, |
| 1128 | 1148 | s1->got->data_offset, |