From 209f668ef256fe2cfd18c64737ed89182383f11f Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 28 May 2001 11:57:54 +0000 Subject: [PATCH] Handle MIPS64 relocs which use a non-1 valued int_rels_per_ext_rel --- bfd/ChangeLog | 11 +++ bfd/elflink.h | 193 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 149 insertions(+), 55 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 766e0f0d59..1ba25f5305 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2001-05-28 Thiemo Seufer + + src/bfd/ChangeLog + * elflink.h (elf_link_size_reloc_section): Use bfd_zmalloc instead of + a zeroing loop. + (elf_link_output_relocs): Handle MIPS ELF64 relocations correctly. + (elf_link_input_bfd): Likewise. + (elf_reloc_link_order): Likewise. + (elf_finish_pointer_linker_section): Typo. Handle MIPS ELF64 + relocations correctly. + 2001-05-28 Nicolas Pitre * elf32-arm.h: fix PLT generation for big endian ARM diff --git a/bfd/elflink.h b/bfd/elflink.h index 0f5c712520..db1c59375f 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -4108,7 +4108,6 @@ elf_link_size_reloc_section (abfd, rel_hdr, o) Elf_Internal_Shdr *rel_hdr; asection *o; { - register struct elf_link_hash_entry **p, **pend; unsigned reloc_count; /* Figure out how many relocations there will be. */ @@ -4132,16 +4131,15 @@ elf_link_size_reloc_section (abfd, rel_hdr, o) first time we are called. */ if (elf_section_data (o)->rel_hashes == NULL) { + struct elf_link_hash_entry **p; + p = ((struct elf_link_hash_entry **) - bfd_malloc (o->reloc_count - * sizeof (struct elf_link_hash_entry *))); + bfd_zmalloc (o->reloc_count + * sizeof (struct elf_link_hash_entry *))); if (p == NULL && o->reloc_count != 0) return false; elf_section_data (o)->rel_hashes = p; - pend = p + o->reloc_count; - for (; p < pend; p++) - *p = NULL; } return true; @@ -4161,6 +4159,24 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash) { unsigned int i; struct elf_backend_data *bed = get_elf_backend_data (abfd); + Elf_Internal_Rel *irel; + Elf_Internal_Rela *irela; + + irel = (Elf_Internal_Rel *) bfd_zmalloc (sizeof (Elf_Internal_Rel) + * bed->s->int_rels_per_ext_rel); + if (irel == NULL) + { + (*_bfd_error_handler) (_("Error: out of memory")); + abort (); + } + + irela = (Elf_Internal_Rela *) bfd_zmalloc (sizeof (Elf_Internal_Rela) + * bed->s->int_rels_per_ext_rel); + if (irela == NULL) + { + (*_bfd_error_handler) (_("Error: out of memory")); + abort (); + } for (i = 0; i < count; i++, rel_hash++) { @@ -4172,41 +4188,50 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash) if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) { Elf_External_Rel *erel; - Elf_Internal_Rel irel; + unsigned int j; erel = (Elf_External_Rel *) rel_hdr->contents + i; if (bed->s->swap_reloc_in) - (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &irel); + (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, irel); else - elf_swap_reloc_in (abfd, erel, &irel); - irel.r_info = ELF_R_INFO ((*rel_hash)->indx, - ELF_R_TYPE (irel.r_info)); + elf_swap_reloc_in (abfd, erel, irel); + + for (j = 0; j < bed->s->int_rels_per_ext_rel; j++) + irel[j].r_info = ELF_R_INFO ((*rel_hash)->indx, + ELF_R_TYPE (irel[j].r_info)); + if (bed->s->swap_reloc_out) - (*bed->s->swap_reloc_out) (abfd, &irel, (bfd_byte *) erel); + (*bed->s->swap_reloc_out) (abfd, irel, (bfd_byte *) erel); else - elf_swap_reloc_out (abfd, &irel, erel); + elf_swap_reloc_out (abfd, irel, erel); } else { Elf_External_Rela *erela; - Elf_Internal_Rela irela; + unsigned int j; BFD_ASSERT (rel_hdr->sh_entsize == sizeof (Elf_External_Rela)); erela = (Elf_External_Rela *) rel_hdr->contents + i; if (bed->s->swap_reloca_in) - (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, &irela); + (*bed->s->swap_reloca_in) (abfd, (bfd_byte *) erela, irela); else - elf_swap_reloca_in (abfd, erela, &irela); - irela.r_info = ELF_R_INFO ((*rel_hash)->indx, - ELF_R_TYPE (irela.r_info)); + elf_swap_reloca_in (abfd, erela, irela); + + for (j = 0; j < bed->s->int_rels_per_ext_rel; j++) + irela[j].r_info = ELF_R_INFO ((*rel_hash)->indx, + ELF_R_TYPE (irela[j].r_info)); + if (bed->s->swap_reloca_out) - (*bed->s->swap_reloca_out) (abfd, &irela, (bfd_byte *) erela); + (*bed->s->swap_reloca_out) (abfd, irela, (bfd_byte *) erela); else - elf_swap_reloca_out (abfd, &irela, erela); + elf_swap_reloca_out (abfd, irela, erela); } } + + free (irel); + free (irela); } /* Do the final step of an ELF link. */ @@ -5440,33 +5465,50 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr, bed = get_elf_backend_data (output_bfd); irela = internal_relocs; - irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr); + irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr) + * bed->s->int_rels_per_ext_rel; + if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) { Elf_External_Rel *erel; + Elf_Internal_Rel *irel; + + irel = (Elf_Internal_Rel *) bfd_zmalloc (bed->s->int_rels_per_ext_rel + * sizeof (Elf_Internal_Rel)); + if (irel == NULL) + { + (*_bfd_error_handler) (_("Error: out of memory")); + abort (); + } erel = ((Elf_External_Rel *) output_rel_hdr->contents + *rel_countp); - for (; irela < irelaend; irela++, erel++) + for (; irela < irelaend; irela += bed->s->int_rels_per_ext_rel, erel++) { - Elf_Internal_Rel irel; + unsigned char i; + + for (i = 0; i < bed->s->int_rels_per_ext_rel; i++) + { + irel[i].r_offset = irela[i].r_offset; + irel[i].r_info = irela[i].r_info; + BFD_ASSERT (irela[i].r_addend == 0); + } - irel.r_offset = irela->r_offset; - irel.r_info = irela->r_info; - BFD_ASSERT (irela->r_addend == 0); if (bed->s->swap_reloc_out) - (*bed->s->swap_reloc_out) (output_bfd, &irel, (PTR) erel); + (*bed->s->swap_reloc_out) (output_bfd, irel, (PTR) erel); else - elf_swap_reloc_out (output_bfd, &irel, erel); + elf_swap_reloc_out (output_bfd, irel, erel); } + + free (irel); } else { Elf_External_Rela *erela; - BFD_ASSERT (input_rel_hdr->sh_entsize - == sizeof (Elf_External_Rela)); + BFD_ASSERT (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rela)); + erela = ((Elf_External_Rela *) output_rel_hdr->contents + *rel_countp); - for (; irela < irelaend; irela++, erela++) + for (; irela < irelaend; irela += bed->s->int_rels_per_ext_rel, erela++) if (bed->s->swap_reloca_out) (*bed->s->swap_reloca_out) (output_bfd, irela, (PTR) erela); else @@ -5798,21 +5840,28 @@ elf_link_input_bfd (finfo, input_bfd) Elf_Internal_Rela *irelaend; struct elf_link_hash_entry **rel_hash; Elf_Internal_Shdr *input_rel_hdr; + unsigned char next_erel; /* Adjust the reloc addresses and symbol indices. */ irela = internal_relocs; - irelaend = - irela + o->reloc_count * bed->s->int_rels_per_ext_rel; + irelaend = irela + + o->reloc_count * bed->s->int_rels_per_ext_rel; rel_hash = (elf_section_data (o->output_section)->rel_hashes + elf_section_data (o->output_section)->rel_count + elf_section_data (o->output_section)->rel_count2); - for (; irela < irelaend; irela++, rel_hash++) + for (next_erel = 0; irela < irelaend; irela++, next_erel++) { unsigned long r_symndx; Elf_Internal_Sym *isym; asection *sec; + if (next_erel == bed->s->int_rels_per_ext_rel) + { + rel_hash++; + next_erel = 0; + } + irela->r_offset += o->output_offset; /* Relocs in an executable have to be virtual addresses. */ @@ -5829,7 +5878,7 @@ elf_link_input_bfd (finfo, input_bfd) && finfo->sections[r_symndx] == NULL)) { struct elf_link_hash_entry *rh; - long indx; + unsigned long indx; /* This is a reloc against a global symbol. We have not yet output all the local symbols, so @@ -5937,7 +5986,8 @@ elf_link_input_bfd (finfo, input_bfd) elf_link_output_relocs (output_bfd, o, input_rel_hdr, internal_relocs); - internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr); + internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr) + * bed->s->int_rels_per_ext_rel; input_rel_hdr = elf_section_data (o)->rel_hdr2; if (input_rel_hdr) elf_link_output_relocs (output_bfd, o, @@ -6110,32 +6160,52 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order) if (rel_hdr->sh_type == SHT_REL) { - Elf_Internal_Rel irel; + Elf_Internal_Rel *irel; Elf_External_Rel *erel; + unsigned char i; + + irel = (Elf_Internal_Rel *) bfd_zmalloc (bed->s->int_rels_per_ext_rel + * sizeof (Elf_Internal_Rel)); + if (irel == NULL) + return false; + + for (i = 0; i < bed->s->int_rels_per_ext_rel; i++) + irel[i].r_offset = offset; + irel[0].r_info = ELF_R_INFO (indx, howto->type); - irel.r_offset = offset; - irel.r_info = ELF_R_INFO (indx, howto->type); erel = ((Elf_External_Rel *) rel_hdr->contents + elf_section_data (output_section)->rel_count); + if (bed->s->swap_reloc_out) - (*bed->s->swap_reloc_out) (output_bfd, &irel, (bfd_byte *) erel); + (*bed->s->swap_reloc_out) (output_bfd, irel, (bfd_byte *) erel); else - elf_swap_reloc_out (output_bfd, &irel, erel); + elf_swap_reloc_out (output_bfd, irel, erel); + + free (irel); } else { - Elf_Internal_Rela irela; + Elf_Internal_Rela *irela; Elf_External_Rela *erela; + unsigned char i; + + irela = (Elf_Internal_Rela *) bfd_zmalloc (bed->s->int_rels_per_ext_rel + * sizeof (Elf_Internal_Rela)); + if (irela == NULL) + return false; + + for (i = 0; i < bed->s->int_rels_per_ext_rel; i++) + irela[i].r_offset = offset; + irela[0].r_info = ELF_R_INFO (indx, howto->type); + irela[0].r_addend = addend; - irela.r_offset = offset; - irela.r_info = ELF_R_INFO (indx, howto->type); - irela.r_addend = addend; erela = ((Elf_External_Rela *) rel_hdr->contents + elf_section_data (output_section)->rel_count); + if (bed->s->swap_reloca_out) - (*bed->s->swap_reloca_out) (output_bfd, &irela, (bfd_byte *) erela); + (*bed->s->swap_reloca_out) (output_bfd, irela, (bfd_byte *) erela); else - elf_swap_reloca_out (output_bfd, &irela, erela); + elf_swap_reloca_out (output_bfd, irela, erela); } ++elf_section_data (output_section)->rel_count; @@ -6272,7 +6342,7 @@ elf_create_pointer_linker_section (abfd, info, lsect, h, rel) #define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_32 (BFD, VAL, ADDR) #endif -/* Fill in the address for a pointer generated in alinker section. */ +/* Fill in the address for a pointer generated in a linker section. */ bfd_vma elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, relocation, rel, relative_reloc) @@ -6339,7 +6409,17 @@ elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, reloca if (info->shared) { asection *srel = lsect->rel_section; - Elf_Internal_Rela outrel; + Elf_Internal_Rela *outrel; + struct elf_backend_data *bed = get_elf_backend_data (output_bfd); + unsigned int i; + + outrel = (Elf_Internal_Rela *) bfd_zmalloc (sizeof (Elf_Internal_Rela) + * bed->s->int_rels_per_ext_rel); + if (outrel == NULL) + { + (*_bfd_error_handler) (_("Error: out of memory")); + return 0; + } /* We need to generate a relative reloc for the dynamic linker. */ if (!srel) @@ -6348,16 +6428,19 @@ elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, reloca BFD_ASSERT (srel != NULL); - outrel.r_offset = (lsect->section->output_section->vma - + lsect->section->output_offset - + linker_section_ptr->offset); - outrel.r_info = ELF_R_INFO (0, relative_reloc); - outrel.r_addend = 0; - elf_swap_reloca_out (output_bfd, &outrel, + for (i = 0; i < bed->s->int_rels_per_ext_rel; i++) + outrel[i].r_offset = (lsect->section->output_section->vma + + lsect->section->output_offset + + linker_section_ptr->offset); + outrel[0].r_info = ELF_R_INFO (0, relative_reloc); + outrel[0].r_addend = 0; + elf_swap_reloca_out (output_bfd, outrel, (((Elf_External_Rela *) lsect->section->contents) + elf_section_data (lsect->section)->rel_count)); ++elf_section_data (lsect->section)->rel_count; + + free (outrel); } } }