GNU Binutils with patches for OS216
Revisão | b9399fcf4ec90d898a610e39bd9141e85c008fbb (tree) |
---|---|
Hora | 2017-10-10 13:16:07 |
Autor | Alan Modra <amodra@gmai...> |
Commiter | Alan Modra |
Prepare powerpc64 for late check_relocs
check_relocs was setting up some data used by the --gc-sections
gc_mark_hook. If we change ld to run check_relocs after gc_sections
that data needs to be set up elsewhere. Done by this patch in the
backend check_directives function (ppc64_elf_before_check_relocs).
* elf64-ppc.c (ppc64_elf_before_check_relocs): Set sec_type for
.opd whenever .opd is present and non-zero size. Move code
setting abiversion to/from output file earlier. Only set
u.opd.func_sec when --gc-sections. Read relocs and set up
u.opd.func_sec values here..
(ppc64_elf_check_relocs): ..rather than here. Simplify opd
section tests.
(ppc64_elf_edit_opd): Don't set sec_type for .opd here.
@@ -1,3 +1,14 @@ | ||
1 | +2017-10-10 Alan Modra <amodra@gmail.com> | |
2 | + | |
3 | + * elf64-ppc.c (ppc64_elf_before_check_relocs): Set sec_type for | |
4 | + .opd whenever .opd is present and non-zero size. Move code | |
5 | + setting abiversion to/from output file earlier. Only set | |
6 | + u.opd.func_sec when --gc-sections. Read relocs and set up | |
7 | + u.opd.func_sec values here.. | |
8 | + (ppc64_elf_check_relocs): ..rather than here. Simplify opd | |
9 | + section tests. | |
10 | + (ppc64_elf_edit_opd): Don't set sec_type for .opd here. | |
11 | + | |
1 | 12 | 2017-10-09 H.J. Lu <hongjiu.lu@intel.com> |
2 | 13 | |
3 | 14 | * elf-m10300.c (mn10300_elf_check_relocs): Don't free cached |
@@ -5182,6 +5182,9 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info) | ||
5182 | 5182 | |
5183 | 5183 | if (opd != NULL && opd->size != 0) |
5184 | 5184 | { |
5185 | + BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal); | |
5186 | + ppc64_elf_section_data (opd)->sec_type = sec_opd; | |
5187 | + | |
5185 | 5188 | if (abiversion (ibfd) == 0) |
5186 | 5189 | set_abiversion (ibfd, 1); |
5187 | 5190 | else if (abiversion (ibfd) >= 2) |
@@ -5193,48 +5196,84 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info) | ||
5193 | 5196 | bfd_set_error (bfd_error_bad_value); |
5194 | 5197 | return FALSE; |
5195 | 5198 | } |
5199 | + } | |
5196 | 5200 | |
5197 | - if ((ibfd->flags & DYNAMIC) == 0 | |
5198 | - && (opd->flags & SEC_RELOC) != 0 | |
5199 | - && opd->reloc_count != 0 | |
5200 | - && !bfd_is_abs_section (opd->output_section)) | |
5201 | - { | |
5202 | - /* Garbage collection needs some extra help with .opd sections. | |
5203 | - We don't want to necessarily keep everything referenced by | |
5204 | - relocs in .opd, as that would keep all functions. Instead, | |
5205 | - if we reference an .opd symbol (a function descriptor), we | |
5206 | - want to keep the function code symbol's section. This is | |
5207 | - easy for global symbols, but for local syms we need to keep | |
5208 | - information about the associated function section. */ | |
5209 | - bfd_size_type amt; | |
5210 | - asection **opd_sym_map; | |
5211 | - | |
5212 | - amt = OPD_NDX (opd->size) * sizeof (*opd_sym_map); | |
5213 | - opd_sym_map = bfd_zalloc (ibfd, amt); | |
5214 | - if (opd_sym_map == NULL) | |
5215 | - return FALSE; | |
5216 | - ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map; | |
5217 | - BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal); | |
5218 | - ppc64_elf_section_data (opd)->sec_type = sec_opd; | |
5219 | - } | |
5201 | + if (is_ppc64_elf (info->output_bfd)) | |
5202 | + { | |
5203 | + /* For input files without an explicit abiversion in e_flags | |
5204 | + we should have flagged any with symbol st_other bits set | |
5205 | + as ELFv1 and above flagged those with .opd as ELFv2. | |
5206 | + Set the output abiversion if not yet set, and for any input | |
5207 | + still ambiguous, take its abiversion from the output. | |
5208 | + Differences in ABI are reported later. */ | |
5209 | + if (abiversion (info->output_bfd) == 0) | |
5210 | + set_abiversion (info->output_bfd, abiversion (ibfd)); | |
5211 | + else if (abiversion (ibfd) == 0) | |
5212 | + set_abiversion (ibfd, abiversion (info->output_bfd)); | |
5220 | 5213 | } |
5221 | 5214 | |
5222 | - if (!is_ppc64_elf (info->output_bfd)) | |
5223 | - return TRUE; | |
5224 | 5215 | htab = ppc_hash_table (info); |
5225 | 5216 | if (htab == NULL) |
5226 | - return FALSE; | |
5217 | + return TRUE; | |
5218 | + | |
5219 | + if (opd != NULL && opd->size != 0 | |
5220 | + && (ibfd->flags & DYNAMIC) == 0 | |
5221 | + && (opd->flags & SEC_RELOC) != 0 | |
5222 | + && opd->reloc_count != 0 | |
5223 | + && !bfd_is_abs_section (opd->output_section) | |
5224 | + && info->gc_sections) | |
5225 | + { | |
5226 | + /* Garbage collection needs some extra help with .opd sections. | |
5227 | + We don't want to necessarily keep everything referenced by | |
5228 | + relocs in .opd, as that would keep all functions. Instead, | |
5229 | + if we reference an .opd symbol (a function descriptor), we | |
5230 | + want to keep the function code symbol's section. This is | |
5231 | + easy for global symbols, but for local syms we need to keep | |
5232 | + information about the associated function section. */ | |
5233 | + bfd_size_type amt; | |
5234 | + asection **opd_sym_map; | |
5235 | + Elf_Internal_Shdr *symtab_hdr; | |
5236 | + Elf_Internal_Rela *relocs, *rel_end, *rel; | |
5237 | + | |
5238 | + amt = OPD_NDX (opd->size) * sizeof (*opd_sym_map); | |
5239 | + opd_sym_map = bfd_zalloc (ibfd, amt); | |
5240 | + if (opd_sym_map == NULL) | |
5241 | + return FALSE; | |
5242 | + ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map; | |
5243 | + relocs = _bfd_elf_link_read_relocs (ibfd, opd, NULL, NULL, | |
5244 | + info->keep_memory); | |
5245 | + if (relocs == NULL) | |
5246 | + return FALSE; | |
5247 | + symtab_hdr = &elf_symtab_hdr (ibfd); | |
5248 | + rel_end = relocs + opd->reloc_count - 1; | |
5249 | + for (rel = relocs; rel < rel_end; rel++) | |
5250 | + { | |
5251 | + enum elf_ppc64_reloc_type r_type = ELF64_R_TYPE (rel->r_info); | |
5252 | + unsigned long r_symndx = ELF64_R_SYM (rel->r_info); | |
5253 | + | |
5254 | + if (r_type == R_PPC64_ADDR64 | |
5255 | + && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC | |
5256 | + && r_symndx < symtab_hdr->sh_info) | |
5257 | + { | |
5258 | + Elf_Internal_Sym *isym; | |
5259 | + asection *s; | |
5227 | 5260 | |
5228 | - /* For input files without an explicit abiversion in e_flags | |
5229 | - we should have flagged any with symbol st_other bits set | |
5230 | - as ELFv1 and above flagged those with .opd as ELFv2. | |
5231 | - Set the output abiversion if not yet set, and for any input | |
5232 | - still ambiguous, take its abiversion from the output. | |
5233 | - Differences in ABI are reported later. */ | |
5234 | - if (abiversion (info->output_bfd) == 0) | |
5235 | - set_abiversion (info->output_bfd, abiversion (ibfd)); | |
5236 | - else if (abiversion (ibfd) == 0) | |
5237 | - set_abiversion (ibfd, abiversion (info->output_bfd)); | |
5261 | + isym = bfd_sym_from_r_symndx (&htab->sym_cache, ibfd, r_symndx); | |
5262 | + if (isym == NULL) | |
5263 | + { | |
5264 | + if (elf_section_data (opd)->relocs != relocs) | |
5265 | + free (relocs); | |
5266 | + return FALSE; | |
5267 | + } | |
5268 | + | |
5269 | + s = bfd_section_from_elf_index (ibfd, isym->st_shndx); | |
5270 | + if (s != NULL && s != opd) | |
5271 | + opd_sym_map[OPD_NDX (rel->r_offset)] = s; | |
5272 | + } | |
5273 | + } | |
5274 | + if (elf_section_data (opd)->relocs != relocs) | |
5275 | + free (relocs); | |
5276 | + } | |
5238 | 5277 | |
5239 | 5278 | p = &htab->dot_syms; |
5240 | 5279 | while ((eh = *p) != NULL) |
@@ -5397,8 +5436,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, | ||
5397 | 5436 | const Elf_Internal_Rela *rel; |
5398 | 5437 | const Elf_Internal_Rela *rel_end; |
5399 | 5438 | asection *sreloc; |
5400 | - asection **opd_sym_map; | |
5401 | 5439 | struct elf_link_hash_entry *tga, *dottga; |
5440 | + bfd_boolean is_opd; | |
5402 | 5441 | |
5403 | 5442 | if (bfd_link_relocatable (info)) |
5404 | 5443 | return TRUE; |
@@ -5425,11 +5464,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, | ||
5425 | 5464 | symtab_hdr = &elf_symtab_hdr (abfd); |
5426 | 5465 | sym_hashes = elf_sym_hashes (abfd); |
5427 | 5466 | sreloc = NULL; |
5428 | - opd_sym_map = NULL; | |
5429 | - if (ppc64_elf_section_data (sec) != NULL | |
5430 | - && ppc64_elf_section_data (sec)->sec_type == sec_opd) | |
5431 | - opd_sym_map = ppc64_elf_section_data (sec)->u.opd.func_sec; | |
5432 | - | |
5467 | + is_opd = ppc64_elf_section_data (sec)->sec_type == sec_opd; | |
5433 | 5468 | rel_end = relocs + sec->reloc_count; |
5434 | 5469 | for (rel = relocs; rel < rel_end; rel++) |
5435 | 5470 | { |
@@ -5857,26 +5892,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, | ||
5857 | 5892 | goto dodyn; |
5858 | 5893 | |
5859 | 5894 | case R_PPC64_ADDR64: |
5860 | - if (opd_sym_map != NULL | |
5895 | + if (is_opd | |
5861 | 5896 | && rel + 1 < rel_end |
5862 | 5897 | && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC) |
5863 | 5898 | { |
5864 | 5899 | if (h != NULL) |
5865 | 5900 | ((struct ppc_link_hash_entry *) h)->is_func = 1; |
5866 | - else | |
5867 | - { | |
5868 | - asection *s; | |
5869 | - Elf_Internal_Sym *isym; | |
5870 | - | |
5871 | - isym = bfd_sym_from_r_symndx (&htab->sym_cache, | |
5872 | - abfd, r_symndx); | |
5873 | - if (isym == NULL) | |
5874 | - return FALSE; | |
5875 | - | |
5876 | - s = bfd_section_from_elf_index (abfd, isym->st_shndx); | |
5877 | - if (s != NULL && s != sec) | |
5878 | - opd_sym_map[OPD_NDX (rel->r_offset)] = s; | |
5879 | - } | |
5880 | 5901 | } |
5881 | 5902 | /* Fall through. */ |
5882 | 5903 |
@@ -5916,7 +5937,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, | ||
5916 | 5937 | h->non_got_ref = 1; |
5917 | 5938 | |
5918 | 5939 | /* Don't propagate .opd relocs. */ |
5919 | - if (NO_OPD_RELOCS && opd_sym_map != NULL) | |
5940 | + if (NO_OPD_RELOCS && is_opd) | |
5920 | 5941 | break; |
5921 | 5942 | |
5922 | 5943 | /* If we are creating a shared library, and this is a reloc |
@@ -8116,7 +8137,6 @@ ppc64_elf_edit_opd (struct bfd_link_info *info) | ||
8116 | 8137 | opd->adjust = bfd_zalloc (sec->owner, amt); |
8117 | 8138 | if (opd->adjust == NULL) |
8118 | 8139 | return FALSE; |
8119 | - ppc64_elf_section_data (sec)->sec_type = sec_opd; | |
8120 | 8140 | |
8121 | 8141 | /* This seems a waste of time as input .opd sections are all |
8122 | 8142 | zeros as generated by gcc, but I suppose there's no reason |