* elflink.h (elf_link_adjust_relocs): New function.
(elf_bfd_final_link): Use it. (elf_link_input_bfd): Deal with the fact that there can be two relocation sections for a single section. (elf_reloc_link_order): Likewise. * elf32-mips.c (_bfd_mips_elf_final_link): Don't set GP for a relocateable object. (_bfd_mips_elf_relocate_section): Handle relocateable links.
This commit is contained in:
parent
c2c594b87d
commit
31367b81b7
3 changed files with 138 additions and 60 deletions
|
@ -1,3 +1,15 @@
|
|||
Sat Jul 17 02:28:28 1999 Mark P. Mitchell <mark@codesourcery.com>
|
||||
|
||||
* elflink.h (elf_link_adjust_relocs): New function.
|
||||
(elf_bfd_final_link): Use it.
|
||||
(elf_link_input_bfd): Deal with the fact that there can be
|
||||
two relocation sections for a single section.
|
||||
(elf_reloc_link_order): Likewise.
|
||||
|
||||
* elf32-mips.c (_bfd_mips_elf_final_link): Don't set GP for
|
||||
a relocateable object.
|
||||
(_bfd_mips_elf_relocate_section): Handle relocateable links.
|
||||
|
||||
1999-07-16 Jakub Jelinek <jj@ultra.linux.cz>
|
||||
|
||||
* elf64-sparc.c (sparc64_elf_info_to_howto): Use ELF64_R_TYPE_ID.
|
||||
|
|
|
@ -4388,20 +4388,6 @@ _bfd_mips_elf_final_link (abfd, info)
|
|||
elf_gp (abfd) = (h->u.def.value
|
||||
+ h->u.def.section->output_section->vma
|
||||
+ h->u.def.section->output_offset);
|
||||
else if (info->relocateable)
|
||||
{
|
||||
bfd_vma lo;
|
||||
|
||||
/* Find the GP-relative section with the lowest offset. */
|
||||
lo = (bfd_vma) -1;
|
||||
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
|
||||
if (o->vma < lo
|
||||
&& (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
|
||||
lo = o->vma;
|
||||
|
||||
/* And calculate GP relative to that. */
|
||||
elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (abfd);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the relocate_section function needs to do a reloc
|
||||
|
@ -6429,7 +6415,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
Elf_Internal_Sym *local_syms;
|
||||
asection **local_sections;
|
||||
{
|
||||
const Elf_Internal_Rela *rel;
|
||||
Elf_Internal_Rela *rel;
|
||||
const Elf_Internal_Rela *relend;
|
||||
bfd_vma addend;
|
||||
bfd_vma last_hi16_addend;
|
||||
|
@ -6445,10 +6431,13 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
bfd_vma value;
|
||||
reloc_howto_type *howto;
|
||||
boolean require_jalx;
|
||||
/* True if the relocation is a RELA relocation, rather than a
|
||||
REL relocation. */
|
||||
boolean rela_relocation_p = true;
|
||||
int r_type = ELF32_R_TYPE (rel->r_info);
|
||||
|
||||
/* Find the relocation howto for this relocation. */
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_MIPS_64
|
||||
&& !ABI_64_P (output_bfd))
|
||||
if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
|
||||
/* Some 32-bit code uses R_MIPS_64. In particular, people use
|
||||
64-bit code, but make sure all their addresses are in the
|
||||
lowermost or uppermost 32-bit section of the 64-bit address
|
||||
|
@ -6457,7 +6446,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
stored value is sign-extended to 64 bits. */
|
||||
howto = elf_mips_howto_table + R_MIPS_32;
|
||||
else
|
||||
howto = elf_mips_howto_table + ELF32_R_TYPE (rel->r_info);
|
||||
howto = elf_mips_howto_table + r_type;
|
||||
|
||||
if (!use_saved_addend_p)
|
||||
{
|
||||
|
@ -6476,8 +6465,10 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
rel_hdr = elf_section_data (input_section)->rel_hdr2;
|
||||
if (rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (input_bfd))
|
||||
{
|
||||
int r_type = ELF32_R_TYPE (rel->r_info);
|
||||
/* Note that this is a REL relocation. */
|
||||
rela_relocation_p = false;
|
||||
|
||||
/* Get the addend, which is stored in the input file. */
|
||||
addend = mips_elf_obtain_contents (howto,
|
||||
rel,
|
||||
input_bfd,
|
||||
|
@ -6533,13 +6524,63 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
addend = rel->r_addend;
|
||||
}
|
||||
|
||||
if (info->relocateable)
|
||||
{
|
||||
Elf_Internal_Sym *sym;
|
||||
unsigned long r_symndx;
|
||||
|
||||
/* Since we're just relocating, all we need to do is copy
|
||||
the relocations back out to the object file, unless they're
|
||||
against a section symbol, in which case we need to adjust
|
||||
by the section offset. */
|
||||
|
||||
if (!mips_elf_local_relocation_p (input_bfd, rel, local_sections))
|
||||
/* A non-local relocation is never against a section. */
|
||||
continue;
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
sym = local_syms + r_symndx;
|
||||
if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
|
||||
continue;
|
||||
|
||||
/* Adjust the addend appropriately. */
|
||||
addend += local_sections[r_symndx]->output_offset;
|
||||
|
||||
/* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
|
||||
then we only want to write out the high-order 16 bits.
|
||||
The subsequent R_MIPS_LO16 will handle the low-order bits. */
|
||||
if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16)
|
||||
addend >>= 16;
|
||||
|
||||
if (rela_relocation_p)
|
||||
/* If this is a RELA relocation, just update the addend.
|
||||
We have to cast away constness for REL. */
|
||||
rel->r_addend = addend;
|
||||
else
|
||||
{
|
||||
/* Otherwise, we have to write the value back out. Note
|
||||
that we use the source mask, rather than the
|
||||
destination mask because the place to which we are
|
||||
writing will be source of the addend in the final
|
||||
link. */
|
||||
addend &= howto->src_mask;
|
||||
if (!mips_elf_perform_relocation (info, howto, rel, addend,
|
||||
input_bfd, input_section,
|
||||
contents, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Go on to the next relocation. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* In the N32 and 64-bit ABIs there may be multiple consecutive
|
||||
relocations for the same offset. In that case we are
|
||||
supposed to treat the output of each relocation as the addend
|
||||
for the next. */
|
||||
if (rel + 1 < relend
|
||||
&& rel->r_offset == rel[1].r_offset
|
||||
&& ELF32_R_TYPE (rel[1].r_info) != R_MIPS_NONE)
|
||||
&& r_type != R_MIPS_NONE)
|
||||
use_saved_addend_p = true;
|
||||
else
|
||||
use_saved_addend_p = false;
|
||||
|
@ -6602,8 +6643,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_MIPS_64
|
||||
&& !ABI_64_P (output_bfd))
|
||||
if (r_type == R_MIPS_64 && !ABI_64_P (output_bfd))
|
||||
/* See the comment above about using R_MIPS_64 in the 32-bit
|
||||
ABI. Until now, we've been using the HOWTO for R_MIPS_32;
|
||||
that calculated the right value. Now, however, we
|
||||
|
|
102
bfd/elflink.h
102
bfd/elflink.h
|
@ -56,6 +56,9 @@ static void elf_link_output_relocs
|
|||
PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *));
|
||||
static boolean elf_link_size_reloc_section
|
||||
PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
|
||||
static void elf_link_adjust_relocs
|
||||
PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned int,
|
||||
struct elf_link_hash_entry **));
|
||||
|
||||
/* Given an ELF BFD, add symbols to the global hash table as
|
||||
appropriate. */
|
||||
|
@ -3782,6 +3785,55 @@ elf_link_size_reloc_section (abfd, rel_hdr, o)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* When performing a relocateable link, the input relocations are
|
||||
preserved. But, if they reference global symbols, the indices
|
||||
referenced must be updated. Update all the relocations in
|
||||
REL_HDR (there are COUNT of them), using the data in REL_HASH. */
|
||||
|
||||
static void
|
||||
elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash)
|
||||
bfd *abfd;
|
||||
Elf_Internal_Shdr *rel_hdr;
|
||||
unsigned int count;
|
||||
struct elf_link_hash_entry **rel_hash;
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++, rel_hash++)
|
||||
{
|
||||
if (*rel_hash == NULL)
|
||||
continue;
|
||||
|
||||
BFD_ASSERT ((*rel_hash)->indx >= 0);
|
||||
|
||||
if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
|
||||
{
|
||||
Elf_External_Rel *erel;
|
||||
Elf_Internal_Rel irel;
|
||||
|
||||
erel = (Elf_External_Rel *) rel_hdr->contents + i;
|
||||
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_out (abfd, &irel, erel);
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf_External_Rela *erela;
|
||||
Elf_Internal_Rela irela;
|
||||
|
||||
BFD_ASSERT (rel_hdr->sh_entsize
|
||||
== sizeof (Elf_External_Rela));
|
||||
|
||||
erela = (Elf_External_Rela *) rel_hdr->contents + i;
|
||||
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_out (abfd, &irela, erela);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the final step of an ELF link. */
|
||||
|
||||
boolean
|
||||
|
@ -4268,42 +4320,14 @@ elf_bfd_final_link (abfd, info)
|
|||
if ((o->flags & SEC_RELOC) == 0)
|
||||
continue;
|
||||
|
||||
rel_hash = elf_section_data (o)->rel_hashes;
|
||||
rel_hdr = &elf_section_data (o)->rel_hdr;
|
||||
BFD_ASSERT (elf_section_data (o)->rel_count == o->reloc_count);
|
||||
for (i = 0; i < o->reloc_count; i++, rel_hash++)
|
||||
{
|
||||
if (*rel_hash == NULL)
|
||||
continue;
|
||||
|
||||
BFD_ASSERT ((*rel_hash)->indx >= 0);
|
||||
|
||||
if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
|
||||
{
|
||||
Elf_External_Rel *erel;
|
||||
Elf_Internal_Rel irel;
|
||||
|
||||
erel = (Elf_External_Rel *) rel_hdr->contents + i;
|
||||
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_out (abfd, &irel, erel);
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf_External_Rela *erela;
|
||||
Elf_Internal_Rela irela;
|
||||
|
||||
BFD_ASSERT (rel_hdr->sh_entsize
|
||||
== sizeof (Elf_External_Rela));
|
||||
|
||||
erela = (Elf_External_Rela *) rel_hdr->contents + i;
|
||||
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_out (abfd, &irela, erela);
|
||||
}
|
||||
}
|
||||
elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr,
|
||||
elf_section_data (o)->rel_count,
|
||||
elf_section_data (o)->rel_hashes);
|
||||
if (elf_section_data (o)->rel_hdr2 != NULL)
|
||||
elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2,
|
||||
elf_section_data (o)->rel_count2,
|
||||
(elf_section_data (o)->rel_hashes
|
||||
+ elf_section_data (o)->rel_count));
|
||||
|
||||
/* Set the reloc_count field to 0 to prevent write_relocs from
|
||||
trying to swap the relocs out itself. */
|
||||
|
@ -5224,7 +5248,8 @@ elf_link_input_bfd (finfo, input_bfd)
|
|||
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_count
|
||||
+ elf_section_data (o->output_section)->rel_count2);
|
||||
for (; irela < irelaend; irela++, rel_hash++)
|
||||
{
|
||||
unsigned long r_symndx;
|
||||
|
@ -5414,7 +5439,8 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
|
|||
|
||||
/* Figure out the symbol index. */
|
||||
rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
|
||||
+ elf_section_data (output_section)->rel_count);
|
||||
+ elf_section_data (output_section)->rel_count
|
||||
+ elf_section_data (output_section)->rel_count2);
|
||||
if (link_order->type == bfd_section_reloc_link_order)
|
||||
{
|
||||
indx = link_order->u.reloc.p->u.section->target_index;
|
||||
|
|
Loading…
Reference in a new issue