* 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:
Alexandre Oliva 2003-03-12 22:52:12 +00:00
parent 0a1e1ca1f6
commit fee24f1c5b
3 changed files with 174 additions and 32 deletions

View File

@ -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> 2003-03-12 Nick Clifton <nickc@redhat.com>
* xsym.c (bfd_sym_fetch_type_information_table_entry): Change * xsym.c (bfd_sym_fetch_type_information_table_entry): Change

View File

@ -91,8 +91,14 @@ static void mips_elf64_info_to_howto_rela
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
static long mips_elf64_get_reloc_upper_bound static long mips_elf64_get_reloc_upper_bound
PARAMS ((bfd *, asection *)); 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 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 static bfd_boolean mips_elf64_slurp_reloc_table
PARAMS ((bfd *, asection *, asymbol **, bfd_boolean)); PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
static void mips_elf64_write_relocs 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 *); 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 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; bfd *abfd;
asection *asect; asection *asect;
Elf_Internal_Shdr *rel_hdr;
bfd_size_type reloc_count;
arelent *relents;
asymbol **symbols; asymbol **symbols;
const Elf_Internal_Shdr *rel_hdr; bfd_boolean dynamic;
{ {
PTR allocated = NULL; PTR allocated = NULL;
bfd_byte *native_relocs; bfd_byte *native_relocs;
arelent *relents;
arelent *relent; arelent *relent;
bfd_vma count;
bfd_vma i; bfd_vma i;
int entsize; int entsize;
reloc_howto_type *howto_table; reloc_howto_type *howto_table;
@ -2045,26 +2135,24 @@ mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, rel_hdr)
return FALSE; return FALSE;
if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0 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; goto error_return;
native_relocs = (bfd_byte *) allocated; native_relocs = (bfd_byte *) allocated;
relents = asect->relocation + asect->reloc_count;
entsize = rel_hdr->sh_entsize; entsize = rel_hdr->sh_entsize;
BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel) BFD_ASSERT (entsize == sizeof (Elf64_Mips_External_Rel)
|| entsize == sizeof (Elf64_Mips_External_Rela)); || entsize == sizeof (Elf64_Mips_External_Rela));
count = rel_hdr->sh_size / entsize;
if (entsize == sizeof (Elf64_Mips_External_Rel)) if (entsize == sizeof (Elf64_Mips_External_Rel))
howto_table = mips_elf64_howto_table_rel; howto_table = mips_elf64_howto_table_rel;
else else
howto_table = mips_elf64_howto_table_rela; howto_table = mips_elf64_howto_table_rela;
relent = relents; for (i = 0, relent = relents;
for (i = 0; i < count; i++, native_relocs += entsize) i < reloc_count;
i++, native_relocs += entsize)
{ {
Elf64_Mips_Internal_Rela rela; Elf64_Mips_Internal_Rela rela;
bfd_boolean used_sym, used_ssym; 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 object file, and absolute for an executable file or
shared library. The address of a BFD reloc is always shared library. The address of a BFD reloc is always
section relative. */ section relative. */
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
relent->address = rela.r_offset; relent->address = rela.r_offset;
else else
relent->address = rela.r_offset - asect->vma; 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 /* 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 static bfd_boolean
mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic) mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
@ -2202,39 +2293,72 @@ mips_elf64_slurp_reloc_table (abfd, asect, symbols, dynamic)
asymbol **symbols; asymbol **symbols;
bfd_boolean dynamic; bfd_boolean dynamic;
{ {
bfd_size_type amt;
struct bfd_elf_section_data * const d = elf_section_data (asect); 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) if (asect->relocation != NULL)
return TRUE;
if (! dynamic)
{ {
bfd_set_error (bfd_error_invalid_operation); if ((asect->flags & SEC_RELOC) == 0
return FALSE;
}
if (asect->relocation != NULL
|| (asect->flags & SEC_RELOC) == 0
|| asect->reloc_count == 0) || asect->reloc_count == 0)
return TRUE; 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. */ /* Allocate space for 3 arelent structures for each Rel structure. */
amt = asect->reloc_count; amt = (reloc_count + reloc_count2) * 3 * sizeof (arelent);
amt *= 3 * sizeof (arelent); relents = (arelent *) bfd_alloc (abfd, amt);
asect->relocation = (arelent *) bfd_alloc (abfd, amt); if (relents == NULL)
if (asect->relocation == NULL)
return FALSE; return FALSE;
/* The slurp_one_reloc_table routine increments reloc_count. */ /* The slurp_one_reloc_table routine increments reloc_count. */
asect->reloc_count = 0; 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; return FALSE;
if (d->rel_hdr2 != NULL) if (d->rel_hdr2 != NULL)
{ {
if (! mips_elf64_slurp_one_reloc_table (abfd, asect, symbols, if (! mips_elf64_slurp_one_reloc_table (abfd, asect,
d->rel_hdr2)) rel_hdr2, reloc_count2,
relents + reloc_count * 3,
symbols, dynamic))
return FALSE; return FALSE;
} }
asect->relocation = relents;
return TRUE; return TRUE;
} }
@ -2764,6 +2888,9 @@ const struct elf_size_info mips_elf64_size_info =
_bfd_mips_elf_print_private_bfd_data _bfd_mips_elf_print_private_bfd_data
#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound #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. */ /* MIPS ELF64 archive functions. */
#define bfd_elf64_archive_functions #define bfd_elf64_archive_functions

View File

@ -33,7 +33,9 @@
#endif #endif
#define bfd_elfNN_canonicalize_dynamic_symtab _bfd_elf_canonicalize_dynamic_symtab #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 #define bfd_elfNN_canonicalize_reloc _bfd_elf_canonicalize_reloc
#endif
#ifndef bfd_elfNN_find_nearest_line #ifndef bfd_elfNN_find_nearest_line
#define bfd_elfNN_find_nearest_line _bfd_elf_find_nearest_line #define bfd_elfNN_find_nearest_line _bfd_elf_find_nearest_line
#endif #endif