Handle MIPS64 relocs which use a non-1 valued int_rels_per_ext_rel

This commit is contained in:
Nick Clifton 2001-05-28 11:57:54 +00:00
parent 1e329ce6ac
commit 209f668ef2
2 changed files with 149 additions and 55 deletions

View File

@ -1,3 +1,14 @@
2001-05-28 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
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 <nico@cam.org> 2001-05-28 Nicolas Pitre <nico@cam.org>
* elf32-arm.h: fix PLT generation for big endian ARM * elf32-arm.h: fix PLT generation for big endian ARM

View File

@ -4108,7 +4108,6 @@ elf_link_size_reloc_section (abfd, rel_hdr, o)
Elf_Internal_Shdr *rel_hdr; Elf_Internal_Shdr *rel_hdr;
asection *o; asection *o;
{ {
register struct elf_link_hash_entry **p, **pend;
unsigned reloc_count; unsigned reloc_count;
/* Figure out how many relocations there will be. */ /* 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. */ first time we are called. */
if (elf_section_data (o)->rel_hashes == NULL) if (elf_section_data (o)->rel_hashes == NULL)
{ {
struct elf_link_hash_entry **p;
p = ((struct elf_link_hash_entry **) p = ((struct elf_link_hash_entry **)
bfd_malloc (o->reloc_count bfd_zmalloc (o->reloc_count
* sizeof (struct elf_link_hash_entry *))); * sizeof (struct elf_link_hash_entry *)));
if (p == NULL && o->reloc_count != 0) if (p == NULL && o->reloc_count != 0)
return false; return false;
elf_section_data (o)->rel_hashes = p; elf_section_data (o)->rel_hashes = p;
pend = p + o->reloc_count;
for (; p < pend; p++)
*p = NULL;
} }
return true; return true;
@ -4161,6 +4159,24 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash)
{ {
unsigned int i; unsigned int i;
struct elf_backend_data *bed = get_elf_backend_data (abfd); 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++) 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)) if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
{ {
Elf_External_Rel *erel; Elf_External_Rel *erel;
Elf_Internal_Rel irel; unsigned int j;
erel = (Elf_External_Rel *) rel_hdr->contents + i; erel = (Elf_External_Rel *) rel_hdr->contents + i;
if (bed->s->swap_reloc_in) 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 else
elf_swap_reloc_in (abfd, erel, &irel); elf_swap_reloc_in (abfd, erel, irel);
irel.r_info = ELF_R_INFO ((*rel_hash)->indx,
ELF_R_TYPE (irel.r_info)); 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) 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 else
elf_swap_reloc_out (abfd, &irel, erel); elf_swap_reloc_out (abfd, irel, erel);
} }
else else
{ {
Elf_External_Rela *erela; Elf_External_Rela *erela;
Elf_Internal_Rela irela; unsigned int j;
BFD_ASSERT (rel_hdr->sh_entsize BFD_ASSERT (rel_hdr->sh_entsize
== sizeof (Elf_External_Rela)); == sizeof (Elf_External_Rela));
erela = (Elf_External_Rela *) rel_hdr->contents + i; erela = (Elf_External_Rela *) rel_hdr->contents + i;
if (bed->s->swap_reloca_in) 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 else
elf_swap_reloca_in (abfd, erela, &irela); elf_swap_reloca_in (abfd, erela, irela);
irela.r_info = ELF_R_INFO ((*rel_hash)->indx,
ELF_R_TYPE (irela.r_info)); 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) 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 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. */ /* 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); bed = get_elf_backend_data (output_bfd);
irela = internal_relocs; 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)) if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
{ {
Elf_External_Rel *erel; 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); 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) 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 else
elf_swap_reloc_out (output_bfd, &irel, erel); elf_swap_reloc_out (output_bfd, irel, erel);
} }
free (irel);
} }
else else
{ {
Elf_External_Rela *erela; Elf_External_Rela *erela;
BFD_ASSERT (input_rel_hdr->sh_entsize BFD_ASSERT (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rela));
== sizeof (Elf_External_Rela));
erela = ((Elf_External_Rela *) output_rel_hdr->contents + *rel_countp); 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) if (bed->s->swap_reloca_out)
(*bed->s->swap_reloca_out) (output_bfd, irela, (PTR) erela); (*bed->s->swap_reloca_out) (output_bfd, irela, (PTR) erela);
else else
@ -5798,21 +5840,28 @@ elf_link_input_bfd (finfo, input_bfd)
Elf_Internal_Rela *irelaend; Elf_Internal_Rela *irelaend;
struct elf_link_hash_entry **rel_hash; struct elf_link_hash_entry **rel_hash;
Elf_Internal_Shdr *input_rel_hdr; Elf_Internal_Shdr *input_rel_hdr;
unsigned char next_erel;
/* Adjust the reloc addresses and symbol indices. */ /* Adjust the reloc addresses and symbol indices. */
irela = internal_relocs; irela = internal_relocs;
irelaend = irelaend = irela
irela + o->reloc_count * bed->s->int_rels_per_ext_rel; + o->reloc_count * bed->s->int_rels_per_ext_rel;
rel_hash = (elf_section_data (o->output_section)->rel_hashes 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_count
+ elf_section_data (o->output_section)->rel_count2); + 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; unsigned long r_symndx;
Elf_Internal_Sym *isym; Elf_Internal_Sym *isym;
asection *sec; asection *sec;
if (next_erel == bed->s->int_rels_per_ext_rel)
{
rel_hash++;
next_erel = 0;
}
irela->r_offset += o->output_offset; irela->r_offset += o->output_offset;
/* Relocs in an executable have to be virtual addresses. */ /* 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)) && finfo->sections[r_symndx] == NULL))
{ {
struct elf_link_hash_entry *rh; struct elf_link_hash_entry *rh;
long indx; unsigned long indx;
/* This is a reloc against a global symbol. We /* This is a reloc against a global symbol. We
have not yet output all the local symbols, so 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, elf_link_output_relocs (output_bfd, o,
input_rel_hdr, input_rel_hdr,
internal_relocs); 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; input_rel_hdr = elf_section_data (o)->rel_hdr2;
if (input_rel_hdr) if (input_rel_hdr)
elf_link_output_relocs (output_bfd, o, 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) if (rel_hdr->sh_type == SHT_REL)
{ {
Elf_Internal_Rel irel; Elf_Internal_Rel *irel;
Elf_External_Rel *erel; 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 erel = ((Elf_External_Rel *) rel_hdr->contents
+ elf_section_data (output_section)->rel_count); + elf_section_data (output_section)->rel_count);
if (bed->s->swap_reloc_out) 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 else
elf_swap_reloc_out (output_bfd, &irel, erel); elf_swap_reloc_out (output_bfd, irel, erel);
free (irel);
} }
else else
{ {
Elf_Internal_Rela irela; Elf_Internal_Rela *irela;
Elf_External_Rela *erela; 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 erela = ((Elf_External_Rela *) rel_hdr->contents
+ elf_section_data (output_section)->rel_count); + elf_section_data (output_section)->rel_count);
if (bed->s->swap_reloca_out) 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 else
elf_swap_reloca_out (output_bfd, &irela, erela); elf_swap_reloca_out (output_bfd, irela, erela);
} }
++elf_section_data (output_section)->rel_count; ++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) #define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_32 (BFD, VAL, ADDR)
#endif #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 bfd_vma
elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, relocation, rel, relative_reloc) 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) if (info->shared)
{ {
asection *srel = lsect->rel_section; 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. */ /* We need to generate a relative reloc for the dynamic linker. */
if (!srel) if (!srel)
@ -6348,16 +6428,19 @@ elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, reloca
BFD_ASSERT (srel != NULL); BFD_ASSERT (srel != NULL);
outrel.r_offset = (lsect->section->output_section->vma for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
+ lsect->section->output_offset outrel[i].r_offset = (lsect->section->output_section->vma
+ linker_section_ptr->offset); + lsect->section->output_offset
outrel.r_info = ELF_R_INFO (0, relative_reloc); + linker_section_ptr->offset);
outrel.r_addend = 0; outrel[0].r_info = ELF_R_INFO (0, relative_reloc);
elf_swap_reloca_out (output_bfd, &outrel, outrel[0].r_addend = 0;
elf_swap_reloca_out (output_bfd, outrel,
(((Elf_External_Rela *) (((Elf_External_Rela *)
lsect->section->contents) lsect->section->contents)
+ elf_section_data (lsect->section)->rel_count)); + elf_section_data (lsect->section)->rel_count));
++elf_section_data (lsect->section)->rel_count; ++elf_section_data (lsect->section)->rel_count;
free (outrel);
} }
} }
} }