Add support for ELF files which contain multiple reloc sections which all target the same section.
* elf-bfd.h (struct elf_backend_data): Add new fields: init_secondary_reloc_section, slurp_secondary_reloc_section, write_secondary_reloc_section. (_bfd_elf_init_secondary_reloc_section): Prototype. (_bfd_elf_slurp_secondary_reloc_section): Prototype. (_bfd_elf_write_secondary_reloc_section): Prototype. * elf.c ( bfd_section_from_shdr): Invoke the new init_secondary_reloc_section backend function, if defined, when a second reloc section is encountered. (swap_out_syms): Invoke the new symbol_section_index function, if defined, when computing the section index of an OS/PROC specific symbol. (_bfd_elf_init_secondary_reloc_section): New function. (_bfd_elf_slurp_secondary_reloc_section): New function. (_bfd_elf_write_secondary_reloc_section): New function. (_bfd_elf_copy_special_section_fields): New function. * elfcode.h (elf_write_relocs): Invoke the new write_secondary_relocs function, if defined, in order to emit secondary relocs. (elf_slurp_reloc_table): Invoke the new slurp_secondary_relocs function, if defined, in order to read in secondary relocs. * elfxx-target.h (elf_backend_copy_special_section_fields): Provide a non-NULL default definition. (elf_backend_init_secondary_reloc_section): Likewise. (elf_backend_slurp_secondary_reloc_section): Likewise. (elf_backend_write_secondary_reloc_section): Likewise. (struct elf_backend_data elfNN_bed): Add initialisers for the new fields. * configure.ac (score_elf32_[bl]e_vec): Add elf64.lo * configure: Regenerate.
This commit is contained in:
parent
842806cb6f
commit
a8e14f4cc2
@ -1,3 +1,36 @@
|
|||||||
|
2020-03-05 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* elf-bfd.h (struct elf_backend_data): Add new fields:
|
||||||
|
init_secondary_reloc_section, slurp_secondary_reloc_section,
|
||||||
|
write_secondary_reloc_section.
|
||||||
|
(_bfd_elf_init_secondary_reloc_section): Prototype.
|
||||||
|
(_bfd_elf_slurp_secondary_reloc_section): Prototype.
|
||||||
|
(_bfd_elf_write_secondary_reloc_section): Prototype.
|
||||||
|
* elf.c ( bfd_section_from_shdr): Invoke the new
|
||||||
|
init_secondary_reloc_section backend function, if defined, when a
|
||||||
|
second reloc section is encountered.
|
||||||
|
(swap_out_syms): Invoke the new symbol_section_index function, if
|
||||||
|
defined, when computing the section index of an OS/PROC specific
|
||||||
|
symbol.
|
||||||
|
(_bfd_elf_init_secondary_reloc_section): New function.
|
||||||
|
(_bfd_elf_slurp_secondary_reloc_section): New function.
|
||||||
|
(_bfd_elf_write_secondary_reloc_section): New function.
|
||||||
|
(_bfd_elf_copy_special_section_fields): New function.
|
||||||
|
* elfcode.h (elf_write_relocs): Invoke the new
|
||||||
|
write_secondary_relocs function, if defined, in order to emit
|
||||||
|
secondary relocs.
|
||||||
|
(elf_slurp_reloc_table): Invoke the new slurp_secondary_relocs
|
||||||
|
function, if defined, in order to read in secondary relocs.
|
||||||
|
* elfxx-target.h (elf_backend_copy_special_section_fields):
|
||||||
|
Provide a non-NULL default definition.
|
||||||
|
(elf_backend_init_secondary_reloc_section): Likewise.
|
||||||
|
(elf_backend_slurp_secondary_reloc_section): Likewise.
|
||||||
|
(elf_backend_write_secondary_reloc_section): Likewise.
|
||||||
|
(struct elf_backend_data elfNN_bed): Add initialisers for the new
|
||||||
|
fields.
|
||||||
|
* configure.ac (score_elf32_[bl]e_vec): Add elf64.lo
|
||||||
|
* configure: Regenerate.
|
||||||
|
|
||||||
2020-03-05 Alan Modra <amodra@gmail.com>
|
2020-03-05 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* archive64.c (_bfd_archive_64_bit_slurp_armap): Check parsed_size
|
* archive64.c (_bfd_archive_64_bit_slurp_armap): Check parsed_size
|
||||||
|
4
bfd/configure
vendored
4
bfd/configure
vendored
@ -14887,8 +14887,8 @@ do
|
|||||||
rx_elf32_linux_le_vec) tb="$tb elf32-rx.lo elf32.lo $elf" ;;
|
rx_elf32_linux_le_vec) tb="$tb elf32-rx.lo elf32.lo $elf" ;;
|
||||||
s390_elf32_vec) tb="$tb elf32-s390.lo elf32.lo $elf" ;;
|
s390_elf32_vec) tb="$tb elf32-s390.lo elf32.lo $elf" ;;
|
||||||
s390_elf64_vec) tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
|
s390_elf64_vec) tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
|
||||||
score_elf32_be_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
|
score_elf32_be_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
|
||||||
score_elf32_le_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
|
score_elf32_le_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
|
||||||
sh_coff_vec) tb="$tb coff-sh.lo $coff" ;;
|
sh_coff_vec) tb="$tb coff-sh.lo $coff" ;;
|
||||||
sh_coff_le_vec) tb="$tb coff-sh.lo $coff" ;;
|
sh_coff_le_vec) tb="$tb coff-sh.lo $coff" ;;
|
||||||
sh_coff_small_vec) tb="$tb coff-sh.lo $coff" ;;
|
sh_coff_small_vec) tb="$tb coff-sh.lo $coff" ;;
|
||||||
|
@ -619,8 +619,8 @@ do
|
|||||||
rx_elf32_linux_le_vec) tb="$tb elf32-rx.lo elf32.lo $elf" ;;
|
rx_elf32_linux_le_vec) tb="$tb elf32-rx.lo elf32.lo $elf" ;;
|
||||||
s390_elf32_vec) tb="$tb elf32-s390.lo elf32.lo $elf" ;;
|
s390_elf32_vec) tb="$tb elf32-s390.lo elf32.lo $elf" ;;
|
||||||
s390_elf64_vec) tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
|
s390_elf64_vec) tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
|
||||||
score_elf32_be_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
|
score_elf32_be_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
|
||||||
score_elf32_le_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true; target_size=64 ;;
|
score_elf32_le_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
|
||||||
sh_coff_vec) tb="$tb coff-sh.lo $coff" ;;
|
sh_coff_vec) tb="$tb coff-sh.lo $coff" ;;
|
||||||
sh_coff_le_vec) tb="$tb coff-sh.lo $coff" ;;
|
sh_coff_le_vec) tb="$tb coff-sh.lo $coff" ;;
|
||||||
sh_coff_small_vec) tb="$tb coff-sh.lo $coff" ;;
|
sh_coff_small_vec) tb="$tb coff-sh.lo $coff" ;;
|
||||||
|
@ -1509,6 +1509,16 @@ struct elf_backend_data
|
|||||||
emitted symbol. If not defined, the value is left unchanged. */
|
emitted symbol. If not defined, the value is left unchanged. */
|
||||||
unsigned int (*symbol_section_index) (bfd *, elf_symbol_type *);
|
unsigned int (*symbol_section_index) (bfd *, elf_symbol_type *);
|
||||||
|
|
||||||
|
/* Called when a section has extra reloc sections. */
|
||||||
|
bfd_boolean (*init_secondary_reloc_section) (bfd *, Elf_Internal_Shdr *,
|
||||||
|
const char *, unsigned int);
|
||||||
|
|
||||||
|
/* Called when after loading the normal relocs for a section. */
|
||||||
|
bfd_boolean (*slurp_secondary_relocs) (bfd *, asection *, asymbol **);
|
||||||
|
|
||||||
|
/* Called after writing the normal relocs for a section. */
|
||||||
|
bfd_boolean (*write_secondary_relocs) (bfd *, asection *);
|
||||||
|
|
||||||
/* This is non-zero if static TLS segments require a special alignment. */
|
/* This is non-zero if static TLS segments require a special alignment. */
|
||||||
unsigned static_tls_alignment;
|
unsigned static_tls_alignment;
|
||||||
|
|
||||||
@ -2838,6 +2848,19 @@ extern bfd_vma elf32_r_sym (bfd_vma);
|
|||||||
|
|
||||||
extern bfd_boolean is_debuginfo_file (bfd *);
|
extern bfd_boolean is_debuginfo_file (bfd *);
|
||||||
|
|
||||||
|
|
||||||
|
extern bfd_boolean _bfd_elf_init_secondary_reloc_section
|
||||||
|
(bfd *, Elf_Internal_Shdr *, const char *, unsigned int);
|
||||||
|
extern bfd_boolean _bfd_elf_slurp_secondary_reloc_section
|
||||||
|
(bfd *, asection *, asymbol **);
|
||||||
|
extern bfd_boolean _bfd_elf_copy_special_section_fields
|
||||||
|
(const bfd *, bfd *, const Elf_Internal_Shdr *, Elf_Internal_Shdr *);
|
||||||
|
extern bfd_boolean _bfd_elf_write_secondary_reloc_section
|
||||||
|
(bfd *, asection *);
|
||||||
|
extern unsigned int _bfd_elf_symbol_section_index
|
||||||
|
(bfd *, elf_symbol_type *);
|
||||||
|
|
||||||
|
|
||||||
/* Large common section. */
|
/* Large common section. */
|
||||||
extern asection _bfd_elf_large_com_section;
|
extern asection _bfd_elf_large_com_section;
|
||||||
|
|
||||||
|
377
bfd/elf.c
377
bfd/elf.c
@ -1607,7 +1607,7 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
|
|||||||
/* Final attempt. Call the backend copy function
|
/* Final attempt. Call the backend copy function
|
||||||
with a NULL input section. */
|
with a NULL input section. */
|
||||||
if (bed->elf_backend_copy_special_section_fields != NULL)
|
if (bed->elf_backend_copy_special_section_fields != NULL)
|
||||||
bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
|
(void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2458,13 +2458,17 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
|
|||||||
sections. */
|
sections. */
|
||||||
if (*p_hdr != NULL)
|
if (*p_hdr != NULL)
|
||||||
{
|
{
|
||||||
_bfd_error_handler
|
if (bed->init_secondary_reloc_section == NULL
|
||||||
/* xgettext:c-format */
|
|| ! bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
|
||||||
(_("%pB: warning: multiple relocation sections for section %pA \
|
{
|
||||||
found - ignoring all but the first"),
|
_bfd_error_handler
|
||||||
abfd, target_sect);
|
/* xgettext:c-format */
|
||||||
|
(_("%pB: warning: secondary relocation section '%s' for section %pA found - ignoring"),
|
||||||
|
abfd, name, target_sect);
|
||||||
|
}
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
|
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2));
|
||||||
if (hdr2 == NULL)
|
if (hdr2 == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -12308,3 +12312,364 @@ _bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec,
|
|||||||
size = 1;
|
size = 1;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set to non-zero to enable some debug messages. */
|
||||||
|
#define DEBUG_SECONDARY_RELOCS 0
|
||||||
|
|
||||||
|
/* An internal-to-the-bfd-library only section type
|
||||||
|
used to indicate a cached secondary reloc section. */
|
||||||
|
#define SHT_SECONDARY_RELOC (SHT_LOOS + SHT_RELA)
|
||||||
|
|
||||||
|
/* Create a BFD section to hold a secondary reloc section. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
_bfd_elf_init_secondary_reloc_section (bfd * abfd,
|
||||||
|
Elf_Internal_Shdr *hdr,
|
||||||
|
const char * name,
|
||||||
|
unsigned int shindex)
|
||||||
|
{
|
||||||
|
/* We only support RELA secondary relocs. */
|
||||||
|
if (hdr->sh_type != SHT_RELA)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "secondary reloc section %s encountered\n", name);
|
||||||
|
#endif
|
||||||
|
hdr->sh_type = SHT_SECONDARY_RELOC;
|
||||||
|
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read in any secondary relocs associated with SEC. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
_bfd_elf_slurp_secondary_reloc_section (bfd * abfd,
|
||||||
|
asection * sec,
|
||||||
|
asymbol ** symbols)
|
||||||
|
{
|
||||||
|
const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
|
||||||
|
asection * relsec;
|
||||||
|
bfd_boolean result = TRUE;
|
||||||
|
bfd_vma (*r_sym) (bfd_vma);
|
||||||
|
|
||||||
|
#if BFD_DEFAULT_TARGET_SIZE > 32
|
||||||
|
if (bfd_arch_bits_per_address (abfd) != 32)
|
||||||
|
r_sym = elf64_r_sym;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
r_sym = elf32_r_sym;
|
||||||
|
|
||||||
|
/* Discover if there are any secondary reloc sections
|
||||||
|
associated with SEC. */
|
||||||
|
for (relsec = abfd->sections; relsec != NULL; relsec = relsec->next)
|
||||||
|
{
|
||||||
|
Elf_Internal_Shdr * hdr = & elf_section_data (relsec)->this_hdr;
|
||||||
|
|
||||||
|
if (hdr->sh_type == SHT_SECONDARY_RELOC
|
||||||
|
&& hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx)
|
||||||
|
{
|
||||||
|
bfd_byte * native_relocs;
|
||||||
|
bfd_byte * native_reloc;
|
||||||
|
arelent * internal_relocs;
|
||||||
|
arelent * internal_reloc;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int entsize;
|
||||||
|
unsigned int symcount;
|
||||||
|
unsigned int reloc_count;
|
||||||
|
size_t amt;
|
||||||
|
|
||||||
|
if (ebd->elf_info_to_howto == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "read secondary relocs for %s from %s\n",
|
||||||
|
sec->name, relsec->name);
|
||||||
|
#endif
|
||||||
|
entsize = hdr->sh_entsize;
|
||||||
|
|
||||||
|
native_relocs = bfd_malloc (hdr->sh_size);
|
||||||
|
if (native_relocs == NULL)
|
||||||
|
{
|
||||||
|
result = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
reloc_count = NUM_SHDR_ENTRIES (hdr);
|
||||||
|
if (_bfd_mul_overflow (reloc_count, sizeof (arelent), & amt))
|
||||||
|
{
|
||||||
|
bfd_set_error (bfd_error_file_too_big);
|
||||||
|
result = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_relocs = (arelent *) bfd_alloc (abfd, amt);
|
||||||
|
if (internal_relocs == NULL)
|
||||||
|
{
|
||||||
|
free (native_relocs);
|
||||||
|
result = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|
||||||
|
|| (bfd_bread (native_relocs, hdr->sh_size, abfd)
|
||||||
|
!= hdr->sh_size))
|
||||||
|
{
|
||||||
|
free (native_relocs);
|
||||||
|
free (internal_relocs);
|
||||||
|
result = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
symcount = bfd_get_symcount (abfd);
|
||||||
|
|
||||||
|
for (i = 0, internal_reloc = internal_relocs,
|
||||||
|
native_reloc = native_relocs;
|
||||||
|
i < reloc_count;
|
||||||
|
i++, internal_reloc++, native_reloc += entsize)
|
||||||
|
{
|
||||||
|
bfd_boolean res;
|
||||||
|
Elf_Internal_Rela rela;
|
||||||
|
|
||||||
|
ebd->s->swap_reloca_in (abfd, native_reloc, & rela);
|
||||||
|
|
||||||
|
/* The address of an ELF reloc is section relative for an object
|
||||||
|
file, and absolute for an executable file or shared library.
|
||||||
|
The address of a normal BFD reloc is always section relative,
|
||||||
|
and the address of a dynamic reloc is absolute.. */
|
||||||
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
|
||||||
|
internal_reloc->address = rela.r_offset;
|
||||||
|
else
|
||||||
|
internal_reloc->address = rela.r_offset - sec->vma;
|
||||||
|
|
||||||
|
if (r_sym (rela.r_info) == STN_UNDEF)
|
||||||
|
{
|
||||||
|
/* FIXME: This and the error case below mean that we
|
||||||
|
have a symbol on relocs that is not elf_symbol_type. */
|
||||||
|
internal_reloc->sym_ptr_ptr =
|
||||||
|
bfd_abs_section_ptr->symbol_ptr_ptr;
|
||||||
|
}
|
||||||
|
else if (r_sym (rela.r_info) > symcount)
|
||||||
|
{
|
||||||
|
_bfd_error_handler
|
||||||
|
/* xgettext:c-format */
|
||||||
|
(_("%pB(%pA): relocation %d has invalid symbol index %ld"),
|
||||||
|
abfd, sec, i, (long) r_sym (rela.r_info));
|
||||||
|
bfd_set_error (bfd_error_bad_value);
|
||||||
|
internal_reloc->sym_ptr_ptr =
|
||||||
|
bfd_abs_section_ptr->symbol_ptr_ptr;
|
||||||
|
result = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asymbol **ps;
|
||||||
|
|
||||||
|
ps = symbols + r_sym (rela.r_info) - 1;
|
||||||
|
|
||||||
|
internal_reloc->sym_ptr_ptr = ps;
|
||||||
|
/* Make sure that this symbol is not removed by strip. */
|
||||||
|
(*ps)->flags |= BSF_KEEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_reloc->addend = rela.r_addend;
|
||||||
|
|
||||||
|
res = ebd->elf_info_to_howto (abfd, internal_reloc, & rela);
|
||||||
|
if (! res || internal_reloc->howto == NULL)
|
||||||
|
{
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "there is no howto associated with reloc %lx\n",
|
||||||
|
rela.r_info);
|
||||||
|
#endif
|
||||||
|
result = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free (native_relocs);
|
||||||
|
/* Store the internal relocs. */
|
||||||
|
elf_section_data (relsec)->sec_info = internal_relocs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the ELF section header fields of an output secondary reloc section. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
_bfd_elf_copy_special_section_fields (const bfd * ibfd ATTRIBUTE_UNUSED,
|
||||||
|
bfd * obfd ATTRIBUTE_UNUSED,
|
||||||
|
const Elf_Internal_Shdr * isection,
|
||||||
|
Elf_Internal_Shdr * osection)
|
||||||
|
{
|
||||||
|
asection * isec;
|
||||||
|
asection * osec;
|
||||||
|
|
||||||
|
if (isection == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (isection->sh_type != SHT_SECONDARY_RELOC)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
isec = isection->bfd_section;
|
||||||
|
if (isec == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
osec = osection->bfd_section;
|
||||||
|
if (osec == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
BFD_ASSERT (elf_section_data (osec)->sec_info == NULL);
|
||||||
|
elf_section_data (osec)->sec_info = elf_section_data (isec)->sec_info;
|
||||||
|
osection->sh_type = SHT_RELA;
|
||||||
|
osection->sh_link = elf_onesymtab (obfd);
|
||||||
|
if (osection->sh_link == 0)
|
||||||
|
{
|
||||||
|
/* There is no symbol table - we are hosed... */
|
||||||
|
_bfd_error_handler
|
||||||
|
/* xgettext:c-format */
|
||||||
|
(_("%pB(%pA): link section cannot be set because the output file does not have a symbol table"),
|
||||||
|
obfd, osec);
|
||||||
|
bfd_set_error (bfd_error_bad_value);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the output section that corresponds to the isection's sh_info link. */
|
||||||
|
BFD_ASSERT (isection->sh_info > 0
|
||||||
|
&& isection->sh_info < elf_numsections (ibfd));
|
||||||
|
isection = elf_elfsections (ibfd)[isection->sh_info];
|
||||||
|
|
||||||
|
BFD_ASSERT (isection != NULL);
|
||||||
|
BFD_ASSERT (isection->bfd_section != NULL);
|
||||||
|
BFD_ASSERT (isection->bfd_section->output_section != NULL);
|
||||||
|
osection->sh_info =
|
||||||
|
elf_section_data (isection->bfd_section->output_section)->this_idx;
|
||||||
|
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "update header of %s, sh_link = %u, sh_info = %u\n",
|
||||||
|
osec->name, osection->sh_link, osection->sh_info);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out a secondary reloc section. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
_bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
|
||||||
|
{
|
||||||
|
const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
|
||||||
|
bfd_vma addr_offset;
|
||||||
|
asection * relsec;
|
||||||
|
bfd_vma (*r_info) (bfd_vma, bfd_vma);
|
||||||
|
|
||||||
|
#if BFD_DEFAULT_TARGET_SIZE > 32
|
||||||
|
if (bfd_arch_bits_per_address (abfd) != 32)
|
||||||
|
r_info = elf64_r_info;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
r_info = elf32_r_info;
|
||||||
|
|
||||||
|
if (sec == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* The address of an ELF reloc is section relative for an object
|
||||||
|
file, and absolute for an executable file or shared library.
|
||||||
|
The address of a BFD reloc is always section relative. */
|
||||||
|
addr_offset = 0;
|
||||||
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
|
||||||
|
addr_offset = sec->vma;
|
||||||
|
|
||||||
|
/* Discover if there are any secondary reloc sections
|
||||||
|
associated with SEC. */
|
||||||
|
for (relsec = abfd->sections; relsec != NULL; relsec = relsec->next)
|
||||||
|
{
|
||||||
|
const struct bfd_elf_section_data * const esd = elf_section_data (relsec);
|
||||||
|
Elf_Internal_Shdr * const hdr = (Elf_Internal_Shdr *) & esd->this_hdr;
|
||||||
|
|
||||||
|
if (hdr->sh_type == SHT_RELA
|
||||||
|
&& hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx)
|
||||||
|
{
|
||||||
|
asymbol * last_sym;
|
||||||
|
int last_sym_idx;
|
||||||
|
unsigned int reloc_count;
|
||||||
|
unsigned int idx;
|
||||||
|
arelent * src_irel;
|
||||||
|
bfd_byte * dst_rela;
|
||||||
|
|
||||||
|
BFD_ASSERT (hdr->contents == NULL);
|
||||||
|
|
||||||
|
reloc_count = hdr->sh_size / hdr->sh_entsize;
|
||||||
|
BFD_ASSERT (reloc_count > 0);
|
||||||
|
|
||||||
|
hdr->contents = bfd_alloc (abfd, hdr->sh_size);
|
||||||
|
if (hdr->contents == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "write %u secondary relocs for %s from %s\n",
|
||||||
|
reloc_count, sec->name, relsec->name);
|
||||||
|
#endif
|
||||||
|
last_sym = NULL;
|
||||||
|
last_sym_idx = 0;
|
||||||
|
dst_rela = hdr->contents;
|
||||||
|
src_irel = (arelent *) esd->sec_info;
|
||||||
|
BFD_ASSERT (src_irel != NULL);
|
||||||
|
|
||||||
|
for (idx = 0; idx < reloc_count; idx++, dst_rela += hdr->sh_entsize)
|
||||||
|
{
|
||||||
|
Elf_Internal_Rela src_rela;
|
||||||
|
arelent *ptr;
|
||||||
|
asymbol *sym;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ptr = src_irel + idx;
|
||||||
|
sym = *ptr->sym_ptr_ptr;
|
||||||
|
|
||||||
|
if (sym == last_sym)
|
||||||
|
n = last_sym_idx;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_sym = sym;
|
||||||
|
n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym);
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "failed to find symbol %s whilst rewriting relocs\n",
|
||||||
|
sym->name);
|
||||||
|
#endif
|
||||||
|
/* FIXME: Signal failure somehow. */
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
last_sym_idx = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
|
||||||
|
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
|
||||||
|
&& ! _bfd_elf_validate_reloc (abfd, ptr))
|
||||||
|
{
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "symbol %s is not in the output bfd\n",
|
||||||
|
sym->name);
|
||||||
|
#endif
|
||||||
|
/* FIXME: Signal failure somehow. */
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->howto == NULL)
|
||||||
|
{
|
||||||
|
#if DEBUG_SECONDARY_RELOCS
|
||||||
|
fprintf (stderr, "reloc for symbol %s does not have a howto associated with it\n",
|
||||||
|
sym->name);
|
||||||
|
#endif
|
||||||
|
/* FIXME: Signal failure somehow. */
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_rela.r_offset = ptr->address + addr_offset;
|
||||||
|
src_rela.r_info = r_info (n, ptr->howto->type);
|
||||||
|
src_rela.r_addend = ptr->addend;
|
||||||
|
ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -869,6 +869,7 @@ elf_object_p (bfd *abfd)
|
|||||||
void
|
void
|
||||||
elf_write_relocs (bfd *abfd, asection *sec, void *data)
|
elf_write_relocs (bfd *abfd, asection *sec, void *data)
|
||||||
{
|
{
|
||||||
|
const struct elf_backend_data * const bed = get_elf_backend_data (abfd);
|
||||||
bfd_boolean *failedp = (bfd_boolean *) data;
|
bfd_boolean *failedp = (bfd_boolean *) data;
|
||||||
Elf_Internal_Shdr *rela_hdr;
|
Elf_Internal_Shdr *rela_hdr;
|
||||||
bfd_vma addr_offset;
|
bfd_vma addr_offset;
|
||||||
@ -985,6 +986,13 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
|
|||||||
src_rela.r_addend = ptr->addend;
|
src_rela.r_addend = ptr->addend;
|
||||||
(*swap_out) (abfd, &src_rela, dst_rela);
|
(*swap_out) (abfd, &src_rela, dst_rela);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bed->write_secondary_relocs != NULL)
|
||||||
|
if (! bed->write_secondary_relocs (abfd, sec))
|
||||||
|
{
|
||||||
|
*failedp = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write out the program headers. */
|
/* Write out the program headers. */
|
||||||
@ -1292,7 +1300,10 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
|
|||||||
{
|
{
|
||||||
/* This symbol is in a section for which we did not
|
/* This symbol is in a section for which we did not
|
||||||
create a BFD section. Just use bfd_abs_section,
|
create a BFD section. Just use bfd_abs_section,
|
||||||
although it is wrong. FIXME. */
|
although it is wrong. FIXME. Note - there is
|
||||||
|
code in elf.c:swap_out_syms that calls
|
||||||
|
symbol_section_index() in the elf backend for
|
||||||
|
cases like this. */
|
||||||
sym->symbol.section = bfd_abs_section_ptr;
|
sym->symbol.section = bfd_abs_section_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1517,6 +1528,7 @@ elf_slurp_reloc_table (bfd *abfd,
|
|||||||
asymbol **symbols,
|
asymbol **symbols,
|
||||||
bfd_boolean dynamic)
|
bfd_boolean dynamic)
|
||||||
{
|
{
|
||||||
|
const struct elf_backend_data * const bed = get_elf_backend_data (abfd);
|
||||||
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_hdr;
|
||||||
Elf_Internal_Shdr *rel_hdr2;
|
Elf_Internal_Shdr *rel_hdr2;
|
||||||
@ -1584,6 +1596,10 @@ elf_slurp_reloc_table (bfd *abfd,
|
|||||||
symbols, dynamic))
|
symbols, dynamic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (bed->slurp_secondary_relocs != NULL
|
||||||
|
&& ! bed->slurp_secondary_relocs (abfd, asect, symbols))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
asect->relocation = relents;
|
asect->relocation = relents;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -758,7 +758,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef elf_backend_copy_special_section_fields
|
#ifndef elf_backend_copy_special_section_fields
|
||||||
#define elf_backend_copy_special_section_fields NULL
|
#define elf_backend_copy_special_section_fields _bfd_elf_copy_special_section_fields
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef elf_backend_compact_eh_encoding
|
#ifndef elf_backend_compact_eh_encoding
|
||||||
@ -766,7 +766,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef elf_backend_cant_unwind_opcode
|
#ifndef elf_backend_cant_unwind_opcode
|
||||||
#define elf_backend_cant_unwind_opcode 0
|
#define elf_backend_cant_unwind_opcode NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef elf_backend_init_secondary_reloc_section
|
||||||
|
#define elf_backend_init_secondary_reloc_section _bfd_elf_init_secondary_reloc_section
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef elf_backend_slurp_secondary_reloc_section
|
||||||
|
#define elf_backend_slurp_secondary_reloc_section _bfd_elf_slurp_secondary_reloc_section
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef elf_backend_write_secondary_reloc_section
|
||||||
|
#define elf_backend_write_secondary_reloc_section _bfd_elf_write_secondary_reloc_section
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef elf_backend_symbol_section_index
|
#ifndef elf_backend_symbol_section_index
|
||||||
@ -900,6 +912,9 @@ static struct elf_backend_data elfNN_bed =
|
|||||||
elf_backend_compact_eh_encoding,
|
elf_backend_compact_eh_encoding,
|
||||||
elf_backend_cant_unwind_opcode,
|
elf_backend_cant_unwind_opcode,
|
||||||
elf_backend_symbol_section_index,
|
elf_backend_symbol_section_index,
|
||||||
|
elf_backend_init_secondary_reloc_section,
|
||||||
|
elf_backend_slurp_secondary_reloc_section,
|
||||||
|
elf_backend_write_secondary_reloc_section,
|
||||||
elf_backend_static_tls_alignment,
|
elf_backend_static_tls_alignment,
|
||||||
elf_backend_stack_align,
|
elf_backend_stack_align,
|
||||||
elf_backend_strtab_flags,
|
elf_backend_strtab_flags,
|
||||||
|
Loading…
Reference in New Issue
Block a user