* 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:
Dave Anglin 2009-03-01 02:10:49 +00:00
parent a8a886ba79
commit a03bd320bd
3 changed files with 780 additions and 634 deletions

View File

@ -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.

View File

@ -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;

File diff suppressed because it is too large Load Diff