* elf32-hppa.c (struct elf32_hppa_link_hash_entry,

hppa_link_hash_newfunc, hppa_build_one_stub,
	elf32_hppa_adjust_dynamic_symbol, mark_PIC_calls, allocate_plt_static,
	allocate_dynrelocs, elf32_hppa_size_dynamic_sections,
	elf32_hppa_finish_dynamic_symbol): Remove pic_call field and all code
	for generating import stubs for calls to statically linked PIC
	functions.
	(hppa_type_of_stub): Don't generate an import stub for calls to
	statically linked pic functions.  Generate import stubs for calls
	in a shared object, to functions not in a regular file, and to
	defined weak functions.  Add new argument INFO.
	(hppa_build_one_stub): Don't undef ADDIL_DP.
	(elf32_hppa_check_relocs): Don't set SEC_HAS_GOT_REF flag.
	(elf32_hppa_size_stubs): Pass info to hppa_type_of_stub.
	(final_link_relocate): Change all DLTIND relocs to DPREL relocs in a
	non-shared link.  Convert instructions that use the the linkage table
	pointer, or a facsimile thereof, to use the global data pointer when
	the reloc has been changed.
This commit is contained in:
Dave Anglin 2003-09-10 18:46:08 +00:00
parent dcc6aaff9c
commit a252afa4cd
2 changed files with 112 additions and 144 deletions

View File

@ -1,3 +1,25 @@
2003-09-10 John David Anglin <dave.anglin@nrc-cnrc.nrc.ca>
Randolph Chung <randolph@tausq.org>
* elf32-hppa.c (struct elf32_hppa_link_hash_entry,
hppa_link_hash_newfunc, hppa_build_one_stub,
elf32_hppa_adjust_dynamic_symbol, mark_PIC_calls, allocate_plt_static,
allocate_dynrelocs, elf32_hppa_size_dynamic_sections,
elf32_hppa_finish_dynamic_symbol): Remove pic_call field and all code
for generating import stubs for calls to statically linked PIC
functions.
(hppa_type_of_stub): Don't generate an import stub for calls to
statically linked pic functions. Generate import stubs for calls
in a shared object, to functions not in a regular file, and to
defined weak functions. Add new argument INFO.
(hppa_build_one_stub): Don't undef ADDIL_DP.
(elf32_hppa_check_relocs): Don't set SEC_HAS_GOT_REF flag.
(elf32_hppa_size_stubs): Pass info to hppa_type_of_stub.
(final_link_relocate): Change all DLTIND relocs to DPREL relocs in a
non-shared link. Convert instructions that use the the linkage table
pointer, or a facsimile thereof, to use the global data pointer when
the reloc has been changed.
2003-09-08 Joel Brobecker <brobecker@gnat.com>
* archures.c: Add new machine names for hppa.

View File

@ -203,10 +203,6 @@ struct elf32_hppa_link_hash_entry {
#endif
} *dyn_relocs;
/* Set if the only reason we need a .plt entry is for a non-PIC to
PIC function call. */
unsigned int pic_call:1;
/* Set if this symbol is used by a plabel reloc. */
unsigned int plabel:1;
};
@ -345,7 +341,6 @@ hppa_link_hash_newfunc (struct bfd_hash_entry *entry,
eh = (struct elf32_hppa_link_hash_entry *) entry;
eh->stub_cache = NULL;
eh->dyn_relocs = NULL;
eh->pic_call = 0;
eh->plabel = 0;
}
@ -556,7 +551,8 @@ static enum elf32_hppa_stub_type
hppa_type_of_stub (asection *input_sec,
const Elf_Internal_Rela *rel,
struct elf32_hppa_link_hash_entry *hash,
bfd_vma destination)
bfd_vma destination,
struct bfd_link_info *info)
{
bfd_vma location;
bfd_vma branch_offset;
@ -565,8 +561,11 @@ hppa_type_of_stub (asection *input_sec,
if (hash != NULL
&& hash->elf.plt.offset != (bfd_vma) -1
&& (hash->elf.dynindx != -1 || hash->pic_call)
&& !hash->plabel)
&& hash->elf.dynindx != -1
&& !hash->plabel
&& (info->shared
|| !(hash->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
|| hash->elf.root.type == bfd_link_hash_defweak))
{
/* We need an import stub. Decide between hppa_stub_import
and hppa_stub_import_shared later. */
@ -769,39 +768,6 @@ hppa_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
size = 16;
}
if (!info->shared
&& stub_entry->h != NULL
&& stub_entry->h->pic_call)
{
/* Build the .plt entry needed to call a PIC function from
statically linked code. We don't need any relocs. */
bfd *dynobj;
struct elf32_hppa_link_hash_entry *eh;
bfd_vma value;
dynobj = htab->elf.dynobj;
eh = (struct elf32_hppa_link_hash_entry *) stub_entry->h;
if (eh->elf.root.type != bfd_link_hash_defined
&& eh->elf.root.type != bfd_link_hash_defweak)
abort ();
value = (eh->elf.root.u.def.value
+ eh->elf.root.u.def.section->output_offset
+ eh->elf.root.u.def.section->output_section->vma);
/* Fill in the entry in the procedure linkage table.
The format of a plt entry is
<funcaddr>
<__gp>. */
bfd_put_32 (htab->splt->owner, value,
htab->splt->contents + off);
value = elf_gp (htab->splt->output_section->owner);
bfd_put_32 (htab->splt->owner, value,
htab->splt->contents + off + 4);
}
break;
case hppa_stub_export:
@ -863,7 +829,6 @@ hppa_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
#undef BL_R1
#undef ADDIL_R1
#undef DEPI_R1
#undef ADDIL_DP
#undef LDW_R1_R21
#undef LDW_R1_DLT
#undef LDW_R1_R19
@ -1100,9 +1065,6 @@ elf32_hppa_check_relocs (bfd *abfd,
case R_PARISC_DLTIND21L:
/* This symbol requires a global offset table entry. */
need_entry = NEED_GOT;
/* Mark this section as containing PIC code. */
sec->flags |= SEC_HAS_GOT_REF;
break;
case R_PARISC_PLABEL14R: /* "Official" procedure labels. */
@ -1685,18 +1647,8 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
used by a plabel relocation. Either this object is the
application or we are doing a shared symbolic link. */
/* As a special sop to the hppa ABI, we keep a .plt entry
for functions in sections containing PIC code. */
if (!info->shared
&& h->plt.refcount > 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
&& (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0)
((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
else
{
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
return TRUE;
@ -1796,34 +1748,8 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
return TRUE;
}
/* Called via elf_link_hash_traverse to create .plt entries for an
application that uses statically linked PIC functions. Similar to
the first part of elf32_hppa_adjust_dynamic_symbol. */
static bfd_boolean
mark_PIC_calls (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (! (h->plt.refcount > 0
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0))
{
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
return TRUE;
}
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
return TRUE;
}
/* Allocate space in the .plt for entries that won't have relocations.
ie. pic_call and plabel entries. */
ie. plabel entries. */
static bfd_boolean
allocate_plt_static (struct elf_link_hash_entry *h, void *inf)
@ -1840,16 +1766,7 @@ allocate_plt_static (struct elf_link_hash_entry *h, void *inf)
info = inf;
htab = hppa_link_hash_table (info);
if (((struct elf32_hppa_link_hash_entry *) h)->pic_call)
{
/* Make an entry in the .plt section for non-pic code that is
calling pic code. */
((struct elf32_hppa_link_hash_entry *) h)->plabel = 0;
s = htab->splt;
h->plt.offset = s->_raw_size;
s->_raw_size += PLT_ENTRY_SIZE;
}
else if (htab->elf.dynamic_sections_created
if (htab->elf.dynamic_sections_created
&& h->plt.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
@ -1916,7 +1833,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
htab = hppa_link_hash_table (info);
if (htab->elf.dynamic_sections_created
&& h->plt.offset != (bfd_vma) -1
&& !((struct elf32_hppa_link_hash_entry *) h)->pic_call
&& !((struct elf32_hppa_link_hash_entry *) h)->plabel)
{
/* Make an entry in the .plt section. */
@ -2114,14 +2030,6 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
clobber_millicode_symbols,
info);
}
else
{
/* Run through the function symbols, looking for any that are
PIC, and mark them as needing .plt entries so that %r19 will
be set up. */
if (! info->shared)
elf_link_hash_traverse (&htab->elf, mark_PIC_calls, info);
}
/* Set up .got and .plt offsets for local syms, and space for local
dynamic relocs. */
@ -2871,7 +2779,7 @@ elf32_hppa_size_stubs
/* Determine what (if any) linker stub is needed. */
stub_type = hppa_type_of_stub (section, irela, hash,
destination);
destination, info);
if (stub_type == hppa_stub_none)
continue;
@ -3126,10 +3034,12 @@ final_link_relocate (asection *input_section,
bfd_vma value,
struct elf32_hppa_link_hash_table *htab,
asection *sym_sec,
struct elf32_hppa_link_hash_entry *h)
struct elf32_hppa_link_hash_entry *h,
struct bfd_link_info *info)
{
int insn;
unsigned int r_type = ELF32_R_TYPE (rel->r_info);
unsigned int orig_r_type = r_type;
reloc_howto_type *howto = elf_hppa_howto_table + r_type;
int r_format = howto->bitsize;
enum hppa_reloc_field_selector_type_alt r_field;
@ -3152,6 +3062,26 @@ final_link_relocate (asection *input_section,
input_section->output_offset +
input_section->output_section->vma);
/* If we are not building a shared library, convert DLTIND relocs to
DPREL relocs. */
if (!info->shared)
{
switch (r_type)
{
case R_PARISC_DLTIND21L:
r_type = R_PARISC_DPREL21L;
break;
case R_PARISC_DLTIND14R:
r_type = R_PARISC_DPREL14R;
break;
case R_PARISC_DLTIND14F:
r_type = R_PARISC_DPREL14F;
break;
}
}
switch (r_type)
{
case R_PARISC_PCREL12F:
@ -3163,8 +3093,11 @@ final_link_relocate (asection *input_section,
|| sym_sec->output_section == NULL
|| (h != NULL
&& h->elf.plt.offset != (bfd_vma) -1
&& (h->elf.dynindx != -1 || h->pic_call)
&& !h->plabel))
&& h->elf.dynindx != -1
&& !h->plabel
&& (info->shared
|| !(h->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
|| h->elf.root.type == bfd_link_hash_defweak)))
{
stub_entry = hppa_get_stub_entry (input_section, sym_sec,
h, rel, htab);
@ -3204,6 +3137,38 @@ final_link_relocate (asection *input_section,
case R_PARISC_DPREL21L:
case R_PARISC_DPREL14R:
case R_PARISC_DPREL14F:
/* Convert instructions that use the linkage table pointer (r19) to
instructions that use the global data pointer (dp). This is the
most efficient way of using PIC code in an incomplete executable,
but the user must follow the standard runtime conventions for
accessing data for this to work. */
if (orig_r_type == R_PARISC_DLTIND21L)
{
/* Convert addil instructions if the original reloc was a
DLTIND21L. GCC sometimes uses a register other than r19 for
the operation, so we must convert any addil instruction
that uses this relocation. */
if ((insn & 0xfc000000) == ((int) OP_ADDIL << 26))
insn = ADDIL_DP;
else
/* We must have a ldil instruction. It's too hard to find
and convert the associated add instruction, so issue an
error. */
(*_bfd_error_handler)
(_("%s(%s+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"),
bfd_archive_filename (input_bfd),
input_section->name,
(long) rel->r_offset,
howto->name,
insn);
}
else if (orig_r_type == R_PARISC_DLTIND14F)
{
/* This must be a format 1 load/store. Change the base
register to dp. */
insn = (insn & 0xfc1ffff) | (27 << 21);
}
/* For all the DP relative relocations, we need to examine the symbol's
section. If it has no section or if it's a code section, then
"data pointer relative" makes no sense. In that case we don't
@ -3806,7 +3771,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
}
r = final_link_relocate (input_section, contents, rel, relocation,
htab, sym_sec, h);
htab, sym_sec, h, info);
if (r == bfd_reloc_ok)
continue;
@ -3863,6 +3828,8 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
Elf_Internal_Sym *sym)
{
struct elf32_hppa_link_hash_table *htab;
Elf_Internal_Rela rel;
bfd_byte *loc;
htab = hppa_link_hash_table (info);
@ -3890,43 +3857,27 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_section->vma);
}
if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
/* Create a dynamic IPLT relocation for this entry. */
rel.r_offset = (h->plt.offset
+ htab->splt->output_offset
+ htab->splt->output_section->vma);
if (h->dynindx != -1)
{
Elf_Internal_Rela rel;
bfd_byte *loc;
/* Create a dynamic IPLT relocation for this entry. */
rel.r_offset = (h->plt.offset
+ htab->splt->output_offset
+ htab->splt->output_section->vma);
if (h->dynindx != -1)
{
rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_IPLT);
rel.r_addend = 0;
}
else
{
/* This symbol has been marked to become local, and is
used by a plabel so must be kept in the .plt. */
rel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
rel.r_addend = value;
}
loc = htab->srelplt->contents;
loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (htab->splt->output_section->owner,
&rel, loc);
rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_IPLT);
rel.r_addend = 0;
}
else
{
bfd_put_32 (htab->splt->owner,
value,
htab->splt->contents + h->plt.offset);
bfd_put_32 (htab->splt->owner,
elf_gp (htab->splt->output_section->owner),
htab->splt->contents + h->plt.offset + 4);
/* This symbol has been marked to become local, and is
used by a plabel so must be kept in the .plt. */
rel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
rel.r_addend = value;
}
loc = htab->srelplt->contents;
loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, &rel, loc);
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
/* Mark the symbol as undefined, rather than as defined in
@ -3937,9 +3888,6 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
if (h->got.offset != (bfd_vma) -1)
{
Elf_Internal_Rela rel;
bfd_byte *loc;
/* This symbol has an entry in the global offset table. Set it
up. */
@ -3978,8 +3926,6 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
{
asection *s;
Elf_Internal_Rela rel;
bfd_byte *loc;
/* This symbol needs a copy reloc. Set it up. */