string. */
#define STUB_SUFFIX ".stub"
-/* Setting the following non-zero makes all long branch stubs
- generated during a shared link of the PIC variety. This saves on
- relocs, but costs one extra instruction per stub. */
-#ifndef LONG_BRANCH_PIC_IN_SHLIB
-#define LONG_BRANCH_PIC_IN_SHLIB 1
-#endif
-
-/* Set this non-zero to use import stubs instead of long branch stubs
- where a .plt entry exists for the symbol. This is a fairly useless
- option as import stubs are bigger than PIC long branch stubs. */
-#ifndef LONG_BRANCH_VIA_PLT
-#define LONG_BRANCH_VIA_PLT 0
-#endif
-
-/* We don't need to copy any PC- or GP-relative dynamic relocs into a
- shared object's dynamic section. All the relocs of the limited
- class we are interested in, are absolute. See check_relocs. */
-#ifndef IS_ABSOLUTE_RELOC
+/* We don't need to copy certain PC- or GP-relative dynamic relocs
+ into a shared object's dynamic section. All the relocs of the
+ limited class we are interested in, are absolute. */
+#ifndef RELATIVE_DYNRELOCS
+#define RELATIVE_DYNRELOCS 0
#define IS_ABSOLUTE_RELOC(r_type) 1
#endif
/* The stub section. */
asection *stub_sec;
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- /* It's associated reloc section. */
- asection *reloc_sec;
-#endif
-
/* Offset within stub_sec of the beginning of this stub. */
bfd_vma stub_offset;
symbol. */
struct elf32_hppa_stub_hash_entry *stub_cache;
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- /* Used to track whether we have allocated space for a long branch
- stub relocation for this symbol in the given section. */
- asection *stub_reloc_sec;
-#endif
-
/* Used to count relocations for delayed sizing of relocation
sections. */
struct elf32_hppa_dyn_reloc_entry {
/* Next relocation in the chain. */
struct elf32_hppa_dyn_reloc_entry *next;
- /* The section in dynobj. */
- asection *section;
+ /* The input section of the reloc. */
+ asection *sec;
/* Number of relocs copied in this section. */
bfd_size_type count;
- } *reloc_entries;
+
+#if RELATIVE_DYNRELOCS
+ /* Number of relative relocs copied for the input section. */
+ bfd_size_type relative_count;
+#endif
+ } *dyn_relocs;
/* Set during a static link if we detect a function is PIC. */
unsigned int maybe_pic_call:1;
asection *link_sec;
/* The stub section. */
asection *stub_sec;
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- /* The stub section's reloc section. */
- asection *reloc_sec;
-#endif
} *stub_group;
/* Short-cuts to get to dynamic linker sections. */
static boolean hppa_handle_PIC_calls
PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean allocate_plt_and_got_and_discard_relocs
+static boolean allocate_dynrelocs
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean readonly_dynrelocs
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean clobber_millicode_symbols
PARAMS ((bfd *, struct bfd_link_info *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
+static enum elf_reloc_type_class elf32_hppa_reloc_type_class
+ PARAMS ((const Elf_Internal_Rela *));
+
static boolean elf32_hppa_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
{
/* Initialize the local fields. */
ret->stub_sec = NULL;
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- ret->reloc_sec = NULL;
-#endif
ret->stub_offset = 0;
ret->target_value = 0;
ret->target_section = NULL;
if (ret)
{
/* Initialize the local fields. */
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- ret->stub_reloc_sec = NULL;
-#endif
ret->stub_cache = NULL;
- ret->reloc_entries = NULL;
+ ret->dyn_relocs = NULL;
ret->maybe_pic_call = 0;
ret->pic_call = 0;
ret->plabel = 0;
}
stub_entry->stub_sec = stub_sec;
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- stub_entry->reloc_sec = hplink->stub_group[section->id].reloc_sec;
-#endif
stub_entry->stub_offset = 0;
stub_entry->id_sec = link_sec;
return stub_entry;
}
if (branch_offset + max_branch_offset >= 2*max_branch_offset)
- {
-#if LONG_BRANCH_VIA_PLT
- if (hash != NULL
- && hash->elf.dynindx != -1
- && hash->elf.plt.offset != (bfd_vma) -1
- && hash->elf.type != STT_PARISC_MILLI)
- {
- /* If we are doing a shared link and find we need a long
- branch stub, then go via the .plt if possible. */
- return hppa_stub_import;
- }
- else
-#endif
- return hppa_stub_long_branch;
- }
+ return hppa_stub_long_branch;
+
return hppa_stub_none;
}
insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);
bfd_put_32 (stub_bfd, insn, loc + 4);
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- if (info->shared)
- {
- /* Output a dynamic relocation for this stub. We only
- output one PCREL21L reloc per stub, trusting that the
- dynamic linker will also fix the implied PCREL17R for the
- second instruction. PCREL21L dynamic relocs had better
- never be emitted for some other purpose... */
- asection *srel;
- Elf_Internal_Rela outrel;
-
- if (stub_entry->h == NULL)
- {
- (*_bfd_error_handler)
- (_("%s(%s+0x%lx): cannot relocate %s, recompile with -ffunction-sections"),
- bfd_archive_filename (stub_entry->target_section->owner),
- stub_sec->name,
- (long) stub_entry->stub_offset,
- stub_entry->root.string);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- srel = stub_entry->reloc_sec;
- if (srel == NULL)
- {
- (*_bfd_error_handler)
- (_("Could not find relocation section for %s"),
- stub_sec->name);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- outrel.r_offset = (stub_entry->stub_offset
- + stub_sec->output_offset
- + stub_sec->output_section->vma);
- outrel.r_info = ELF32_R_INFO (0, R_PARISC_PCREL21L);
- outrel.r_addend = sym_value;
- bfd_elf32_swap_reloca_out (stub_sec->output_section->owner,
- &outrel,
- ((Elf32_External_Rela *)
- srel->contents + srel->reloc_count));
- ++srel->reloc_count;
- }
-#endif
size = 8;
break;
hplink = (struct elf32_hppa_link_hash_table *) in_arg;
if (stub_entry->stub_type == hppa_stub_long_branch)
- {
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- if (stub_entry->reloc_sec != NULL)
- stub_entry->reloc_sec->_raw_size += sizeof (Elf32_External_Rela);
-#endif
- size = 8;
- }
+ size = 8;
else if (stub_entry->stub_type == hppa_stub_long_branch_shared)
size = 12;
else if (stub_entry->stub_type == hppa_stub_export)
NEED_GOT = 1,
NEED_PLT = 2,
NEED_DYNREL = 4,
-#if LONG_BRANCH_PIC_IN_SHLIB
- NEED_STUBREL = 0, /* We won't be needing them in this case. */
-#else
- NEED_STUBREL = 8,
-#endif
- PLT_PLABEL = 16
+ PLT_PLABEL = 8
};
unsigned int r_symndx, r_type;
stub. Unfortunately, we have to cater for the case
where a symbol is forced local by versioning, or due
to symbolic linking, and we lose the .plt entry. */
- need_entry = NEED_PLT | NEED_STUBREL;
+ need_entry = NEED_PLT;
if (h->elf.type == STT_PARISC_MILLI)
- need_entry = NEED_STUBREL;
+ need_entry = 0;
}
break;
}
}
- if (need_entry & (NEED_DYNREL | NEED_STUBREL))
+ if (need_entry & NEED_DYNREL)
{
/* Flag this symbol as having a non-got, non-plt reference
so that we generate copy relocs if it turns out to be
have not seen all the input files, so it is possible that
DEF_REGULAR is not set now but will be set later (it is
never cleared). We account for that possibility below by
- storing information in the reloc_entries field of the
+ storing information in the dyn_relocs field of the
hash table entry.
A similar situation to the -Bsymbolic case occurs when
|| (h->elf.elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
- boolean doit;
- asection *srel;
-
- srel = sreloc;
- if ((need_entry & NEED_STUBREL))
- srel = stubreloc;
-
/* Create a reloc section in dynobj and make room for
this reloc. */
- if (srel == NULL)
+ if (sreloc == NULL)
{
char *name;
if (dynobj == NULL)
hplink->root.dynobj = dynobj = abfd;
- name = bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name);
+ name = (bfd_elf_string_from_elf_section
+ (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ elf_section_data (sec)->rel_hdr.sh_name));
if (name == NULL)
{
(*_bfd_error_handler)
return false;
}
- if ((need_entry & NEED_STUBREL))
- {
- bfd_size_type len = strlen (name) + sizeof (STUB_SUFFIX);
- char *newname = bfd_malloc (len);
-
- if (newname == NULL)
- return false;
- strcpy (newname, name);
- strcpy (newname + len - sizeof (STUB_SUFFIX),
- STUB_SUFFIX);
- name = newname;
- }
-
- srel = bfd_get_section_by_name (dynobj, name);
- if (srel == NULL)
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
{
flagword flags;
- srel = bfd_make_section (dynobj, name);
+ sreloc = bfd_make_section (dynobj, name);
flags = (SEC_HAS_CONTENTS | SEC_READONLY
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
if ((sec->flags & SEC_ALLOC) != 0)
flags |= SEC_ALLOC | SEC_LOAD;
- if (srel == NULL
- || !bfd_set_section_flags (dynobj, srel, flags)
- || !bfd_set_section_alignment (dynobj, srel, 2))
+ if (sreloc == NULL
+ || !bfd_set_section_flags (dynobj, sreloc, flags)
+ || !bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
}
- else if ((need_entry & NEED_STUBREL))
- free (name);
- if ((need_entry & NEED_STUBREL))
- stubreloc = srel;
- else
- sreloc = srel;
+ elf_section_data (sec)->sreloc = sreloc;
}
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- /* If this is a function call, we only need one dynamic
- reloc for the stub as all calls to a particular
- function will go through the same stub. Actually, a
- long branch stub needs two relocations, but we count
- on some intelligence on the part of the dynamic
- linker. */
- if ((need_entry & NEED_STUBREL))
+ /* If this is a global symbol, we count the number of
+ relocations we need for this symbol. */
+ if (h != NULL)
{
- doit = h->stub_reloc_sec != stubreloc;
- h->stub_reloc_sec = stubreloc;
- }
- else
-#endif
- doit = 1;
+ struct elf32_hppa_dyn_reloc_entry *p;
- if (doit)
- {
- srel->_raw_size += sizeof (Elf32_External_Rela);
-
- /* Keep track of relocations we have entered for
- this global symbol, so that we can discard them
- later if necessary. */
- if (!info->shared
- || (h != NULL
- && (! IS_ABSOLUTE_RELOC (rtype)
- || (need_entry & NEED_STUBREL))))
+ p = h->dyn_relocs;
+ if (p == NULL || p->sec != sec)
{
- struct elf32_hppa_dyn_reloc_entry *p;
-
- for (p = h->reloc_entries; p != NULL; p = p->next)
- if (p->section == srel)
- break;
-
+ p = ((struct elf32_hppa_dyn_reloc_entry *)
+ bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
if (p == NULL)
- {
- p = ((struct elf32_hppa_dyn_reloc_entry *)
- bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
- if (p == NULL)
- return false;
- p->next = h->reloc_entries;
- h->reloc_entries = p;
- p->section = srel;
- p->count = 0;
- }
-
- /* NEED_STUBREL and NEED_DYNREL are never both
- set. Leave the count at zero for the
- NEED_STUBREL case as we only ever have one
- stub reloc per section per symbol, and this
- simplifies code to discard unneeded relocs. */
- if (! (need_entry & NEED_STUBREL))
- ++p->count;
+ return false;
+ p->next = h->dyn_relocs;
+ h->dyn_relocs = p;
+ p->sec = sec;
+ p->count = 0;
+#if RELATIVE_DYNRELOCS
+ p->relative_count = 0;
+#endif
}
+
+ p->count += 1;
+#if RELATIVE_DYNRELOCS
+ 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 *hplink;
bfd *dynobj;
+ elf_section_data (sec)->local_dynrel = 0;
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
+ struct elf32_hppa_link_hash_entry *eh;
+ struct elf32_hppa_dyn_reloc_entry **pp;
+ struct elf32_hppa_dyn_reloc_entry *p;
+
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
+
+ eh = (struct elf32_hppa_link_hash_entry *) h;
+
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
+ if (p->sec == sec)
+ {
+#if RELATIVE_DYNRELOCS
+ if (!IS_ABSOLUTE_RELOC (rtype))
+ p->relative_count -= 1;
+#endif
+ p->count -= 1;
+ if (p->count == 0)
+ *pp = p->next;
+ break;
+ }
}
else if (local_plt_refcounts != NULL)
{
}
break;
+ case R_PARISC_DIR32:
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ struct elf32_hppa_link_hash_entry *eh;
+ struct elf32_hppa_dyn_reloc_entry **pp;
+ struct elf32_hppa_dyn_reloc_entry *p;
+
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ eh = (struct elf32_hppa_link_hash_entry *) h;
+
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
+ if (p->sec == sec)
+ {
+#if RELATIVE_DYNRELOCS
+ if (!IS_ABSOLUTE_RELOC (R_PARISC_DIR32))
+ p->relative_count -= 1;
+#endif
+ p->count -= 1;
+ if (p->count == 0)
+ *pp = p->next;
+ break;
+ }
+ }
+ break;
+
default:
break;
}
global syms. */
static boolean
-allocate_plt_and_got_and_discard_relocs (h, inf)
+allocate_dynrelocs (h, inf)
struct elf_link_hash_entry *h;
PTR inf;
{
struct elf32_hppa_link_hash_table *hplink;
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)
else
h->got.offset = (bfd_vma) -1;
- /* If this is a -Bsymbolic shared link, then we need to discard all
- space allocated for dynamic relocs against symbols defined in a
- regular object. For the normal shared case, discard space for
- relocs that have become local due to symbol visibility changes.
- For the non-shared case, discard space for symbols which turn out
- to need copy relocs or are not dynamic. We also need to lose
- relocs we've allocated for long branch stubs if we know we won't
- be generating a stub. */
-
eh = (struct elf32_hppa_link_hash_entry *) h;
- if (eh->reloc_entries == NULL)
+ if (eh->dyn_relocs == NULL)
return true;
- /* First handle the non-shared case. */
- if (!info->shared
- && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
- && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- || (hplink->root.dynamic_sections_created
- && (h->root.type == bfd_link_hash_undefweak
- || h->root.type == bfd_link_hash_undefined))))
+ /* If this is a -Bsymbolic shared link, then we need to discard all
+ space allocated for dynamic pc-relative relocs against symbols
+ defined in a regular object. For the normal shared case, discard
+ space for relocs that have become local due to symbol visibility
+ changes. */
+ if (info->shared)
{
- /* 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)
+#if RELATIVE_DYNRELOCS
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
+ || info->symbolic))
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
+ struct elf32_hppa_dyn_reloc_entry **pp;
- /* If that succeeded, we know we'll be keeping all the relocs. */
- if (h->dynindx != -1)
- return true;
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ {
+ p->count -= p->relative_count;
+ p->relative_count = 0;
+ if (p->count == 0)
+ *pp = p->next;
+ else
+ pp = &p->next;
+ }
+ }
+#endif
}
-
-#if ! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT
- /* Handle the stub reloc case. If we have a plt entry for the
- function, we won't be needing long branch stubs. c->count will
- only be zero for stub relocs, which provides a handy way of
- flagging these relocs, and means we need do nothing special for
- the forced local and symbolic link case. */
- if (eh->stub_reloc_sec != NULL
- && eh->elf.plt.offset != (bfd_vma) -1)
+ else
{
- struct elf32_hppa_dyn_reloc_entry *c;
+ /* For the non-shared case, discard space for relocs against
+ symbols which turn out to need copy relocs or are not
+ dynamic. */
+ if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+ && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ || (hplink->root.dynamic_sections_created
+ && (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined))))
+ {
+ /* 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)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ /* If that succeeded, we know we'll be keeping all the
+ relocs. */
+ if (h->dynindx != -1)
+ goto keep;
+ }
- for (c = eh->reloc_entries; c != NULL; c = c->next)
- if (c->count == 0)
- c->section->_raw_size -= sizeof (Elf32_External_Rela);
+ eh->dyn_relocs = NULL;
+ return true;
+
+ keep:
}
-#endif
- /* Discard any relocs in the non-shared case. For the shared case,
- if a symbol has been forced local or we have found a regular
- definition for the symbolic link case, then we won't be needing
- any relocs. */
- if (!info->shared
- || ((eh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
- && ((eh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
- || info->symbolic)))
+ /* Finally, allocate space. */
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
- struct elf32_hppa_dyn_reloc_entry *c;
-
- for (c = eh->reloc_entries; c != NULL; c = c->next)
- c->section->_raw_size -= c->count * sizeof (Elf32_External_Rela);
+ asection *sreloc = elf_section_data (p->sec)->sreloc;
+ sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela);
}
return true;
return true;
}
+/* Find any dynamic relocs that apply to read-only sections. */
+
+static boolean
+readonly_dynrelocs (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct elf32_hppa_link_hash_entry *eh;
+ struct elf32_hppa_dyn_reloc_entry *p;
+
+ eh = (struct elf32_hppa_link_hash_entry *) h;
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ {
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+ info->flags |= DF_TEXTREL;
+
+ /* Not an error, just cut short the traversal. */
+ return false;
+ }
+ }
+ return true;
+}
+
/* Set the sizes of the dynamic sections. */
static boolean
elf32_hppa_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
+ bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
struct elf32_hppa_link_hash_table *hplink;
bfd *dynobj;
- bfd *i;
+ bfd *ibfd;
asection *s;
boolean relocs;
- boolean reltext;
hplink = hppa_link_hash_table (info);
dynobj = hplink->root.dynobj;
info);
}
- /* Set up .got and .plt offsets for local syms. */
- for (i = info->input_bfds; i; i = i->link_next)
+ /* Set up .got and .plt offsets for local syms, and space for local
+ dynamic relocs. */
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
Elf_Internal_Shdr *symtab_hdr;
asection *srel;
- if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
- local_got = elf_local_got_refcounts (i);
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ {
+ bfd_size_type count = elf_section_data (s)->local_dynrel;
+
+ if (count != 0)
+ {
+ srel = elf_section_data (s)->sreloc;
+ srel->_raw_size += count * sizeof (Elf32_External_Rela);
+ }
+ }
+
+ local_got = elf_local_got_refcounts (ibfd);
if (!local_got)
continue;
- symtab_hdr = &elf_tdata (i)->symtab_hdr;
+ symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
s = hplink->sgot;
}
}
- /* Allocate global sym .plt and .got entries. Also discard all
- unneeded relocs. */
- elf_link_hash_traverse (&hplink->root,
- allocate_plt_and_got_and_discard_relocs,
- (PTR) info);
+ /* Allocate global sym .plt and .got entries, and space for global
+ sym dynamic relocs. */
+ elf_link_hash_traverse (&hplink->root, allocate_dynrelocs, (PTR) info);
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
relocs = false;
- reltext = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LINKER_CREATED) == 0)
{
if (s->_raw_size != 0)
{
- asection *target;
- const char *outname;
-
/* Remember whether there are any reloc sections other
than .rela.plt. */
if (s != hplink->srelplt)
relocs = true;
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL entry. */
- outname = bfd_get_section_name (output_bfd,
- s->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 5);
- if (target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0)
- reltext = true;
-
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
s->reloc_count = 0;
|| !add_dynamic_entry (DT_RELASZ, 0)
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
return false;
- }
- if (reltext)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return false;
- info->flags |= DF_TEXTREL;
+ /* If any dynamic relocs apply to a read-only section,
+ then we need a DT_TEXTREL entry. */
+ elf_link_hash_traverse (&hplink->root, readonly_dynrelocs, (PTR) info);
+
+ if ((info->flags & DF_TEXTREL) != 0)
+ {
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
+ return false;
+ }
}
}
#undef add_dynamic_entry
/* Now we can free the external symbols. */
free (ext_syms);
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- /* If this is a shared link, find all the stub reloc sections. */
- if (info->shared)
- for (section = input_bfd->sections;
- section != NULL;
- section = section->next)
- {
- char *name;
- asection *reloc_sec;
-
- name = bfd_malloc ((bfd_size_type) strlen (section->name)
- + sizeof STUB_SUFFIX
- + 5);
- if (name == NULL)
- return false;
- sprintf (name, ".rela%s%s", section->name, STUB_SUFFIX);
- reloc_sec = bfd_get_section_by_name (hplink->root.dynobj, name);
- hplink->stub_group[section->id].reloc_sec = reloc_sec;
- free (name);
- }
-#endif
-
if (info->shared && hplink->multi_subspace)
{
struct elf_link_hash_entry **sym_hashes;
{
if (stub_type == hppa_stub_import)
stub_entry->stub_type = hppa_stub_import_shared;
- else if (stub_type == hppa_stub_long_branch
- && (LONG_BRANCH_PIC_IN_SHLIB || hash == NULL))
+ else if (stub_type == hppa_stub_long_branch)
stub_entry->stub_type = hppa_stub_long_branch_shared;
}
stub_entry->h = hash;
stub_sec->_raw_size = 0;
stub_sec->_cooked_size = 0;
}
-#if ! LONG_BRANCH_PIC_IN_SHLIB
- {
- int i;
-
- for (i = top_id; i >= 0; --i)
- {
- /* This will probably hit the same section many times.. */
- stub_sec = hplink->stub_group[i].reloc_sec;
- if (stub_sec != NULL)
- {
- stub_sec->_raw_size = 0;
- stub_sec->_cooked_size = 0;
- }
- }
- }
-#endif
bfd_hash_traverse (&hplink->stub_hash_table,
hppa_size_one_stub,
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- asection *sreloc;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
hplink = hppa_link_hash_table (info);
dynobj = hplink->root.dynobj;
local_got_offsets = elf_local_got_offsets (input_bfd);
- sreloc = NULL;
rel = relocs;
relend = relocs + input_section->reloc_count;
{
Elf_Internal_Rela outrel;
boolean skip;
+ asection *sreloc;
+ Elf32_External_Rela *loc;
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
- if (sreloc == NULL)
- {
- const char *name;
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd,
- elf_elfheader (input_bfd)->e_shstrndx,
- elf_section_data (input_section)->rel_hdr.sh_name));
- if (name == NULL)
- return false;
- sreloc = bfd_get_section_by_name (dynobj, name);
- if (sreloc == NULL)
- abort ();
- }
-
outrel.r_offset = rel->r_offset;
outrel.r_addend = rel->r_addend;
skip = false;
outrel.r_info = ELF32_R_INFO (ELF32_R_SYM (outrel.r_info),
R_PARISC_DIR32U);
#endif
- bfd_elf32_swap_reloca_out (output_bfd, &outrel,
- ((Elf32_External_Rela *)
- sreloc->contents
- + sreloc->reloc_count));
- ++sreloc->reloc_count;
+ sreloc = elf_section_data (input_section)->sreloc;
+ if (sreloc == NULL)
+ abort ();
+
+ loc = ((Elf32_External_Rela *) sreloc->contents
+ + sreloc->reloc_count);
+ sreloc->reloc_count += 1;
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
}
break;
return true;
}
+/* Used to decide how to sort relocs in an optimal manner for the
+ dynamic linker, before writing them out. */
+
+static enum elf_reloc_type_class
+elf32_hppa_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
+{
+ if (ELF32_R_SYM (rela->r_info) == 0)
+ return reloc_class_relative;
+
+ switch ((int) ELF32_R_TYPE (rela->r_info))
+ {
+ case R_PARISC_IPLT:
+ return reloc_class_plt;
+ case R_PARISC_COPY:
+ return reloc_class_copy;
+ default:
+ return reloc_class_normal;
+ }
+}
+
/* Finish up the dynamic sections. */
static boolean
#define elf_backend_final_write_processing elf_hppa_final_write_processing
#define elf_backend_post_process_headers elf32_hppa_post_process_headers
#define elf_backend_get_symbol_type elf32_hppa_elf_get_symbol_type
+#define elf_backend_reloc_type_class elf32_hppa_reloc_type_class
#define elf_backend_can_gc_sections 1
#define elf_backend_plt_alignment 2