* elfxx-target.h (bfd_elfNN_canonicalize_reloc): Make it
overridable. * elf64-mips.c (mips_elf64_canonicalize_reloc, mips_elf64_get_dynamic_reloc_upper_bound, mips_elf64_canonicalize_dynamic_reloc): New, adapted from elf.c. (bfd_elf64_get_canonicalize_reloc, bfd_elf64_get_dynamic_reloc_upper_bound, bfd_elf64_canonicalize_dynamic_reloc): Define. (mips_elf64_slurp_reloc_table): Support dynamic. (mips_elf64_slurp_one_reloc_table): Adjust.
This commit is contained in:
parent
0a1e1ca1f6
commit
fee24f1c5b
3 changed files with 174 additions and 32 deletions
|
@ -1,3 +1,16 @@
|
|||
2003-03-12 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* elfxx-target.h (bfd_elfNN_canonicalize_reloc): Make it
|
||||
overridable.
|
||||
* elf64-mips.c (mips_elf64_canonicalize_reloc,
|
||||
mips_elf64_get_dynamic_reloc_upper_bound,
|
||||
mips_elf64_canonicalize_dynamic_reloc): New, adapted from elf.c.
|
||||
(bfd_elf64_get_canonicalize_reloc,
|
||||
bfd_elf64_get_dynamic_reloc_upper_bound,
|
||||
bfd_elf64_canonicalize_dynamic_reloc): Define.
|
||||
(mips_elf64_slurp_reloc_table): Support dynamic.
|
||||
(mips_elf64_slurp_one_reloc_table): Adjust.
|
||||
|
||||
2003-03-12 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* xsym.c (bfd_sym_fetch_type_information_table_entry): Change
|
||||
|
|
191
bfd/elf64-mips.c
191
bfd/elf64-mips.c
|
@ -91,8 +91,14 @@ static void mips_elf64_info_to_howto_rela
|
|||
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
|
||||
static long mips_elf64_get_reloc_upper_bound
|
||||
PARAMS ((bfd *, asection *));
|
||||
static long mips_elf64_canonicalize_reloc
|
||||
PARAMS ((bfd *, asection *, arelent **, asymbol **));
|
||||
static long mips_elf64_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
|
||||
static long mips_elf64_canonicalize_dynamic_reloc
|
||||
PARAMS ((bfd *, arelent **, asymbol **));
|
||||
static bfd_boolean mips_elf64_slurp_one_reloc_table
|
||||
PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *));
|
||||
PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type,
|
||||
arelent *, asymbol **, bfd_boolean));
|
||||
static bfd_boolean mips_elf64_slurp_reloc_table
|
||||
PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
|
||||
static void mips_elf64_write_relocs
|
||||
|
@ -2022,20 +2028,104 @@ mips_elf64_get_reloc_upper_bound (abfd, sec)
|
|||
return (sec->reloc_count * 3 + 1) * sizeof (arelent *);
|
||||
}
|
||||
|
||||
/* Read the relocations from one reloc section. */
|
||||
static long
|
||||
mips_elf64_get_dynamic_reloc_upper_bound (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
|
||||
}
|
||||
|
||||
/* We must also copy more relocations than the corresponding functions
|
||||
in elf.c would, so the two following functions are slightly
|
||||
modified from elf.c, that multiply the external relocation count by
|
||||
3 to obtain the internal relocation count. */
|
||||
|
||||
static long
|
||||
mips_elf64_canonicalize_reloc (abfd, section, relptr, symbols)
|
||||
bfd *abfd;
|
||||
sec_ptr section;
|
||||
arelent **relptr;
|
||||
asymbol **symbols;
|
||||
{
|
||||
arelent *tblptr;
|
||||
unsigned int i;
|
||||
struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
|
||||
if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
|
||||
return -1;
|
||||
|
||||
tblptr = section->relocation;
|
||||
for (i = 0; i < section->reloc_count * 3; i++)
|
||||
*relptr++ = tblptr++;
|
||||
|
||||
*relptr = NULL;
|
||||
|
||||
return section->reloc_count * 3;
|
||||
}
|
||||
|
||||
static long
|
||||
mips_elf64_canonicalize_dynamic_reloc (abfd, storage, syms)
|
||||
bfd *abfd;
|
||||
arelent **storage;
|
||||
asymbol **syms;
|
||||
{
|
||||
bfd_boolean (*slurp_relocs)
|
||||
PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
|
||||
asection *s;
|
||||
long ret;
|
||||
|
||||
if (elf_dynsymtab (abfd) == 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return -1;
|
||||
}
|
||||
|
||||
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
|
||||
ret = 0;
|
||||
for (s = abfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
|
||||
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|
||||
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
|
||||
{
|
||||
arelent *p;
|
||||
long count, i;
|
||||
|
||||
if (! (*slurp_relocs) (abfd, s, syms, TRUE))
|
||||
return -1;
|
||||
count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize * 3;
|
||||
p = s->relocation;
|
||||
for (i = 0; i < count; i++)
|
||||
*storage++ = p++;
|
||||
ret += count;
|
||||
}
|
||||
}
|
||||
|
||||
*storage = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the relocations from one reloc section. This is mostly copied
|
||||
from elfcode.h, except for the changes to expand one external
|
||||
relocation to 3 internal ones. We must unfortunately set
|
||||
reloc_count to the number of external relocations, because a lot of
|
||||
generic code seems to depend on this. */
|
||||
|
||||
static bfd_boolean
|
||||
mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
|
||||
mips_elf64_slurp_one_reloc_table (abfd, asect, rel_hdr, reloc_count,
|
||||
relents, symbols, dynamic)
|
||||
bfd *abfd;
|
||||
asection *asect;
|
||||
Elf_Internal_Shdr *rel_hdr;
|
||||
bfd_size_type reloc_count;
|
||||
arelent *relents;
|
||||
asymbol **symbols;
|
||||
const Elf_Internal_Shdr *rel_hdr;
|
||||
bfd_boolean dynamic;
|
||||
{
|
||||
PTR allocated = NULL;
|
||||
bfd_byte *native_relocs;
|
||||
arelent *relents;
|
||||
arelent *relent;
|
||||
bfd_vma count;
|
||||
bfd_vma i;
|
||||
int entsize;
|
||||
reloc_howto_type *howto_table;
|
||||
|
@ -2045,26 +2135,24 @@ mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
|
|||
return FALSE;
|
||||
|
||||
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
|
||||
|| (bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size))
|
||||
|| (bfd_bread (allocated, rel_hdr->sh_size, abfd)
|
||||
!= rel_hdr->sh_size))
|
||||
goto error_return;
|
||||
|
||||
native_relocs = (bfd_byte *) allocated;
|
||||
|
||||
relents = asect->relocation + asect->reloc_count;
|
||||
|
||||
entsize = rel_hdr->sh_entsize;
|
||||
BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
|
||||
|| entsize == sizeof (Elf64_Mips_External_Rela));
|
||||
|
||||
count = rel_hdr->sh_size / entsize;
|
||||
|
||||
if (entsize == sizeof (Elf64_Mips_External_Rel))
|
||||
howto_table = mips_elf64_howto_table_rel;
|
||||
else
|
||||
howto_table = mips_elf64_howto_table_rela;
|
||||
|
||||
relent = relents;
|
||||
for (i = 0; i < count; i++, native_relocs += entsize)
|
||||
for (i = 0, relent = relents;
|
||||
i < reloc_count;
|
||||
i++, native_relocs += entsize)
|
||||
{
|
||||
Elf64_Mips_Internal_Rela rela;
|
||||
bfd_boolean used_sym, used_ssym;
|
||||
|
@ -2166,7 +2254,7 @@ mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
|
|||
object file, and absolute for an executable file or
|
||||
shared library. The address of a BFD reloc is always
|
||||
section relative. */
|
||||
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
|
||||
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
|
||||
relent->address = rela.r_offset;
|
||||
else
|
||||
relent->address = rela.r_offset - asect->vma;
|
||||
|
@ -2193,7 +2281,10 @@ mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
|
|||
}
|
||||
|
||||
/* Read the relocations. On Irix 6, there can be two reloc sections
|
||||
associated with a single data section. */
|
||||
associated with a single data section. This is copied from
|
||||
elfcode.h as well, with changes as small as accounting for 3
|
||||
internal relocs per external reloc and resetting reloc_count to
|
||||
zero before processing the relocs of a section. */
|
||||
|
||||
static bfd_boolean
|
||||
mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
|
||||
|
@ -2202,39 +2293,72 @@ mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
|
|||
asymbol **symbols;
|
||||
bfd_boolean dynamic;
|
||||
{
|
||||
bfd_size_type amt;
|
||||
struct bfd_elf_section_data * const d = elf_section_data (asect);
|
||||
Elf_Internal_Shdr *rel_hdr;
|
||||
Elf_Internal_Shdr *rel_hdr2;
|
||||
bfd_size_type reloc_count;
|
||||
bfd_size_type reloc_count2;
|
||||
arelent *relents;
|
||||
bfd_size_type amt;
|
||||
|
||||
if (dynamic)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (asect->relocation != NULL
|
||||
|| (asect->flags & SEC_RELOC) == 0
|
||||
|| asect->reloc_count == 0)
|
||||
if (asect->relocation != NULL)
|
||||
return TRUE;
|
||||
|
||||
if (! dynamic)
|
||||
{
|
||||
if ((asect->flags & SEC_RELOC) == 0
|
||||
|| asect->reloc_count == 0)
|
||||
return TRUE;
|
||||
|
||||
rel_hdr = &d->rel_hdr;
|
||||
reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
|
||||
rel_hdr2 = d->rel_hdr2;
|
||||
reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0);
|
||||
|
||||
BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
|
||||
BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
|
||||
|| (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Note that ASECT->RELOC_COUNT tends not to be accurate in this
|
||||
case because relocations against this section may use the
|
||||
dynamic symbol table, and in that case bfd_section_from_shdr
|
||||
in elf.c does not update the RELOC_COUNT. */
|
||||
if (asect->_raw_size == 0)
|
||||
return TRUE;
|
||||
|
||||
rel_hdr = &d->this_hdr;
|
||||
reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
|
||||
rel_hdr2 = NULL;
|
||||
reloc_count2 = 0;
|
||||
}
|
||||
|
||||
/* Allocate space for 3 arelent structures for each Rel structure. */
|
||||
amt = asect->reloc_count;
|
||||
amt *= 3 * sizeof (arelent);
|
||||
asect->relocation = (arelent *) bfd_alloc (abfd, amt);
|
||||
if (asect->relocation == NULL)
|
||||
amt = (reloc_count + reloc_count2) * 3 * sizeof (arelent);
|
||||
relents = (arelent *) bfd_alloc (abfd, amt);
|
||||
if (relents == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* The slurp_one_reloc_table routine increments reloc_count. */
|
||||
asect->reloc_count = 0;
|
||||
|
||||
if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, &d->rel_hdr))
|
||||
if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
|
||||
rel_hdr, reloc_count,
|
||||
relents,
|
||||
symbols, dynamic))
|
||||
return FALSE;
|
||||
if (d->rel_hdr2 != NULL)
|
||||
{
|
||||
if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols,
|
||||
d->rel_hdr2))
|
||||
if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
|
||||
rel_hdr2, reloc_count2,
|
||||
relents + reloc_count * 3,
|
||||
symbols, dynamic))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
asect->relocation = relents;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2764,6 +2888,9 @@ const struct elf_size_info mips_elf64_size_info =
|
|||
_bfd_mips_elf_print_private_bfd_data
|
||||
|
||||
#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
|
||||
#define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc
|
||||
#define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
|
||||
#define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc
|
||||
|
||||
/* MIPS ELF64 archive functions. */
|
||||
#define bfd_elf64_archive_functions
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
#endif
|
||||
|
||||
#define bfd_elfNN_canonicalize_dynamic_symtab _bfd_elf_canonicalize_dynamic_symtab
|
||||
#ifndef bfd_elfNN_canonicalize_reloc
|
||||
#define bfd_elfNN_canonicalize_reloc _bfd_elf_canonicalize_reloc
|
||||
#endif
|
||||
#ifndef bfd_elfNN_find_nearest_line
|
||||
#define bfd_elfNN_find_nearest_line _bfd_elf_find_nearest_line
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue