: be,n 0(%sr0,%rp) ; inter-space return */
#define PLT_ENTRY_SIZE 8
-#define PLABEL_PLT_ENTRY_SIZE PLT_ENTRY_SIZE
#define GOT_ENTRY_SIZE 4
#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
/* Set if we need a .plt stub to support lazy dynamic linking. */
unsigned int need_plt_stub:1;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
};
/* Various hash macros and functions. */
static boolean elf32_hppa_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean hppa_handle_PIC_calls
+static boolean mark_PIC_calls
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean allocate_plt_static
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean allocate_dynrelocs
ret->has_12bit_branch = 0;
ret->has_17bit_branch = 0;
ret->need_plt_stub = 0;
+ ret->sym_sec.abfd = NULL;
return &ret->elf.root;
}
|| (h->elf.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
+ struct elf32_hppa_dyn_reloc_entry *p;
+ struct elf32_hppa_dyn_reloc_entry **head;
+
/* Create a reloc section in dynobj and make room for
this reloc. */
if (sreloc == NULL)
relocations we need for this symbol. */
if (h != NULL)
{
- struct elf32_hppa_dyn_reloc_entry *p;
+ head = &h->dyn_relocs;
+ }
+ else
+ {
+ /* Track dynamic relocs needed for local syms too.
+ We really need local syms available to do this
+ easily. Oh well. */
+
+ asection *s;
+ s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+ sec, r_symndx);
+ if (s == NULL)
+ return false;
- p = h->dyn_relocs;
- if (p == NULL || p->sec != sec)
- {
- p = ((struct elf32_hppa_dyn_reloc_entry *)
- bfd_alloc (htab->elf.dynobj,
- (bfd_size_type) sizeof *p));
- if (p == NULL)
- return false;
- p->next = h->dyn_relocs;
- h->dyn_relocs = p;
- p->sec = sec;
- p->count = 0;
+ head = ((struct elf32_hppa_dyn_reloc_entry **)
+ &elf_section_data (s)->local_dynrel);
+ }
+
+ p = *head;
+ if (p == NULL || p->sec != sec)
+ {
+ p = ((struct elf32_hppa_dyn_reloc_entry *)
+ bfd_alloc (htab->elf.dynobj,
+ (bfd_size_type) sizeof *p));
+ if (p == NULL)
+ return false;
+ p->next = *head;
+ *head = p;
+ p->sec = sec;
+ p->count = 0;
#if RELATIVE_DYNRELOCS
- p->relative_count = 0;
+ p->relative_count = 0;
#endif
- }
+ }
- p->count += 1;
+ p->count += 1;
#if RELATIVE_DYNRELOCS
- if (!IS_ABSOLUTE_RELOC (rtype))
- p->relative_count += 1;
+ if (!IS_ABSOLUTE_RELOC (rtype))
+ p->relative_count += 1;
#endif
- }
- else
- {
- /* Track dynamic relocs needed for local syms too. */
- elf_section_data (sec)->local_dynrel += 1;
- }
}
}
}
struct elf32_hppa_link_hash_table *htab;
bfd *dynobj;
- elf_section_data (sec)->local_dynrel = 0;
+ elf_section_data (sec)->local_dynrel = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
the first part of elf32_hppa_adjust_dynamic_symbol. */
static boolean
-hppa_handle_PIC_calls (h, inf)
+mark_PIC_calls (h, inf)
struct elf_link_hash_entry *h;
PTR inf ATTRIBUTE_UNUSED;
{
return true;
}
-/* Allocate space in .plt, .got and associated reloc sections for
- global syms. */
+/* Allocate space in the .plt for entries that won't have relocations.
+ ie. pic_call and plabel entries. */
static boolean
-allocate_dynrelocs (h, inf)
+allocate_plt_static (h, inf)
struct elf_link_hash_entry *h;
PTR inf;
{
struct bfd_link_info *info;
struct elf32_hppa_link_hash_table *htab;
asection *s;
- struct elf32_hppa_link_hash_entry *eh;
- struct elf32_hppa_dyn_reloc_entry *p;
if (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
info = (struct bfd_link_info *) inf;
htab = hppa_link_hash_table (info);
- if ((htab->elf.dynamic_sections_created
- && h->plt.refcount > 0)
- || ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
+ 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. */
+ s = htab->splt;
+ h->plt.offset = s->_raw_size;
+ s->_raw_size += PLT_ENTRY_SIZE;
+ }
+ else if (htab->elf.dynamic_sections_created
+ && h->plt.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0
- && h->type != STT_PARISC_MILLI
- && !((struct elf32_hppa_link_hash_entry *) h)->pic_call)
+ && h->type != STT_PARISC_MILLI)
{
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
- if (((struct elf32_hppa_link_hash_entry *) h)->pic_call
- || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
{
- /* Make an entry in the .plt section. */
+ /* Allocate these later. */
+ }
+ else if (((struct elf32_hppa_link_hash_entry *) h)->plabel)
+ {
+ /* Make an entry in the .plt section for plabel references
+ that won't have a .plt entry for other reasons. */
s = htab->splt;
h->plt.offset = s->_raw_size;
- if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
- && ((struct elf32_hppa_link_hash_entry *) h)->plabel
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- /* Add some extra space for the dynamic linker to use. */
- s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
- }
- else
- s->_raw_size += PLT_ENTRY_SIZE;
-
- if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
- {
- /* We also need to make an entry in the .rela.plt section. */
- htab->srelplt->_raw_size += sizeof (Elf32_External_Rela);
- htab->need_plt_stub = 1;
- }
+ s->_raw_size += PLT_ENTRY_SIZE;
}
else
{
+ /* No .plt entry needed. */
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
+ return true;
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+ global syms. */
+
+static boolean
+allocate_dynrelocs (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct bfd_link_info *info;
+ struct elf32_hppa_link_hash_table *htab;
+ asection *s;
+ struct elf32_hppa_link_hash_entry *eh;
+ struct elf32_hppa_dyn_reloc_entry *p;
+
+ if (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ return true;
+
+ info = (struct bfd_link_info *) 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
+ && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ {
+ /* Make an entry in the .plt section. */
+ s = htab->splt;
+ h->plt.offset = s->_raw_size;
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .rela.plt section. */
+ htab->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+ htab->need_plt_stub = 1;
+ }
+
if (h->got.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
eh->dyn_relocs = NULL;
return true;
- keep:
+ keep: ;
}
/* Finally, allocate space. */
Therefore we do not leave ELF_LINK_FORCED_LOCAL set. */
if (h->type == STT_PARISC_MILLI)
{
+ struct elf32_hppa_link_hash_table *htab;
unsigned short oldflags = h->elf_link_hash_flags;
+
h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
elf32_hppa_hide_symbol (info, h);
+ htab = hppa_link_hash_table (info);
+ _bfd_elf_strtab_delref (htab->elf.dynstr, h->dynstr_index);
h->elf_link_hash_flags &= ~ELF_LINK_FORCED_LOCAL;
h->elf_link_hash_flags |= oldflags & ELF_LINK_FORCED_LOCAL;
}
else
{
/* Run through the function symbols, looking for any that are
- PIC, and allocate space for the necessary .plt entries so
- that %r19 will be set up. */
+ PIC, and mark them as needing .plt entries so that %r19 will
+ be set up. */
if (! info->shared)
- elf_link_hash_traverse (&htab->elf,
- hppa_handle_PIC_calls,
- info);
+ elf_link_hash_traverse (&htab->elf, mark_PIC_calls, (PTR) info);
}
/* Set up .got and .plt offsets for local syms, and space for local
for (s = ibfd->sections; s != NULL; s = s->next)
{
- bfd_size_type count = elf_section_data (s)->local_dynrel;
+ struct elf32_hppa_dyn_reloc_entry *p;
- if (count != 0)
+ for (p = ((struct elf32_hppa_dyn_reloc_entry *)
+ elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
{
- srel = elf_section_data (s)->sreloc;
- srel->_raw_size += count * sizeof (Elf32_External_Rela);
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else
+ {
+ srel = elf_section_data (p->sec)->sreloc;
+ srel->_raw_size += p->count * sizeof (Elf32_External_Rela);
+ }
}
}
}
}
+ /* Do all the .plt entries without relocs first. The dynamic linker
+ uses the last .plt reloc to find the end of the .plt (and hence
+ the start of the .got) for lazy linking. */
+ elf_link_hash_traverse (&htab->elf, allocate_plt_static, (PTR) info);
+
/* Allocate global sym .plt and .got entries, and space for global
sym dynamic relocs. */
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
{
if (s->_raw_size != 0)
{
- /* Remember whether there are any reloc sections. */
- relocs = true;
+ /* Remember whether there are any reloc sections other
+ than .rela.plt. */
+ if (s != htab->srelplt)
+ relocs = true;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
if (! (info->shared
&& !info->no_undefined
&& (ELF_ST_VISIBILITY (hash->elf.other)
- == STV_DEFAULT)))
+ == STV_DEFAULT)
+ && hash->elf.type != STT_PARISC_MILLI))
continue;
}
else
/* This is a local symbol, h defaults to NULL. */
sym = local_syms + r_symndx;
sym_sec = local_sections[r_symndx];
- relocation = ((ELF_ST_TYPE (sym->st_info) == STT_SECTION
- ? 0 : sym->st_value)
- + sym_sec->output_offset
- + sym_sec->output_section->vma);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
}
else
{
case R_PARISC_DPREL14R:
case R_PARISC_DPREL21L:
case R_PARISC_DIR32:
+ /* r_symndx will be zero only for relocs against symbols
+ from removed linkonce sections, or sections discarded by
+ a linker script. */
+ if (r_symndx == 0
+ || (input_section->flags & SEC_ALLOC) == 0)
+ break;
+
/* The reloc types handled here and this conditional
expression must match the code in ..check_relocs and
- ..discard_relocs. ie. We need exactly the same condition
+ allocate_dynrelocs. ie. We need exactly the same condition
as in ..check_relocs, with some extra conditions (dynindx
test in this case) to cater for relocs removed by
- ..discard_relocs. If you squint, the non-shared test
+ allocate_dynrelocs. If you squint, the non-shared test
here does indeed match the one in ..check_relocs, the
difference being that here we test DEF_DYNAMIC as well as
!DEF_REGULAR. All common syms end up with !DEF_REGULAR,
Conversely, DEF_DYNAMIC can't be used in check_relocs as
there all files have not been loaded. */
if ((info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& (IS_ABSOLUTE_RELOC (r_type)
|| (h != NULL
&& h->elf.dynindx != -1
|| (h->elf.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
|| (!info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->elf.dynindx != -1
&& (h->elf.elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+ htab->splt->output_section->vma);
if (h->dynindx != -1)
{
- /* To support lazy linking, the function pointer is
- initialised to point to a special stub stored at the
- end of the .plt. This is not done for plt entries
- with a base-relative dynamic relocation. */
- value = (htab->splt->output_offset
- + htab->splt->output_section->vma
- + htab->splt->_raw_size
- - sizeof (plt_stub)
- + PLT_STUB_ENTRY);
rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_IPLT);
rel.r_addend = 0;
}
else
dyn.d_un.d_val = s->_raw_size;
break;
+
+ case DT_RELASZ:
+ /* Don't count procedure linkage table relocs in the
+ overall reloc count. */
+ if (htab->srelplt != NULL)
+ {
+ s = htab->srelplt->output_section;
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val -= s->_cooked_size;
+ else
+ dyn.d_un.d_val -= s->_raw_size;
+ }
+ break;
}
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);