mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-29 04:53:56 +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:
parent
a8a886ba79
commit
a03bd320bd
@ -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>
|
||||
|
||||
* elf32-arm.c (stub_reloc_type): Removed.
|
||||
|
356
bfd/elf-hppa.h
356
bfd/elf-hppa.h
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -1606,18 +1606,23 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
||||
bfd_vma value,
|
||||
struct bfd_link_info *info,
|
||||
asection *sym_sec,
|
||||
struct elf_link_hash_entry *h,
|
||||
struct elf64_hppa_dyn_hash_entry *dyn_h)
|
||||
struct elf_link_hash_entry *eh)
|
||||
{
|
||||
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;
|
||||
bfd_vma max_branch_offset = 0;
|
||||
bfd_vma offset = rel->r_offset;
|
||||
bfd_signed_vma addend = rel->r_addend;
|
||||
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;
|
||||
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);
|
||||
|
||||
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
|
||||
function. */
|
||||
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);
|
||||
|
||||
/* 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
|
||||
function. */
|
||||
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);
|
||||
|
||||
/* Turn VALUE into a proper PC relative address. */
|
||||
@ -1702,7 +1707,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
||||
input_bfd,
|
||||
input_section,
|
||||
offset,
|
||||
h->root.root.string);
|
||||
eh->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return bfd_reloc_notsupported;
|
||||
}
|
||||
@ -1746,6 +1751,8 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
||||
case R_PARISC_LTOFF16WF:
|
||||
case R_PARISC_LTOFF16DF:
|
||||
{
|
||||
bfd_vma off;
|
||||
|
||||
/* 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
|
||||
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
|
||||
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. */
|
||||
if (r_type == R_PARISC_LTOFF_FPTR14R
|
||||
|| 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_FPTR16DF)
|
||||
{
|
||||
/* The first two words of an .opd entry are zero. */
|
||||
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset,
|
||||
0, 16);
|
||||
local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info;
|
||||
off = local_opd_offsets[r_symndx];
|
||||
|
||||
/* The next word is the address of the function. */
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||
(hppa_info->opd_sec->contents
|
||||
+ dyn_h->opd_offset + 16));
|
||||
/* 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 last word is our local __gp value. */
|
||||
value = _bfd_get_gp_value
|
||||
(hppa_info->opd_sec->output_section->owner);
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||
(hppa_info->opd_sec->contents
|
||||
+ dyn_h->opd_offset + 24));
|
||||
/* The first two words of an .opd entry are zero. */
|
||||
memset (hppa_info->opd_sec->contents + off, 0, 16);
|
||||
|
||||
/* The next word is the address of the function. */
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||
(hppa_info->opd_sec->contents + off + 16));
|
||||
|
||||
/* The last word is our local __gp value. */
|
||||
value = _bfd_get_gp_value
|
||||
(hppa_info->opd_sec->output_section->owner);
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||
(hppa_info->opd_sec->contents + off + 24));
|
||||
}
|
||||
|
||||
/* 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_section->vma);
|
||||
addend = 0;
|
||||
}
|
||||
|
||||
bfd_put_64 (hppa_info->dlt_sec->owner,
|
||||
value + addend,
|
||||
hppa_info->dlt_sec->contents + dyn_h->dlt_offset);
|
||||
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,
|
||||
value + addend,
|
||||
hppa_info->dlt_sec->contents + off);
|
||||
}
|
||||
}
|
||||
else
|
||||
off = hh->dlt_offset;
|
||||
|
||||
/* We want the value of the DLT offset for this symbol, not
|
||||
the symbol's actual address. Note that __gp may not point
|
||||
to the start of the DLT, so we have to compute the absolute
|
||||
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_section->vma);
|
||||
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
|
||||
to the start of the DLT, so we have to compute the absolute
|
||||
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_section->vma);
|
||||
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
|
||||
a local symbol. */
|
||||
if (dyn_h->h == NULL)
|
||||
if (hh == NULL)
|
||||
{
|
||||
/* 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. */
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||
(hppa_info->opd_sec->contents
|
||||
+ dyn_h->opd_offset + 16));
|
||||
+ hh->opd_offset + 16));
|
||||
|
||||
/* The last word is our local __gp value. */
|
||||
value = _bfd_get_gp_value
|
||||
(hppa_info->opd_sec->output_section->owner);
|
||||
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. */
|
||||
value = (dyn_h->opd_offset
|
||||
value = (hh->opd_offset
|
||||
+ hppa_info->opd_sec->output_offset
|
||||
+ hppa_info->opd_sec->output_section->vma);
|
||||
|
||||
bfd_put_64 (hppa_info->dlt_sec->owner,
|
||||
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
|
||||
the symbol's actual address. Note that __gp may not point
|
||||
to the start of the DLT, so we have to compute the absolute
|
||||
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_section->vma);
|
||||
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
|
||||
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. */
|
||||
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. */
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||
(hppa_info->opd_sec->contents
|
||||
+ dyn_h->opd_offset + 16));
|
||||
+ hh->opd_offset + 16));
|
||||
|
||||
/* The last word is our local __gp value. */
|
||||
value = _bfd_get_gp_value
|
||||
(hppa_info->opd_sec->output_section->owner);
|
||||
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. */
|
||||
value = (dyn_h->opd_offset
|
||||
value = (hh->opd_offset
|
||||
+ hppa_info->opd_sec->output_offset
|
||||
+ hppa_info->opd_sec->output_section->vma);
|
||||
|
||||
bfd_put_64 (hppa_info->dlt_sec->owner,
|
||||
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
|
||||
the symbol's actual address. Note that __gp may not point
|
||||
to the start of the DLT, so we have to compute the absolute
|
||||
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_section->vma);
|
||||
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
|
||||
to the start of the DLT, so we have to compute the absolute
|
||||
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_section->vma);
|
||||
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
|
||||
function. */
|
||||
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);
|
||||
|
||||
/* 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
|
||||
function. */
|
||||
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);
|
||||
|
||||
/* 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:
|
||||
{
|
||||
bfd_vma off;
|
||||
|
||||
/* We may still need to create the FPTR itself if it was for
|
||||
a local symbol. */
|
||||
if (dyn_h->h == NULL)
|
||||
if (hh == NULL)
|
||||
{
|
||||
/* The first two words of an .opd entry are zero. */
|
||||
memset (hppa_info->opd_sec->contents + dyn_h->opd_offset, 0, 16);
|
||||
bfd_vma *local_opd_offsets;
|
||||
|
||||
/* The next word is the address of the function. */
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||
(hppa_info->opd_sec->contents
|
||||
+ dyn_h->opd_offset + 16));
|
||||
if (local_offsets == NULL)
|
||||
abort ();
|
||||
|
||||
/* The last word is our local __gp value. */
|
||||
value = _bfd_get_gp_value
|
||||
(hppa_info->opd_sec->output_section->owner);
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||
hppa_info->opd_sec->contents + dyn_h->opd_offset + 24);
|
||||
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. */
|
||||
memset (hppa_info->opd_sec->contents + off, 0, 16);
|
||||
|
||||
/* The next word is the address of the function. */
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value + addend,
|
||||
(hppa_info->opd_sec->contents + off + 16));
|
||||
|
||||
/* The last word is our local __gp value. */
|
||||
value = _bfd_get_gp_value
|
||||
(hppa_info->opd_sec->output_section->owner);
|
||||
bfd_put_64 (hppa_info->opd_sec->owner, value,
|
||||
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. */
|
||||
value = (dyn_h->opd_offset
|
||||
value = (off
|
||||
+ hppa_info->opd_sec->output_offset
|
||||
+ hppa_info->opd_sec->output_section->vma);
|
||||
else
|
||||
@ -2123,9 +2182,9 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
||||
}
|
||||
|
||||
case R_PARISC_SECREL32:
|
||||
bfd_put_32 (input_bfd,
|
||||
value + addend - sym_sec->output_section->vma,
|
||||
hit_data);
|
||||
if (sym_sec)
|
||||
value -= sym_sec->output_section->vma;
|
||||
bfd_put_32 (input_bfd, value + addend, hit_data);
|
||||
return bfd_reloc_ok;
|
||||
|
||||
case R_PARISC_SEGREL32:
|
||||
@ -2170,7 +2229,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
|
||||
/* Relocate an HPPA ELF section. */
|
||||
|
||||
static bfd_boolean
|
||||
elf_hppa_relocate_section (bfd *output_bfd,
|
||||
elf64_hppa_relocate_section (bfd *output_bfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd *input_bfd,
|
||||
asection *input_section,
|
||||
@ -2184,7 +2243,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
||||
Elf_Internal_Rela *relend;
|
||||
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;
|
||||
|
||||
rel = relocs;
|
||||
@ -2194,15 +2253,12 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
||||
int r_type;
|
||||
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
struct elf_link_hash_entry *eh;
|
||||
Elf_Internal_Sym *sym;
|
||||
asection *sym_sec;
|
||||
bfd_vma relocation;
|
||||
bfd_reloc_status_type r;
|
||||
const char *dyn_name;
|
||||
char *dynh_buf = NULL;
|
||||
size_t dynh_buflen = 0;
|
||||
struct elf64_hppa_dyn_hash_entry *dyn_h = NULL;
|
||||
bfd_boolean warned_undef;
|
||||
|
||||
r_type = ELF_R_TYPE (rel->r_info);
|
||||
if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
|
||||
@ -2210,114 +2266,98 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
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. */
|
||||
r_symndx = ELF_R_SYM (rel->r_info);
|
||||
h = NULL;
|
||||
eh = NULL;
|
||||
sym = NULL;
|
||||
sym_sec = NULL;
|
||||
warned_undef = FALSE;
|
||||
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_sec = local_sections[r_symndx];
|
||||
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
|
||||
{
|
||||
/* 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;
|
||||
indx = r_symndx - symtab_hdr->sh_info;
|
||||
h = elf_sym_hashes (input_bfd)[indx];
|
||||
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)
|
||||
if (eh->root.type == bfd_link_hash_defined
|
||||
|| eh->root.type == bfd_link_hash_defweak)
|
||||
{
|
||||
sym_sec = h->root.u.def.section;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* If we have a relocation against a symbol defined in a
|
||||
shared library and we have not created an entry in the
|
||||
PA64 dynamic symbol hash table for it, then we lose. */
|
||||
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);
|
||||
sym_sec = eh->root.u.def.section;
|
||||
if (sym_sec == NULL
|
||||
|| sym_sec->output_section == NULL)
|
||||
/* Set a flag that will be cleared later if we find a
|
||||
relocation value for this symbol. output_section
|
||||
is typically NULL for symbols satisfied by a shared
|
||||
library. */
|
||||
unresolved_reloc = TRUE;
|
||||
else
|
||||
relocation = (eh->root.u.def.value
|
||||
+ sym_sec->output_section->vma
|
||||
+ sym_sec->output_offset);
|
||||
}
|
||||
else if (eh->root.type == bfd_link_hash_undefweak)
|
||||
;
|
||||
else if (info->unresolved_syms_in_objects == RM_IGNORE
|
||||
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
&& ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT)
|
||||
;
|
||||
else if (!info->relocatable
|
||||
&& elf_hppa_is_dynamic_loader_symbol (eh->root.root.string))
|
||||
continue;
|
||||
else if (!info->relocatable)
|
||||
{
|
||||
/* Ignore dynamic loader defined symbols. */
|
||||
if (!elf_hppa_is_dynamic_loader_symbol (h->root.root.string))
|
||||
{
|
||||
if (!((*info->callbacks->undefined_symbol)
|
||||
(info, h->root.root.string, input_bfd,
|
||||
input_section, rel->r_offset,
|
||||
(info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|
||||
|| ELF_ST_VISIBILITY (h->other)))))
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
bfd_boolean err;
|
||||
err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|
||||
|| ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT);
|
||||
if (!info->callbacks->undefined_symbol (info,
|
||||
eh->root.root.string,
|
||||
input_bfd,
|
||||
input_section,
|
||||
rel->r_offset, err))
|
||||
return FALSE;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sym_sec != NULL && elf_discarded_section (sym_sec))
|
||||
@ -2337,7 +2377,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
||||
r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
|
||||
input_section, contents,
|
||||
relocation, info, sym_sec,
|
||||
h, dyn_h);
|
||||
eh);
|
||||
|
||||
if (r != bfd_reloc_ok)
|
||||
{
|
||||
@ -2349,7 +2389,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
||||
{
|
||||
const char *sym_name;
|
||||
|
||||
if (h != NULL)
|
||||
if (eh != NULL)
|
||||
sym_name = NULL;
|
||||
else
|
||||
{
|
||||
@ -2363,7 +2403,7 @@ elf_hppa_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
|
||||
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,
|
||||
input_section, rel->r_offset)))
|
||||
return FALSE;
|
||||
|
1017
bfd/elf64-hppa.c
1017
bfd/elf64-hppa.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user