* elf32-mips.c (mips_elf_create_dynamic_relocation): Change

prototype.  Handle local symbols.  Add commentary.
	(mips_elf_calculate_relocation): Adjust accordingly.
	(_bfd_mips_elf_check_relocs): Handle local symbols in R_MIPS_32
	relocations.
This commit is contained in:
Mark Mitchell
1999-08-10 06:27:48 +00:00
parent ce00621771
commit 7b1f123191
2 changed files with 132 additions and 54 deletions

View File

@ -1,5 +1,11 @@
Tue Aug 10 00:21:08 1999 Mark P. Mitchell <mark@codesourcery.com> Tue Aug 10 00:21:08 1999 Mark P. Mitchell <mark@codesourcery.com>
* elf32-mips.c (mips_elf_create_dynamic_relocation): Change
prototype. Handle local symbols. Add commentary.
(mips_elf_calculate_relocation): Adjust accordingly.
(_bfd_mips_elf_check_relocs): Handle local symbols in R_MIPS_32
relocations.
* elflink.h (elf_bfd_final_link): Tweak last change. * elflink.h (elf_bfd_final_link): Tweak last change.
1999-08-09 Mark Mitchell <mark@codesourcery.com> 1999-08-09 Mark Mitchell <mark@codesourcery.com>

View File

@ -192,9 +192,10 @@ static bfd_vma mips_elf_create_local_got_entry
PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma)); PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));
static bfd_vma mips_elf_got16_entry static bfd_vma mips_elf_got16_entry
PARAMS ((bfd *, struct bfd_link_info *, bfd_vma)); PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
static unsigned int mips_elf_create_dynamic_relocation static boolean mips_elf_create_dynamic_relocation
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *, PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
long, bfd_vma, asection *)); struct mips_elf_link_hash_entry *, asection *,
bfd_vma, bfd_vma *, asection *));
static void mips_elf_allocate_dynamic_relocations static void mips_elf_allocate_dynamic_relocations
PARAMS ((bfd *, unsigned int)); PARAMS ((bfd *, unsigned int));
static boolean mips_elf_stub_section_p static boolean mips_elf_stub_section_p
@ -5541,7 +5542,7 @@ mips_elf_got16_entry (abfd, info, value)
want, it is really the %high value. The complete value is want, it is really the %high value. The complete value is
calculated with a `addiu' of a LO16 relocation, just as with a calculated with a `addiu' of a LO16 relocation, just as with a
HI16/LO16 pair. */ HI16/LO16 pair. */
value = mips_elf_high (value); value = mips_elf_high (value) << 16;
g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot); g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
/* Look to see if we already have an appropriate entry. */ /* Look to see if we already have an appropriate entry. */
@ -5594,19 +5595,21 @@ mips_elf_next_lo16_relocation (relocation, relend)
return NULL; return NULL;
} }
/* Create a rel.dyn relocation for the dynamic linker to resolve. The /* Create a rel.dyn relocation for the dynamic linker to resolve. REL
relocatin is against the symbol with the dynamic symbol table index is the original relocation, which is now being transformed into a
DYNINDX. REL is the original relocation, which is now being made dyanmic relocation. The ADDENDP is adjusted if necessary; the
dynamic. */ caller should store the result in place of the original addend. */
static unsigned int static boolean
mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx, mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
addend, input_section) symbol, addendp, input_section)
bfd *output_bfd; bfd *output_bfd;
struct bfd_link_info *info; struct bfd_link_info *info;
const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel;
long dynindx; struct mips_elf_link_hash_entry *h;
bfd_vma addend; asection *sec;
bfd_vma symbol;
bfd_vma *addendp;
asection *input_section; asection *input_section;
{ {
Elf_Internal_Rel outrel; Elf_Internal_Rel outrel;
@ -5624,36 +5627,94 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
skip = false; skip = false;
/* The symbol for the relocation is the same as it was for the /* We begin by assuming that the offset for the dynamic relocation
original relocation. */ is the same as for the original relocation. We'll adjust this
outrel.r_info = ELF32_R_INFO (dynindx, R_MIPS_REL32); later to reflect the correct output offsets. */
/* The offset for the dynamic relocation is the same as for the
original relocation, adjusted by the offset at which the original
section is output. */
if (elf_section_data (input_section)->stab_info == NULL) if (elf_section_data (input_section)->stab_info == NULL)
outrel.r_offset = rel->r_offset; outrel.r_offset = rel->r_offset;
else else
{ {
bfd_vma off; /* Except that in a stab section things are more complex.
Because we compress stab information, the offset given in the
off = (_bfd_stab_section_offset relocation may not be the one we want; we must let the stabs
(output_bfd, &elf_hash_table (info)->stab_info, machinery tell us the offset. */
input_section, outrel.r_offset
&elf_section_data (input_section)->stab_info, = (_bfd_stab_section_offset
rel->r_offset)); (output_bfd, &elf_hash_table (info)->stab_info,
if (off == (bfd_vma) -1) input_section,
&elf_section_data (input_section)->stab_info,
rel->r_offset));
/* If we didn't need the relocation at all, this value will be
-1. */
if (outrel.r_offset == (bfd_vma) -1)
skip = true; skip = true;
outrel.r_offset = off;
} }
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
/* If we've decided to skip this relocation, just output an emtpy /* If we've decided to skip this relocation, just output an emtpy
record. */ record. Note that R_MIPS_NONE == 0, so that this call to memset
is a way of setting R_TYPE to R_MIPS_NONE. */
if (skip) if (skip)
memset (&outrel, 0, sizeof (outrel)); memset (&outrel, 0, sizeof (outrel));
else
{
long indx;
bfd_vma section_offset;
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
if (h != NULL
&& (! info->symbolic || (h->root.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))
{
indx = h->root.dynindx;
BFD_ASSERT (indx != -1);
}
else
{
if (sec != NULL && bfd_is_abs_section (sec))
indx = 0;
else if (sec == NULL || sec->owner == NULL)
{
bfd_set_error (bfd_error_bad_value);
return false;
}
else
{
indx = elf_section_data (sec->output_section)->dynindx;
if (indx == 0)
abort ();
}
/* Figure out how far the target of the relocation is from
the beginning of its section. */
section_offset = symbol - sec->output_section->vma;
/* The relocation we're building is section-relative.
Therefore, the original addend must be adjusted by the
section offset. */
*addendp += symbol - sec->output_section->vma;
/* Now, the relocation is just against the section. */
symbol = sec->output_section->vma;
}
/* If the relocation was previously an absolute relocation, we
must adjust it by the value we give it in the dynamic symbol
table. */
if (r_type != R_MIPS_REL32)
*addendp += symbol;
/* The relocation is always an REL32 relocation because we don't
know where the shared library will wind up at load-time. */
outrel.r_info = ELF32_R_INFO (indx, R_MIPS_REL32);
/* Adjust the output offset of the relocation to reference the
correct location in the output file. */
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
}
/* Put the relocation back out. We have to use the special
relocation outputter in the 64-bit case since the 64-bit
relocation format is non-standard. */
if (ABI_64_P (output_bfd)) if (ABI_64_P (output_bfd))
{ {
(*get_elf_backend_data (output_bfd)->s->swap_reloc_out) (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
@ -5666,6 +5727,15 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
(((Elf32_External_Rel *) (((Elf32_External_Rel *)
sreloc->contents) sreloc->contents)
+ sreloc->reloc_count)); + sreloc->reloc_count));
/* Record the index of the first relocation referencing H. This
information is later emitted in the .msym section. */
if (h != NULL
&& (h->min_dyn_reloc_index == 0
|| sreloc->reloc_count < h->min_dyn_reloc_index))
h->min_dyn_reloc_index = sreloc->reloc_count;
/* We've now added another relocation. */
++sreloc->reloc_count; ++sreloc->reloc_count;
/* Make sure the output section is writable. The dynamic linker /* Make sure the output section is writable. The dynamic linker
@ -5692,7 +5762,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
else else
mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD); mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
mips_elf_set_cr_dist2to (cptrel, 0); mips_elf_set_cr_dist2to (cptrel, 0);
cptrel.konst = addend; cptrel.konst = *addendp;
cr = (scpt->contents cr = (scpt->contents
+ sizeof (Elf32_External_compact_rel)); + sizeof (Elf32_External_compact_rel));
@ -5703,7 +5773,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx,
} }
} }
return sreloc->reloc_count - 1; return true;
} }
/* Calculate the value produced by the RELOCATION (which comes from /* Calculate the value produced by the RELOCATION (which comes from
@ -6024,27 +6094,28 @@ mips_elf_calculate_relocation (abfd,
case R_MIPS_32: case R_MIPS_32:
case R_MIPS_REL32: case R_MIPS_REL32:
case R_MIPS_64: case R_MIPS_64:
/* If we're creating a shared library, or this relocation is if ((info->shared
against a symbol in a shared library, then we can't know || (elf_hash_table (info)->dynamic_sections_created
where the symbol will end up. So, we create a relocation && h != NULL
record in the output, and leave the job up to the dynamic && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
linker. */ == 0)))
if (info->shared || !sec->output_section) && (input_section->flags & SEC_ALLOC) != 0)
{ {
unsigned int reloc_index; /* If we're creating a shared library, or this relocation is
against a symbol in a shared library, then we can't know
BFD_ASSERT (h != NULL); where the symbol will end up. So, we create a relocation
reloc_index record in the output, and leave the job up to the dynamic
= mips_elf_create_dynamic_relocation (abfd, linker. */
info, value = addend;
relocation, if (!mips_elf_create_dynamic_relocation (abfd,
h->root.dynindx, info,
addend, relocation,
input_section); h,
if (h->min_dyn_reloc_index == 0 sec,
|| reloc_index < h->min_dyn_reloc_index) symbol,
h->min_dyn_reloc_index = reloc_index; &value,
value = symbol + addend; input_section))
return false;
} }
else else
{ {
@ -7488,7 +7559,8 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
this symbol, a symbol must have a dynamic symbol this symbol, a symbol must have a dynamic symbol
table index greater that DT_GOTSYM if there are table index greater that DT_GOTSYM if there are
dynamic relocations against it. */ dynamic relocations against it. */
if (!mips_elf_record_global_got_symbol (h, info, g)) if (h != NULL
&& !mips_elf_record_global_got_symbol (h, info, g))
return false; return false;
} }