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 | int reloc_type, unsigned long size, int info, | 1008 | int reloc_type, unsigned long size, int info, |
| 1009 | int sym_index) | 1009 | int sym_index) |
| 1010 | { | 1010 | { |
| 1011 | int index; | 1011 | int index, need_plt_entry, got_entry_present = 0; |
| 1012 | const char *name; | 1012 | const char *name; |
| 1013 | ElfW(Sym) *sym; | 1013 | ElfW(Sym) *sym; |
| 1014 | unsigned long offset; | 1014 | unsigned long offset; |
| @@ -1017,25 +1017,38 @@ static void put_got_entry(TCCState *s1, · 2 unmodified lines | |||
| 1017 | if (!s1->got) | 1017 | if (!s1->got) |
| 1018 | build_got(s1); | 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 | /* if a got entry already exists for that symbol, no need to add one */ | 1031 | /* if a got entry already exists for that symbol, no need to add one */ |
| 1021 | if (sym_index < s1->nb_sym_attrs && | 1032 | if (sym_index < s1->nb_sym_attrs && |
| 1022 | s1->sym_attrs[sym_index].got_offset) | 1033 | s1->sym_attrs[sym_index].got_offset) { |
| 1023 | return; | 1034 | if (!need_plt_entry) |
| 1035 | return; | ||
| 1036 | else | ||
| 1037 | got_entry_present = 1; | ||
| 1038 | } | ||
| 1024 | 1039 | ||
| 1025 | alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset; | 1040 | alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset; |
| 1026 | 1041 | ||
| 1027 | if (s1->dynsym) { | 1042 | if (s1->dynsym) { |
| 1028 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | 1043 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 1029 | name = (char *) symtab_section->link->data + sym->st_name; | 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 | offset = sym->st_value; | 1049 | offset = sym->st_value; |
| 1031 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) | 1050 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
| 1032 | if (reloc_type == | 1051 | if (need_plt_entry) { |
| 1033 | #ifdef TCC_TARGET_X86_64 | ||
| 1034 | R_X86_64_JUMP_SLOT | ||
| 1035 | #else | ||
| 1036 | R_386_JMP_SLOT | ||
| 1037 | #endif | ||
| 1038 | ) { | ||
| 1039 | Section *plt; | 1052 | Section *plt; |
| 1040 | uint8_t *p; | 1053 | uint8_t *p; |
| 1041 | int modrm; | 1054 | int modrm; |
| @@ -1080,7 +1093,7 @@ static void put_got_entry(TCCState *s1, · 38 unmodified lines | |||
| 1080 | offset = plt->data_offset - 16; | 1093 | offset = plt->data_offset - 16; |
| 1081 | } | 1094 | } |
| 1082 | #elif defined(TCC_TARGET_ARM) | 1095 | #elif defined(TCC_TARGET_ARM) |
| 1083 | if (reloc_type == R_ARM_JUMP_SLOT) { | 1096 | if (need_plt_entry) { |
| 1084 | Section *plt; | 1097 | Section *plt; |
| 1085 | uint8_t *p; | 1098 | uint8_t *p; |
| 1086 | 1099 | ||
| @@ -1123,6 +1136,13 @@ static void put_got_entry(TCCState *s1, · 36 unmodified lines | |||
| 1123 | #endif | 1136 | #endif |
| 1124 | index = put_elf_sym(s1->dynsym, offset, | 1137 | index = put_elf_sym(s1->dynsym, offset, |
| 1125 | size, info, 0, sym->st_shndx, name); | 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 | /* put a got entry */ | 1146 | /* put a got entry */ |
| 1127 | put_elf_reloc(s1->dynsym, s1->got, | 1147 | put_elf_reloc(s1->dynsym, s1->got, |
| 1128 | s1->got->data_offset, | 1148 | s1->got->data_offset, |