* elfxx-mips.c (mips_elf_create_dynamic_relocation): Return early

for discard relocations; don't add an R_MIPS_NONE to the main body
	of .rel.dyn.
This commit is contained in:
Richard Sandiford
2004-11-16 09:54:10 +00:00
parent 1d72487d99
commit 5d41f0b6e5
2 changed files with 95 additions and 99 deletions

View File

@ -1,3 +1,9 @@
2004-11-16 Richard Sandiford <rsandifo@redhat.com>
* elfxx-mips.c (mips_elf_create_dynamic_relocation): Return early
for discard relocations; don't add an R_MIPS_NONE to the main body
of .rel.dyn.
2004-11-04 Paul Brook <paul@codesourcery.com> 2004-11-04 Paul Brook <paul@codesourcery.com>
* elf-bfd.h (_bfd_elf_slurp_version_tables): Update prototype. * elf-bfd.h (_bfd_elf_slurp_version_tables): Update prototype.

View File

@ -3783,10 +3783,11 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
bfd_vma *addendp, asection *input_section) bfd_vma *addendp, asection *input_section)
{ {
Elf_Internal_Rela outrel[3]; Elf_Internal_Rela outrel[3];
bfd_boolean skip;
asection *sreloc; asection *sreloc;
bfd *dynobj; bfd *dynobj;
int r_type; int r_type;
long indx;
bfd_boolean defined_p;
r_type = ELF_R_TYPE (output_bfd, rel->r_info); r_type = ELF_R_TYPE (output_bfd, rel->r_info);
dynobj = elf_hash_table (info)->dynobj; dynobj = elf_hash_table (info)->dynobj;
@ -3796,7 +3797,6 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd) BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd)
< sreloc->size); < sreloc->size);
skip = FALSE;
outrel[0].r_offset = outrel[0].r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset); _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
outrel[1].r_offset = outrel[1].r_offset =
@ -3830,119 +3830,109 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
if (outrel[0].r_offset == MINUS_ONE) if (outrel[0].r_offset == MINUS_ONE)
/* The relocation field has been deleted. */ /* The relocation field has been deleted. */
skip = TRUE; return TRUE;
else if (outrel[0].r_offset == MINUS_TWO)
if (outrel[0].r_offset == MINUS_TWO)
{ {
/* The relocation field has been converted into a relative value of /* The relocation field has been converted into a relative value of
some sort. Functions like _bfd_elf_write_section_eh_frame expect some sort. Functions like _bfd_elf_write_section_eh_frame expect
the field to be fully relocated, so add in the symbol's value. */ the field to be fully relocated, so add in the symbol's value. */
skip = TRUE;
*addendp += symbol; *addendp += symbol;
return TRUE;
} }
/* If we've decided to skip this relocation, just output an empty /* We must now calculate the dynamic symbol table index to use
record. Note that R_MIPS_NONE == 0, so that this call to memset in the relocation. */
is a way of setting R_TYPE to R_MIPS_NONE. */ if (h != NULL
if (skip) && (! info->symbolic || !h->root.def_regular)
memset (outrel, 0, sizeof (Elf_Internal_Rela) * 3); /* h->root.dynindx may be -1 if this symbol was marked to
become local. */
&& h->root.dynindx != -1)
{
indx = h->root.dynindx;
if (SGI_COMPAT (output_bfd))
defined_p = h->root.def_regular;
else
/* ??? glibc's ld.so just adds the final GOT entry to the
relocation field. It therefore treats relocs against
defined symbols in the same way as relocs against
undefined symbols. */
defined_p = FALSE;
}
else else
{ {
long indx; if (sec != NULL && bfd_is_abs_section (sec))
bfd_boolean defined_p; indx = 0;
else if (sec == NULL || sec->owner == NULL)
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
if (h != NULL
&& (! info->symbolic || !h->root.def_regular)
/* h->root.dynindx may be -1 if this symbol was marked to
become local. */
&& h->root.dynindx != -1)
{ {
indx = h->root.dynindx; bfd_set_error (bfd_error_bad_value);
if (SGI_COMPAT (output_bfd)) return FALSE;
defined_p = h->root.def_regular;
else
/* ??? glibc's ld.so just adds the final GOT entry to the
relocation field. It therefore treats relocs against
defined symbols in the same way as relocs against
undefined symbols. */
defined_p = FALSE;
} }
else else
{ {
if (sec != NULL && bfd_is_abs_section (sec)) indx = elf_section_data (sec->output_section)->dynindx;
indx = 0; if (indx == 0)
else if (sec == NULL || sec->owner == NULL) abort ();
{
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
else
{
indx = elf_section_data (sec->output_section)->dynindx;
if (indx == 0)
abort ();
}
/* Instead of generating a relocation using the section
symbol, we may as well make it a fully relative
relocation. We want to avoid generating relocations to
local symbols because we used to generate them
incorrectly, without adding the original symbol value,
which is mandated by the ABI for section symbols. In
order to give dynamic loaders and applications time to
phase out the incorrect use, we refrain from emitting
section-relative relocations. It's not like they're
useful, after all. This should be a bit more efficient
as well. */
/* ??? Although this behavior is compatible with glibc's ld.so,
the ABI says that relocations against STN_UNDEF should have
a symbol value of 0. Irix rld honors this, so relocations
against STN_UNDEF have no effect. */
if (!SGI_COMPAT (output_bfd))
indx = 0;
defined_p = TRUE;
} }
/* If the relocation was previously an absolute relocation and /* Instead of generating a relocation using the section
this symbol will not be referred to by the relocation, we must symbol, we may as well make it a fully relative
adjust it by the value we give it in the dynamic symbol table. relocation. We want to avoid generating relocations to
Otherwise leave the job up to the dynamic linker. */ local symbols because we used to generate them
if (defined_p && r_type != R_MIPS_REL32) incorrectly, without adding the original symbol value,
*addendp += symbol; which is mandated by the ABI for section symbols. In
order to give dynamic loaders and applications time to
/* The relocation is always an REL32 relocation because we don't phase out the incorrect use, we refrain from emitting
know where the shared library will wind up at load-time. */ section-relative relocations. It's not like they're
outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx, useful, after all. This should be a bit more efficient
R_MIPS_REL32); as well. */
/* For strict adherence to the ABI specification, we should /* ??? Although this behavior is compatible with glibc's ld.so,
generate a R_MIPS_64 relocation record by itself before the the ABI says that relocations against STN_UNDEF should have
_REL32/_64 record as well, such that the addend is read in as a symbol value of 0. Irix rld honors this, so relocations
a 64-bit value (REL32 is a 32-bit relocation, after all). against STN_UNDEF have no effect. */
However, since none of the existing ELF64 MIPS dynamic if (!SGI_COMPAT (output_bfd))
loaders seems to care, we don't waste space with these indx = 0;
artificial relocations. If this turns out to not be true, defined_p = TRUE;
mips_elf_allocate_dynamic_relocation() should be tweaked so
as to make room for a pair of dynamic relocations per
invocation if ABI_64_P, and here we should generate an
additional relocation record with R_MIPS_64 by itself for a
NULL symbol before this relocation record. */
outrel[1].r_info = ELF_R_INFO (output_bfd, 0,
ABI_64_P (output_bfd)
? R_MIPS_64
: R_MIPS_NONE);
outrel[2].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_NONE);
/* Adjust the output offset of the relocation to reference the
correct location in the output file. */
outrel[0].r_offset += (input_section->output_section->vma
+ input_section->output_offset);
outrel[1].r_offset += (input_section->output_section->vma
+ input_section->output_offset);
outrel[2].r_offset += (input_section->output_section->vma
+ input_section->output_offset);
} }
/* If the relocation was previously an absolute relocation and
this symbol will not be referred to by the relocation, we must
adjust it by the value we give it in the dynamic symbol table.
Otherwise leave the job up to the dynamic linker. */
if (defined_p && 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[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
R_MIPS_REL32);
/* For strict adherence to the ABI specification, we should
generate a R_MIPS_64 relocation record by itself before the
_REL32/_64 record as well, such that the addend is read in as
a 64-bit value (REL32 is a 32-bit relocation, after all).
However, since none of the existing ELF64 MIPS dynamic
loaders seems to care, we don't waste space with these
artificial relocations. If this turns out to not be true,
mips_elf_allocate_dynamic_relocation() should be tweaked so
as to make room for a pair of dynamic relocations per
invocation if ABI_64_P, and here we should generate an
additional relocation record with R_MIPS_64 by itself for a
NULL symbol before this relocation record. */
outrel[1].r_info = ELF_R_INFO (output_bfd, 0,
ABI_64_P (output_bfd)
? R_MIPS_64
: R_MIPS_NONE);
outrel[2].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_NONE);
/* Adjust the output offset of the relocation to reference the
correct location in the output file. */
outrel[0].r_offset += (input_section->output_section->vma
+ input_section->output_offset);
outrel[1].r_offset += (input_section->output_section->vma
+ input_section->output_offset);
outrel[2].r_offset += (input_section->output_section->vma
+ input_section->output_offset);
/* Put the relocation back out. We have to use the special /* Put the relocation back out. We have to use the special
relocation outputter in the 64-bit case since the 64-bit relocation outputter in the 64-bit case since the 64-bit
relocation format is non-standard. */ relocation format is non-standard. */
@ -3967,7 +3957,7 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
|= SHF_WRITE; |= SHF_WRITE;
/* On IRIX5, make an entry of compact relocation info. */ /* On IRIX5, make an entry of compact relocation info. */
if (! skip && IRIX_COMPAT (output_bfd) == ict_irix5) if (IRIX_COMPAT (output_bfd) == ict_irix5)
{ {
asection *scpt = bfd_get_section_by_name (dynobj, ".compact_rel"); asection *scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
bfd_byte *cr; bfd_byte *cr;