mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-19 17:18:24 +08:00
* elf-hppa.h (elf_hppa_final_link): Use elf_hppa_final_link.
(elf_hppa_final_link_relocate ): Rewrite eliminating dynamic hash table. (elf_hppa_relocate_section): Likewise. * elf64-hppa.c (struct elf64_hppa_link_hash_entry): Change to derive from struct elf_link_hash_entry. Add count field. (struct elf64_hppa_dyn_hash_table): Delete. (struct elf64_hppa_link_hash_table): Delete dyn_hash_table field. (elf64_hppa_hash_table): Rename to hppa_link_hash_table. (hppa_elf_hash_entry, eh_name): Define. (elf64_hppa_new_dyn_hash_entry): Delete. (elf64_hppa_dyn_hash_lookup): Delete. (elf64_hppa_dyn_hash_traverse): Delete. (get_dyn_name): Delete. (elf64_hppa_finalize_opd): Use struct elf_link_hash_entry * instead of struct elf64_hppa_dyn_hash_entry *. (elf64_hppa_finalize_dlt, llocate_global_data_dlt, allocate_global_data_plt, allocate_global_data_stub, allocate_global_data_opd, count_dyn_reloc, allocate_dynrel_entries): Likewise. (hppa64_link_hash_newfunc): New. (elf64_hppa_hash_table_create): Rework. (count_dyn_reloc): Likewise. (hppa64_elf_local_refcounts): New. (elf64_hppa_check_relocs): Rework using standard technique for recording local DLT, PLT and OPD reference counts. (elf64_hppa_dynamic_symbol_p): Revise using "eh" for struct elf_link_hash_entry *. (elf64_hppa_mark_exported_functions, allocate_global_data_dlt, allocate_global_data_plt, allocate_global_data_stub, allocate_global_data_opd, allocate_dynrel_entries, elf64_hppa_adjust_dynamic_symbol, elf64_hppa_mark_milli_and_exported_functions): Likewise. (elf64_hppa_create_dynamic_sections, elf64_hppa_size_dynamic_sections): Use hppa_link_hash_table. Rework. (elf64_hppa_link_output_symbol_hook): Rework. (elf64_hppa_finish_dynamic_symbol, elf64_hppa_finalize_opd, elf64_hppa_finalize_dlt, elf64_hppa_finalize_dynreloc, elf64_hppa_finish_dynamic_sections): Likewise.
This commit is contained in:
@ -1,3 +1,44 @@
|
|||||||
|
2009-02-28 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||||
|
|
||||||
|
* elf-hppa.h (elf_hppa_final_link): Use elf_hppa_final_link.
|
||||||
|
(elf_hppa_final_link_relocate ): Rewrite eliminating dynamic hash table.
|
||||||
|
(elf_hppa_relocate_section): Likewise.
|
||||||
|
* elf64-hppa.c (struct elf64_hppa_link_hash_entry): Change to derive
|
||||||
|
from struct elf_link_hash_entry. Add count field.
|
||||||
|
(struct elf64_hppa_dyn_hash_table): Delete.
|
||||||
|
(struct elf64_hppa_link_hash_table): Delete dyn_hash_table field.
|
||||||
|
(elf64_hppa_hash_table): Rename to hppa_link_hash_table.
|
||||||
|
(hppa_elf_hash_entry, eh_name): Define.
|
||||||
|
(elf64_hppa_new_dyn_hash_entry): Delete.
|
||||||
|
(elf64_hppa_dyn_hash_lookup): Delete.
|
||||||
|
(elf64_hppa_dyn_hash_traverse): Delete.
|
||||||
|
(get_dyn_name): Delete.
|
||||||
|
(elf64_hppa_finalize_opd): Use struct elf_link_hash_entry * instead
|
||||||
|
of struct elf64_hppa_dyn_hash_entry *.
|
||||||
|
(elf64_hppa_finalize_dlt, llocate_global_data_dlt,
|
||||||
|
allocate_global_data_plt, allocate_global_data_stub,
|
||||||
|
allocate_global_data_opd, count_dyn_reloc, allocate_dynrel_entries):
|
||||||
|
Likewise.
|
||||||
|
(hppa64_link_hash_newfunc): New.
|
||||||
|
(elf64_hppa_hash_table_create): Rework.
|
||||||
|
(count_dyn_reloc): Likewise.
|
||||||
|
(hppa64_elf_local_refcounts): New.
|
||||||
|
(elf64_hppa_check_relocs): Rework using standard technique for recording
|
||||||
|
local DLT, PLT and OPD reference counts.
|
||||||
|
(elf64_hppa_dynamic_symbol_p): Revise using "eh" for struct
|
||||||
|
elf_link_hash_entry *.
|
||||||
|
(elf64_hppa_mark_exported_functions, allocate_global_data_dlt,
|
||||||
|
allocate_global_data_plt, allocate_global_data_stub,
|
||||||
|
allocate_global_data_opd, allocate_dynrel_entries,
|
||||||
|
elf64_hppa_adjust_dynamic_symbol,
|
||||||
|
elf64_hppa_mark_milli_and_exported_functions): Likewise.
|
||||||
|
(elf64_hppa_create_dynamic_sections, elf64_hppa_size_dynamic_sections):
|
||||||
|
Use hppa_link_hash_table. Rework.
|
||||||
|
(elf64_hppa_link_output_symbol_hook): Rework.
|
||||||
|
(elf64_hppa_finish_dynamic_symbol, elf64_hppa_finalize_opd,
|
||||||
|
elf64_hppa_finalize_dlt, elf64_hppa_finalize_dynreloc,
|
||||||
|
elf64_hppa_finish_dynamic_sections): Likewise.
|
||||||
|
|
||||||
2009-02-26 Christophe Lyon <christophe.lyon@st.com>
|
2009-02-26 Christophe Lyon <christophe.lyon@st.com>
|
||||||
|
|
||||||
* elf32-arm.c (stub_reloc_type): Removed.
|
* elf32-arm.c (stub_reloc_type): Removed.
|
||||||
|
320
bfd/elf-hppa.h
320
bfd/elf-hppa.h
@ -1,5 +1,5 @@
|
|||||||
/* Common code for PA ELF implementations.
|
/* Common code for PA ELF implementations.
|
||||||
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
||||||
@ -1378,7 +1378,7 @@ static bfd_boolean
|
|||||||
elf_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
|
elf_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||||
{
|
{
|
||||||
bfd_boolean retval;
|
bfd_boolean retval;
|
||||||
struct elf64_hppa_link_hash_table *hppa_info = elf64_hppa_hash_table (info);
|
struct elf64_hppa_link_hash_table *hppa_info = hppa_link_hash_table (info);
|
||||||
|
|
||||||
if (! info->relocatable)
|
if (! info->relocatable)
|
||||||
{
|
{
|
||||||
@ -1606,18 +1606,23 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
bfd_vma value,
|
bfd_vma value,
|
||||||
struct bfd_link_info *info,
|
struct bfd_link_info *info,
|
||||||
asection *sym_sec,
|
asection *sym_sec,
|
||||||
struct elf_link_hash_entry *h,
|
struct elf_link_hash_entry *eh)
|
||||||
struct elf64_hppa_dyn_hash_entry *dyn_h)
|
|
||||||
{
|
{
|
||||||
|
struct elf64_hppa_link_hash_table *hppa_info = hppa_link_hash_table (info);
|
||||||
|
struct elf64_hppa_link_hash_entry *hh = hppa_elf_hash_entry (eh);
|
||||||
|
bfd_vma *local_offsets;
|
||||||
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
int insn;
|
int insn;
|
||||||
bfd_vma max_branch_offset = 0;
|
bfd_vma max_branch_offset = 0;
|
||||||
bfd_vma offset = rel->r_offset;
|
bfd_vma offset = rel->r_offset;
|
||||||
bfd_signed_vma addend = rel->r_addend;
|
bfd_signed_vma addend = rel->r_addend;
|
||||||
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
|
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
|
||||||
|
unsigned int r_symndx = ELF_R_SYM (rel->r_info);
|
||||||
unsigned int r_type = howto->type;
|
unsigned int r_type = howto->type;
|
||||||
bfd_byte *hit_data = contents + offset;
|
bfd_byte *hit_data = contents + offset;
|
||||||
struct elf64_hppa_link_hash_table *hppa_info = elf64_hppa_hash_table (info);
|
|
||||||
|
|
||||||
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||||
|
local_offsets = elf_local_got_offsets (input_bfd);
|
||||||
insn = bfd_get_32 (input_bfd, hit_data);
|
insn = bfd_get_32 (input_bfd, hit_data);
|
||||||
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
@ -1644,7 +1649,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
library, then redirect the call to the local stub for this
|
library, then redirect the call to the local stub for this
|
||||||
function. */
|
function. */
|
||||||
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
||||||
value = (dyn_h->stub_offset + hppa_info->stub_sec->output_offset
|
value = (hh->stub_offset + hppa_info->stub_sec->output_offset
|
||||||
+ hppa_info->stub_sec->output_section->vma);
|
+ hppa_info->stub_sec->output_section->vma);
|
||||||
|
|
||||||
/* Turn VALUE into a proper PC relative address. */
|
/* Turn VALUE into a proper PC relative address. */
|
||||||
@ -1678,7 +1683,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
library, then redirect the call to the local stub for this
|
library, then redirect the call to the local stub for this
|
||||||
function. */
|
function. */
|
||||||
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
||||||
value = (dyn_h->stub_offset + hppa_info->stub_sec->output_offset
|
value = (hh->stub_offset + hppa_info->stub_sec->output_offset
|
||||||
+ hppa_info->stub_sec->output_section->vma);
|
+ hppa_info->stub_sec->output_section->vma);
|
||||||
|
|
||||||
/* Turn VALUE into a proper PC relative address. */
|
/* Turn VALUE into a proper PC relative address. */
|
||||||
@ -1702,7 +1707,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
input_bfd,
|
input_bfd,
|
||||||
input_section,
|
input_section,
|
||||||
offset,
|
offset,
|
||||||
h->root.root.string);
|
eh->root.root.string);
|
||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
return bfd_reloc_notsupported;
|
return bfd_reloc_notsupported;
|
||||||
}
|
}
|
||||||
@ -1746,6 +1751,8 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
case R_PARISC_LTOFF16WF:
|
case R_PARISC_LTOFF16WF:
|
||||||
case R_PARISC_LTOFF16DF:
|
case R_PARISC_LTOFF16DF:
|
||||||
{
|
{
|
||||||
|
bfd_vma off;
|
||||||
|
|
||||||
/* If this relocation was against a local symbol, then we still
|
/* If this relocation was against a local symbol, then we still
|
||||||
have not set up the DLT entry (it's not convenient to do so
|
have not set up the DLT entry (it's not convenient to do so
|
||||||
in the "finalize_dlt" routine because it is difficult to get
|
in the "finalize_dlt" routine because it is difficult to get
|
||||||
@ -1756,8 +1763,13 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
|
|
||||||
Similarly we may still need to set up an entry in .opd for
|
Similarly we may still need to set up an entry in .opd for
|
||||||
a local function which had its address taken. */
|
a local function which had its address taken. */
|
||||||
if (dyn_h->h == NULL)
|
if (hh == NULL)
|
||||||
{
|
{
|
||||||
|
bfd_vma *local_opd_offsets, *local_dlt_offsets;
|
||||||
|
|
||||||
|
if (local_offsets == NULL)
|
||||||
|
abort ();
|
||||||
|
|
||||||
/* Now do .opd creation if needed. */
|
/* Now do .opd creation if needed. */
|
||||||
if (r_type == R_PARISC_LTOFF_FPTR14R
|
if (r_type == R_PARISC_LTOFF_FPTR14R
|
||||||
|| r_type == R_PARISC_LTOFF_FPTR14DR
|
|| r_type == R_PARISC_LTOFF_FPTR14DR
|
||||||
@ -1767,39 +1779,65 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
|| r_type == R_PARISC_LTOFF_FPTR16WF
|
|| r_type == R_PARISC_LTOFF_FPTR16WF
|
||||||
|| r_type == R_PARISC_LTOFF_FPTR16DF)
|
|| r_type == R_PARISC_LTOFF_FPTR16DF)
|
||||||
{
|
{
|
||||||
|
local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info;
|
||||||
|
off = local_opd_offsets[r_symndx];
|
||||||
|
|
||||||
|
/* The last bit records whether we've already initialised
|
||||||
|
this local .opd entry. */
|
||||||
|
if ((off & 1) != 0)
|
||||||
|
{
|
||||||
|
BFD_ASSERT (off != (bfd_vma) -1);
|
||||||
|
off &= ~1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
local_opd_offsets[r_symndx] |= 1;
|
||||||
|
|
||||||
/* The first two words of an .opd entry are zero. */
|
/* The first two words of an .opd entry are zero. */
|
||||||
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset,
|
memset (hppa_info->opd_sec->contents + off, 0, 16);
|
||||||
0, 16);
|
|
||||||
|
|
||||||
/* The next word is the address of the function. */
|
/* The next word is the address of the function. */
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||||
(hppa_info->opd_sec->contents
|
(hppa_info->opd_sec->contents + off + 16));
|
||||||
+ dyn_h->opd_offset + 16));
|
|
||||||
|
|
||||||
/* The last word is our local __gp value. */
|
/* The last word is our local __gp value. */
|
||||||
value = _bfd_get_gp_value
|
value = _bfd_get_gp_value
|
||||||
(hppa_info->opd_sec->output_section->owner);
|
(hppa_info->opd_sec->output_section->owner);
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||||
(hppa_info->opd_sec->contents
|
(hppa_info->opd_sec->contents + off + 24));
|
||||||
+ dyn_h->opd_offset + 24));
|
}
|
||||||
|
|
||||||
/* The DLT value is the address of the .opd entry. */
|
/* The DLT value is the address of the .opd entry. */
|
||||||
value = (dyn_h->opd_offset
|
value = (off
|
||||||
+ hppa_info->opd_sec->output_offset
|
+ hppa_info->opd_sec->output_offset
|
||||||
+ hppa_info->opd_sec->output_section->vma);
|
+ hppa_info->opd_sec->output_section->vma);
|
||||||
addend = 0;
|
addend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_dlt_offsets = local_offsets;
|
||||||
|
off = local_dlt_offsets[r_symndx];
|
||||||
|
|
||||||
|
if ((off & 1) != 0)
|
||||||
|
{
|
||||||
|
BFD_ASSERT (off != (bfd_vma) -1);
|
||||||
|
off &= ~1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
local_dlt_offsets[r_symndx] |= 1;
|
||||||
bfd_put_64 (hppa_info->dlt_sec->owner,
|
bfd_put_64 (hppa_info->dlt_sec->owner,
|
||||||
value + addend,
|
value + addend,
|
||||||
hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
|
hppa_info->dlt_sec->contents + off);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
off = hh->dlt_offset;
|
||||||
|
|
||||||
/* We want the value of the DLT offset for this symbol, not
|
/* We want the value of the DLT offset for this symbol, not
|
||||||
the symbol's actual address. Note that __gp may not point
|
the symbol's actual address. Note that __gp may not point
|
||||||
to the start of the DLT, so we have to compute the absolute
|
to the start of the DLT, so we have to compute the absolute
|
||||||
address, then subtract out the value of __gp. */
|
address, then subtract out the value of __gp. */
|
||||||
value = (dyn_h->dlt_offset
|
value = (off
|
||||||
+ hppa_info->dlt_sec->output_offset
|
+ hppa_info->dlt_sec->output_offset
|
||||||
+ hppa_info->dlt_sec->output_section->vma);
|
+ hppa_info->dlt_sec->output_section->vma);
|
||||||
value -= _bfd_get_gp_value (output_bfd);
|
value -= _bfd_get_gp_value (output_bfd);
|
||||||
@ -1914,7 +1952,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
the symbol's actual address. Note that __gp may not point
|
the symbol's actual address. Note that __gp may not point
|
||||||
to the start of the DLT, so we have to compute the absolute
|
to the start of the DLT, so we have to compute the absolute
|
||||||
address, then subtract out the value of __gp. */
|
address, then subtract out the value of __gp. */
|
||||||
value = (dyn_h->plt_offset
|
value = (hh->plt_offset
|
||||||
+ hppa_info->plt_sec->output_offset
|
+ hppa_info->plt_sec->output_offset
|
||||||
+ hppa_info->plt_sec->output_section->vma);
|
+ hppa_info->plt_sec->output_section->vma);
|
||||||
value -= _bfd_get_gp_value (output_bfd);
|
value -= _bfd_get_gp_value (output_bfd);
|
||||||
@ -1940,37 +1978,37 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
{
|
{
|
||||||
/* We may still need to create the FPTR itself if it was for
|
/* We may still need to create the FPTR itself if it was for
|
||||||
a local symbol. */
|
a local symbol. */
|
||||||
if (dyn_h->h == NULL)
|
if (hh == NULL)
|
||||||
{
|
{
|
||||||
/* The first two words of an .opd entry are zero. */
|
/* The first two words of an .opd entry are zero. */
|
||||||
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
|
memset (hppa_info->opd_sec->contents + hh->opd_offset, 0, 16);
|
||||||
|
|
||||||
/* The next word is the address of the function. */
|
/* The next word is the address of the function. */
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||||
(hppa_info->opd_sec->contents
|
(hppa_info->opd_sec->contents
|
||||||
+ dyn_h->opd_offset + 16));
|
+ hh->opd_offset + 16));
|
||||||
|
|
||||||
/* The last word is our local __gp value. */
|
/* The last word is our local __gp value. */
|
||||||
value = _bfd_get_gp_value
|
value = _bfd_get_gp_value
|
||||||
(hppa_info->opd_sec->output_section->owner);
|
(hppa_info->opd_sec->output_section->owner);
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||||
hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
|
hppa_info->opd_sec->contents + hh->opd_offset + 24);
|
||||||
|
|
||||||
/* The DLT value is the address of the .opd entry. */
|
/* The DLT value is the address of the .opd entry. */
|
||||||
value = (dyn_h->opd_offset
|
value = (hh->opd_offset
|
||||||
+ hppa_info->opd_sec->output_offset
|
+ hppa_info->opd_sec->output_offset
|
||||||
+ hppa_info->opd_sec->output_section->vma);
|
+ hppa_info->opd_sec->output_section->vma);
|
||||||
|
|
||||||
bfd_put_64 (hppa_info->dlt_sec->owner,
|
bfd_put_64 (hppa_info->dlt_sec->owner,
|
||||||
value,
|
value,
|
||||||
hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
|
hppa_info->dlt_sec->contents + hh->dlt_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want the value of the DLT offset for this symbol, not
|
/* We want the value of the DLT offset for this symbol, not
|
||||||
the symbol's actual address. Note that __gp may not point
|
the symbol's actual address. Note that __gp may not point
|
||||||
to the start of the DLT, so we have to compute the absolute
|
to the start of the DLT, so we have to compute the absolute
|
||||||
address, then subtract out the value of __gp. */
|
address, then subtract out the value of __gp. */
|
||||||
value = (dyn_h->dlt_offset
|
value = (hh->dlt_offset
|
||||||
+ hppa_info->dlt_sec->output_offset
|
+ hppa_info->dlt_sec->output_offset
|
||||||
+ hppa_info->dlt_sec->output_section->vma);
|
+ hppa_info->dlt_sec->output_section->vma);
|
||||||
value -= _bfd_get_gp_value (output_bfd);
|
value -= _bfd_get_gp_value (output_bfd);
|
||||||
@ -1983,37 +2021,37 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
{
|
{
|
||||||
/* We may still need to create the FPTR itself if it was for
|
/* We may still need to create the FPTR itself if it was for
|
||||||
a local symbol. */
|
a local symbol. */
|
||||||
if (dyn_h->h == NULL && r_type == R_PARISC_LTOFF_FPTR64)
|
if (eh == NULL && r_type == R_PARISC_LTOFF_FPTR64)
|
||||||
{
|
{
|
||||||
/* The first two words of an .opd entry are zero. */
|
/* The first two words of an .opd entry are zero. */
|
||||||
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
|
memset (hppa_info->opd_sec->contents + hh->opd_offset, 0, 16);
|
||||||
|
|
||||||
/* The next word is the address of the function. */
|
/* The next word is the address of the function. */
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||||
(hppa_info->opd_sec->contents
|
(hppa_info->opd_sec->contents
|
||||||
+ dyn_h->opd_offset + 16));
|
+ hh->opd_offset + 16));
|
||||||
|
|
||||||
/* The last word is our local __gp value. */
|
/* The last word is our local __gp value. */
|
||||||
value = _bfd_get_gp_value
|
value = _bfd_get_gp_value
|
||||||
(hppa_info->opd_sec->output_section->owner);
|
(hppa_info->opd_sec->output_section->owner);
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||||
hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
|
hppa_info->opd_sec->contents + hh->opd_offset + 24);
|
||||||
|
|
||||||
/* The DLT value is the address of the .opd entry. */
|
/* The DLT value is the address of the .opd entry. */
|
||||||
value = (dyn_h->opd_offset
|
value = (hh->opd_offset
|
||||||
+ hppa_info->opd_sec->output_offset
|
+ hppa_info->opd_sec->output_offset
|
||||||
+ hppa_info->opd_sec->output_section->vma);
|
+ hppa_info->opd_sec->output_section->vma);
|
||||||
|
|
||||||
bfd_put_64 (hppa_info->dlt_sec->owner,
|
bfd_put_64 (hppa_info->dlt_sec->owner,
|
||||||
value,
|
value,
|
||||||
hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
|
hppa_info->dlt_sec->contents + hh->dlt_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want the value of the DLT offset for this symbol, not
|
/* We want the value of the DLT offset for this symbol, not
|
||||||
the symbol's actual address. Note that __gp may not point
|
the symbol's actual address. Note that __gp may not point
|
||||||
to the start of the DLT, so we have to compute the absolute
|
to the start of the DLT, so we have to compute the absolute
|
||||||
address, then subtract out the value of __gp. */
|
address, then subtract out the value of __gp. */
|
||||||
value = (dyn_h->dlt_offset
|
value = (hh->dlt_offset
|
||||||
+ hppa_info->dlt_sec->output_offset
|
+ hppa_info->dlt_sec->output_offset
|
||||||
+ hppa_info->dlt_sec->output_section->vma);
|
+ hppa_info->dlt_sec->output_section->vma);
|
||||||
value -= _bfd_get_gp_value (output_bfd);
|
value -= _bfd_get_gp_value (output_bfd);
|
||||||
@ -2042,7 +2080,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
the symbol's actual address. Note that __gp may not point
|
the symbol's actual address. Note that __gp may not point
|
||||||
to the start of the DLT, so we have to compute the absolute
|
to the start of the DLT, so we have to compute the absolute
|
||||||
address, then subtract out the value of __gp. */
|
address, then subtract out the value of __gp. */
|
||||||
value = (dyn_h->dlt_offset
|
value = (hh->dlt_offset
|
||||||
+ hppa_info->dlt_sec->output_offset
|
+ hppa_info->dlt_sec->output_offset
|
||||||
+ hppa_info->dlt_sec->output_section->vma);
|
+ hppa_info->dlt_sec->output_section->vma);
|
||||||
value -= _bfd_get_gp_value (output_bfd);
|
value -= _bfd_get_gp_value (output_bfd);
|
||||||
@ -2056,7 +2094,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
library, then redirect the call to the local stub for this
|
library, then redirect the call to the local stub for this
|
||||||
function. */
|
function. */
|
||||||
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
||||||
value = (dyn_h->stub_offset + hppa_info->stub_sec->output_offset
|
value = (hh->stub_offset + hppa_info->stub_sec->output_offset
|
||||||
+ hppa_info->stub_sec->output_section->vma);
|
+ hppa_info->stub_sec->output_section->vma);
|
||||||
|
|
||||||
/* Turn VALUE into a proper PC relative address. */
|
/* Turn VALUE into a proper PC relative address. */
|
||||||
@ -2075,7 +2113,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
library, then redirect the call to the local stub for this
|
library, then redirect the call to the local stub for this
|
||||||
function. */
|
function. */
|
||||||
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
if (sym_sec == NULL || sym_sec->output_section == NULL)
|
||||||
value = (dyn_h->stub_offset + hppa_info->stub_sec->output_offset
|
value = (hh->stub_offset + hppa_info->stub_sec->output_offset
|
||||||
+ hppa_info->stub_sec->output_section->vma);
|
+ hppa_info->stub_sec->output_section->vma);
|
||||||
|
|
||||||
/* Turn VALUE into a proper PC relative address. */
|
/* Turn VALUE into a proper PC relative address. */
|
||||||
@ -2090,28 +2128,49 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
|
|
||||||
case R_PARISC_FPTR64:
|
case R_PARISC_FPTR64:
|
||||||
{
|
{
|
||||||
|
bfd_vma off;
|
||||||
|
|
||||||
/* We may still need to create the FPTR itself if it was for
|
/* We may still need to create the FPTR itself if it was for
|
||||||
a local symbol. */
|
a local symbol. */
|
||||||
if (dyn_h->h == NULL)
|
if (hh == NULL)
|
||||||
|
{
|
||||||
|
bfd_vma *local_opd_offsets;
|
||||||
|
|
||||||
|
if (local_offsets == NULL)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info;
|
||||||
|
off = local_opd_offsets[r_symndx];
|
||||||
|
|
||||||
|
/* The last bit records whether we've already initialised
|
||||||
|
this local .opd entry. */
|
||||||
|
if ((off & 1) != 0)
|
||||||
|
{
|
||||||
|
BFD_ASSERT (off != (bfd_vma) -1);
|
||||||
|
off &= ~1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* The first two words of an .opd entry are zero. */
|
/* The first two words of an .opd entry are zero. */
|
||||||
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
|
memset (hppa_info->opd_sec->contents + off, 0, 16);
|
||||||
|
|
||||||
/* The next word is the address of the function. */
|
/* The next word is the address of the function. */
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||||
(hppa_info->opd_sec->contents
|
(hppa_info->opd_sec->contents + off + 16));
|
||||||
+ dyn_h->opd_offset + 16));
|
|
||||||
|
|
||||||
/* The last word is our local __gp value. */
|
/* The last word is our local __gp value. */
|
||||||
value = _bfd_get_gp_value
|
value = _bfd_get_gp_value
|
||||||
(hppa_info->opd_sec->output_section->owner);
|
(hppa_info->opd_sec->output_section->owner);
|
||||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||||
hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
|
hppa_info->opd_sec->contents + off + 24);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
off = hh->opd_offset;
|
||||||
|
|
||||||
if (dyn_h->want_opd)
|
if (hh == NULL || hh->want_opd)
|
||||||
/* We want the value of the OPD offset for this symbol. */
|
/* We want the value of the OPD offset for this symbol. */
|
||||||
value = (dyn_h->opd_offset
|
value = (off
|
||||||
+ hppa_info->opd_sec->output_offset
|
+ hppa_info->opd_sec->output_offset
|
||||||
+ hppa_info->opd_sec->output_section->vma);
|
+ hppa_info->opd_sec->output_section->vma);
|
||||||
else
|
else
|
||||||
@ -2123,9 +2182,9 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case R_PARISC_SECREL32:
|
case R_PARISC_SECREL32:
|
||||||
bfd_put_32 (input_bfd,
|
if (sym_sec)
|
||||||
value + addend - sym_sec->output_section->vma,
|
value -= sym_sec->output_section->vma;
|
||||||
hit_data);
|
bfd_put_32 (input_bfd, value + addend, hit_data);
|
||||||
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
||||||
|
|
||||||
case R_PARISC_SEGREL32:
|
case R_PARISC_SEGREL32:
|
||||||
@ -2170,7 +2229,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
|||||||
/* Relocate an HPPA ELF section. */
|
/* Relocate an HPPA ELF section. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
elf_hppa_relocate_section (bfd *output_bfd,
|
elf64_hppa_relocate_section (bfd *output_bfd,
|
||||||
struct bfd_link_info *info,
|
struct bfd_link_info *info,
|
||||||
bfd *input_bfd,
|
bfd *input_bfd,
|
||||||
asection *input_section,
|
asection *input_section,
|
||||||
@ -2184,7 +2243,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
|||||||
Elf_Internal_Rela *relend;
|
Elf_Internal_Rela *relend;
|
||||||
struct elf64_hppa_link_hash_table *hppa_info;
|
struct elf64_hppa_link_hash_table *hppa_info;
|
||||||
|
|
||||||
hppa_info = elf64_hppa_hash_table (info);
|
hppa_info = hppa_link_hash_table (info);
|
||||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||||
|
|
||||||
rel = relocs;
|
rel = relocs;
|
||||||
@ -2194,15 +2253,12 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
|||||||
int r_type;
|
int r_type;
|
||||||
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
|
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
|
||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *eh;
|
||||||
Elf_Internal_Sym *sym;
|
Elf_Internal_Sym *sym;
|
||||||
asection *sym_sec;
|
asection *sym_sec;
|
||||||
bfd_vma relocation;
|
bfd_vma relocation;
|
||||||
bfd_reloc_status_type r;
|
bfd_reloc_status_type r;
|
||||||
const char *dyn_name;
|
bfd_boolean warned_undef;
|
||||||
char *dynh_buf = NULL;
|
|
||||||
size_t dynh_buflen = 0;
|
|
||||||
struct elf64_hppa_dyn_hash_entry *dyn_h = NULL;
|
|
||||||
|
|
||||||
r_type = ELF_R_TYPE (rel->r_info);
|
r_type = ELF_R_TYPE (rel->r_info);
|
||||||
if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
|
if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
|
||||||
@ -2210,112 +2266,96 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
|||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (r_type == (unsigned int) R_PARISC_GNU_VTENTRY
|
||||||
|
|| r_type == (unsigned int) R_PARISC_GNU_VTINHERIT)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* This is a final link. */
|
/* This is a final link. */
|
||||||
r_symndx = ELF_R_SYM (rel->r_info);
|
r_symndx = ELF_R_SYM (rel->r_info);
|
||||||
h = NULL;
|
eh = NULL;
|
||||||
sym = NULL;
|
sym = NULL;
|
||||||
sym_sec = NULL;
|
sym_sec = NULL;
|
||||||
|
warned_undef = FALSE;
|
||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
{
|
{
|
||||||
/* This is a local symbol. */
|
/* This is a local symbol, hh defaults to NULL. */
|
||||||
sym = local_syms + r_symndx;
|
sym = local_syms + r_symndx;
|
||||||
sym_sec = local_sections[r_symndx];
|
sym_sec = local_sections[r_symndx];
|
||||||
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sym_sec, rel);
|
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sym_sec, rel);
|
||||||
|
|
||||||
/* If this symbol has an entry in the PA64 dynamic hash
|
|
||||||
table, then get it. */
|
|
||||||
dyn_name = get_dyn_name (input_bfd, h, rel,
|
|
||||||
&dynh_buf, &dynh_buflen);
|
|
||||||
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
|
|
||||||
dyn_name, FALSE, FALSE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This is not a local symbol. */
|
/* This is not a local symbol. */
|
||||||
long indx;
|
bfd_boolean unresolved_reloc;
|
||||||
|
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
|
|
||||||
|
/* It seems this can happen with erroneous or unsupported
|
||||||
|
input (mixing a.out and elf in an archive, for example.) */
|
||||||
|
if (sym_hashes == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
eh = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
|
|
||||||
|
while (eh->root.type == bfd_link_hash_indirect
|
||||||
|
|| eh->root.type == bfd_link_hash_warning)
|
||||||
|
eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
|
||||||
|
|
||||||
|
warned_undef = FALSE;
|
||||||
|
unresolved_reloc = FALSE;
|
||||||
relocation = 0;
|
relocation = 0;
|
||||||
indx = r_symndx - symtab_hdr->sh_info;
|
if (eh->root.type == bfd_link_hash_defined
|
||||||
h = elf_sym_hashes (input_bfd)[indx];
|
|| eh->root.type == bfd_link_hash_defweak)
|
||||||
while (h->root.type == bfd_link_hash_indirect
|
|
||||||
|| h->root.type == bfd_link_hash_warning)
|
|
||||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
||||||
if (h->root.type == bfd_link_hash_defined
|
|
||||||
|| h->root.type == bfd_link_hash_defweak)
|
|
||||||
{
|
{
|
||||||
sym_sec = h->root.u.def.section;
|
sym_sec = eh->root.u.def.section;
|
||||||
|
if (sym_sec == NULL
|
||||||
/* If this symbol has an entry in the PA64 dynamic hash
|
|| sym_sec->output_section == NULL)
|
||||||
table, then get it. */
|
/* Set a flag that will be cleared later if we find a
|
||||||
dyn_name = get_dyn_name (input_bfd, h, rel,
|
relocation value for this symbol. output_section
|
||||||
&dynh_buf, &dynh_buflen);
|
is typically NULL for symbols satisfied by a shared
|
||||||
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
|
library. */
|
||||||
dyn_name, FALSE, FALSE);
|
unresolved_reloc = TRUE;
|
||||||
|
else
|
||||||
/* If we have a relocation against a symbol defined in a
|
relocation = (eh->root.u.def.value
|
||||||
shared library and we have not created an entry in the
|
+ sym_sec->output_section->vma
|
||||||
PA64 dynamic symbol hash table for it, then we lose. */
|
+ sym_sec->output_offset);
|
||||||
if (!info->relocatable
|
|
||||||
&& sym_sec->output_section == NULL && dyn_h == NULL)
|
|
||||||
{
|
|
||||||
(*_bfd_error_handler)
|
|
||||||
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
|
|
||||||
input_bfd,
|
|
||||||
input_section,
|
|
||||||
(long) rel->r_offset,
|
|
||||||
howto->name,
|
|
||||||
h->root.root.string);
|
|
||||||
}
|
|
||||||
else if (sym_sec->output_section)
|
|
||||||
relocation = (h->root.u.def.value
|
|
||||||
+ sym_sec->output_offset
|
|
||||||
+ sym_sec->output_section->vma);
|
|
||||||
}
|
}
|
||||||
|
else if (eh->root.type == bfd_link_hash_undefweak)
|
||||||
|
;
|
||||||
else if (info->unresolved_syms_in_objects == RM_IGNORE
|
else if (info->unresolved_syms_in_objects == RM_IGNORE
|
||||||
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
|
&& ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT)
|
||||||
{
|
;
|
||||||
/* If this symbol has an entry in the PA64 dynamic hash
|
else if (!info->relocatable
|
||||||
table, then get it. */
|
&& elf_hppa_is_dynamic_loader_symbol (eh->root.root.string))
|
||||||
dyn_name = get_dyn_name (input_bfd, h, rel,
|
continue;
|
||||||
&dynh_buf, &dynh_buflen);
|
|
||||||
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
|
|
||||||
dyn_name, FALSE, FALSE);
|
|
||||||
|
|
||||||
if (!info->relocatable && dyn_h == NULL)
|
|
||||||
{
|
|
||||||
(*_bfd_error_handler)
|
|
||||||
(_("%B(%A): warning: unresolvable relocation against symbol `%s'"),
|
|
||||||
input_bfd, input_section, h->root.root.string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (h->root.type == bfd_link_hash_undefweak)
|
|
||||||
{
|
|
||||||
dyn_name = get_dyn_name (input_bfd, h, rel,
|
|
||||||
&dynh_buf, &dynh_buflen);
|
|
||||||
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
|
|
||||||
dyn_name, FALSE, FALSE);
|
|
||||||
|
|
||||||
if (!info->relocatable && dyn_h == NULL)
|
|
||||||
{
|
|
||||||
(*_bfd_error_handler)
|
|
||||||
(_("%B(%A): warning: unresolvable relocation against symbol `%s'"),
|
|
||||||
input_bfd, input_section, h->root.root.string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!info->relocatable)
|
else if (!info->relocatable)
|
||||||
{
|
{
|
||||||
/* Ignore dynamic loader defined symbols. */
|
bfd_boolean err;
|
||||||
if (!elf_hppa_is_dynamic_loader_symbol (h->root.root.string))
|
err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|
||||||
{
|
|| ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT);
|
||||||
if (!((*info->callbacks->undefined_symbol)
|
if (!info->callbacks->undefined_symbol (info,
|
||||||
(info, h->root.root.string, input_bfd,
|
eh->root.root.string,
|
||||||
input_section, rel->r_offset,
|
input_bfd,
|
||||||
(info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|
input_section,
|
||||||
|| ELF_ST_VISIBILITY (h->other)))))
|
rel->r_offset, err))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
warned_undef = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info->relocatable
|
||||||
|
&& relocation == 0
|
||||||
|
&& eh->root.type != bfd_link_hash_defined
|
||||||
|
&& eh->root.type != bfd_link_hash_defweak
|
||||||
|
&& eh->root.type != bfd_link_hash_undefweak)
|
||||||
|
{
|
||||||
|
if (info->unresolved_syms_in_objects == RM_IGNORE
|
||||||
|
&& ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT
|
||||||
|
&& eh->type == STT_PARISC_MILLI)
|
||||||
|
{
|
||||||
|
if (! info->callbacks->undefined_symbol
|
||||||
|
(info, eh_name (eh), input_bfd,
|
||||||
|
input_section, rel->r_offset, FALSE))
|
||||||
|
return FALSE;
|
||||||
|
warned_undef = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2337,7 +2377,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
|||||||
r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
|
r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
|
||||||
input_section, contents,
|
input_section, contents,
|
||||||
relocation, info, sym_sec,
|
relocation, info, sym_sec,
|
||||||
h, dyn_h);
|
eh);
|
||||||
|
|
||||||
if (r != bfd_reloc_ok)
|
if (r != bfd_reloc_ok)
|
||||||
{
|
{
|
||||||
@ -2349,7 +2389,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
const char *sym_name;
|
const char *sym_name;
|
||||||
|
|
||||||
if (h != NULL)
|
if (eh != NULL)
|
||||||
sym_name = NULL;
|
sym_name = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2363,7 +2403,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!((*info->callbacks->reloc_overflow)
|
if (!((*info->callbacks->reloc_overflow)
|
||||||
(info, (h ? &h->root : NULL), sym_name,
|
(info, (eh ? &eh->root : NULL), sym_name,
|
||||||
howto->name, (bfd_vma) 0, input_bfd,
|
howto->name, (bfd_vma) 0, input_bfd,
|
||||||
input_section, rel->r_offset)))
|
input_section, rel->r_offset)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
969
bfd/elf64-hppa.c
969
bfd/elf64-hppa.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user