diff options
Diffstat (limited to 'bfd/elf32-hppa.c')
-rw-r--r-- | bfd/elf32-hppa.c | 542 |
1 files changed, 296 insertions, 246 deletions
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 5a65dcb..f0fd549 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -71,14 +71,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ (single sub-space version) : addil LR'lt_ptr+ltoff,%dp ; get procedure entry point : ldw RR'lt_ptr+ltoff(%r1),%r21 - : bv %r0(%r21) + : bv %r0(%r21) : ldw RR'lt_ptr+ltoff+4(%r1),%r19 ; get new dlt value. Import stub to call shared library routine from shared library (single sub-space version) : addil LR'ltoff,%r19 ; get procedure entry point : ldw RR'ltoff(%r1),%r21 - : bv %r0(%r21) + : bv %r0(%r21) : ldw RR'ltoff+4(%r1),%r19 ; get new dlt value. Import stub to call shared library routine from normal object file @@ -203,9 +203,6 @@ struct elf32_hppa_link_hash_entry { #endif } *dyn_relocs; - /* Set during a static link if we detect a function is PIC. */ - unsigned int maybe_pic_call:1; - /* Set if the only reason we need a .plt entry is for a non-PIC to PIC function call. */ unsigned int pic_call:1; @@ -239,6 +236,12 @@ struct elf32_hppa_link_hash_table { asection *stub_sec; } *stub_group; + /* Assorted information used by elf32_hppa_size_stubs. */ + unsigned int bfd_count; + int top_index; + asection **input_list; + Elf_Internal_Sym **all_local_syms; + /* Short-cuts to get to dynamic linker sections. */ asection *sgot; asection *srelgot; @@ -255,10 +258,11 @@ struct elf32_hppa_link_hash_table { /* Whether we support multiple sub-spaces for shared libs. */ unsigned int multi_subspace:1; - /* Flags set when PCREL12F and PCREL17F branches detected. Used to + /* Flags set when various size branches are detected. Used to select suitable defaults for the stub group size. */ unsigned int has_12bit_branch:1; unsigned int has_17bit_branch:1; + unsigned int has_22bit_branch:1; /* Set if we need a .plt stub to support lazy dynamic linking. */ unsigned int need_plt_stub:1; @@ -284,6 +288,9 @@ static struct bfd_hash_entry *hppa_link_hash_newfunc static struct bfd_link_hash_table *elf32_hppa_link_hash_table_create PARAMS ((bfd *)); +static void elf32_hppa_link_hash_table_free + PARAMS ((struct bfd_link_hash_table *)); + /* Stub handling functions. */ static char *hppa_stub_name PARAMS ((const asection *, const asection *, @@ -358,6 +365,12 @@ static boolean clobber_millicode_symbols static boolean elf32_hppa_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); +static void group_sections + PARAMS ((struct elf32_hppa_link_hash_table *, bfd_size_type, boolean)); + +static int get_local_syms + PARAMS ((bfd *, bfd *, struct bfd_link_info *)); + static boolean elf32_hppa_final_link PARAMS ((bfd *, struct bfd_link_info *)); @@ -373,9 +386,6 @@ static boolean elf32_hppa_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -static int hppa_unwind_entry_compare - PARAMS ((const PTR, const PTR)); - static boolean elf32_hppa_finish_dynamic_symbol PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); @@ -460,7 +470,6 @@ hppa_link_hash_newfunc (entry, table, string) eh = (struct elf32_hppa_link_hash_entry *) entry; eh->stub_cache = NULL; eh->dyn_relocs = NULL; - eh->maybe_pic_call = 0; eh->pic_call = 0; eh->plabel = 0; } @@ -479,13 +488,13 @@ elf32_hppa_link_hash_table_create (abfd) struct elf32_hppa_link_hash_table *ret; bfd_size_type amt = sizeof (*ret); - ret = (struct elf32_hppa_link_hash_table *) bfd_alloc (abfd, amt); + ret = (struct elf32_hppa_link_hash_table *) bfd_malloc (amt); if (ret == NULL) return NULL; if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, hppa_link_hash_newfunc)) { - bfd_release (abfd, ret); + free (ret); return NULL; } @@ -508,12 +517,26 @@ elf32_hppa_link_hash_table_create (abfd) ret->multi_subspace = 0; ret->has_12bit_branch = 0; ret->has_17bit_branch = 0; + ret->has_22bit_branch = 0; ret->need_plt_stub = 0; ret->sym_sec.abfd = NULL; return &ret->elf.root; } +/* Free the derived linker hash table. */ + +static void +elf32_hppa_link_hash_table_free (hash) + struct bfd_link_hash_table *hash; +{ + struct elf32_hppa_link_hash_table *ret + = (struct elf32_hppa_link_hash_table *) hash; + + bfd_hash_table_free (&ret->stub_hash_table); + _bfd_generic_link_hash_table_free (hash); +} + /* Build a name for an entry in the stub hash table. */ static char * @@ -670,21 +693,12 @@ hppa_type_of_stub (input_sec, rel, hash, destination) unsigned int r_type; if (hash != NULL - && (((hash->elf.root.type == bfd_link_hash_defined - || hash->elf.root.type == bfd_link_hash_defweak) - && hash->elf.root.u.def.section->output_section == NULL) - || (hash->elf.root.type == bfd_link_hash_defweak - && hash->elf.dynindx != -1 - && hash->elf.plt.offset != (bfd_vma) -1) - || hash->elf.root.type == bfd_link_hash_undefweak - || hash->elf.root.type == bfd_link_hash_undefined - || (hash->maybe_pic_call && !(input_sec->flags & SEC_HAS_GOT_REF)))) + && hash->elf.plt.offset != (bfd_vma) -1 + && (hash->elf.dynindx != -1 || hash->pic_call) + && !hash->plabel) { - /* If output_section is NULL, then it's a symbol defined in a - shared library. We will need an import stub. Decide between - hppa_stub_import and hppa_stub_import_shared later. For - shared links we need stubs for undefined or weak syms too; - They will presumably be resolved by the dynamic linker. */ + /* We need an import stub. Decide between hppa_stub_import + and hppa_stub_import_shared later. */ return hppa_stub_import; } @@ -742,6 +756,7 @@ hppa_type_of_stub (input_sec, rel, hash, destination) #define BE_SR0_R21 0xe2a00000 /* be 0(%sr0,%r21) */ #define STW_RP 0x6bc23fd1 /* stw %rp,-24(%sr0,%sp) */ +#define BL22_RP 0xe800a002 /* b,l,n XXX,%rp */ #define BL_RP 0xe8400002 /* b,l,n XXX,%rp */ #define NOP 0x08000240 /* nop */ #define LDW_RP 0x4bc23fd1 /* ldw -24(%sr0,%sp),%rp */ @@ -931,7 +946,9 @@ hppa_build_one_stub (gen_entry, in_arg) + stub_sec->output_offset + stub_sec->output_section->vma); - if (sym_value - 8 + 0x40000 >= 0x80000) + if (sym_value - 8 + (1 << (17 + 1)) >= (1 << (17 + 2)) + && (!htab->has_22bit_branch + || sym_value - 8 + (1 << (22 + 1)) >= (1 << (22 + 2)))) { (*_bfd_error_handler) (_("%s(%s+0x%lx): cannot reach %s, recompile with -ffunction-sections"), @@ -944,7 +961,10 @@ hppa_build_one_stub (gen_entry, in_arg) } val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_fsel) >> 2; - insn = hppa_rebuild_insn ((int) BL_RP, val, 17); + if (!htab->has_22bit_branch) + insn = hppa_rebuild_insn ((int) BL_RP, val, 17); + else + insn = hppa_rebuild_insn ((int) BL22_RP, val, 22); bfd_put_32 (stub_bfd, insn, loc); bfd_put_32 (stub_bfd, (bfd_vma) NOP, loc + 4); @@ -1263,12 +1283,16 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) case R_PARISC_PCREL12F: htab->has_12bit_branch = 1; - /* Fall thru. */ + goto branch_common; + case R_PARISC_PCREL17C: case R_PARISC_PCREL17F: htab->has_17bit_branch = 1; - /* Fall thru. */ + goto branch_common; + case R_PARISC_PCREL22F: + htab->has_22bit_branch = 1; + branch_common: /* Function calls might need to go through the .plt, and might require long branch stubs. */ if (h == NULL) @@ -1322,7 +1346,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) case R_PARISC_DIR14F: /* Used for load/store from absolute locn. */ case R_PARISC_DIR14R: case R_PARISC_DIR21L: /* As above, and for ext branches too. */ -#if 1 +#if 0 /* Help debug shared library creation. Any of the above relocs can be used in shared libs, but they may cause pages to become unshared. */ @@ -1838,19 +1862,10 @@ elf32_hppa_adjust_dynamic_symbol (info, h) unsigned int power_of_two; /* If this is a function, put it in the procedure linkage table. We - will fill in the contents of the procedure linkage table later, - when we know the address of the .got section. */ + will fill in the contents of the procedure linkage table later. */ if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { - 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)->maybe_pic_call = 1; - } - if (h->plt.refcount <= 0 || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 && h->root.type != bfd_link_hash_defweak @@ -1867,7 +1882,10 @@ elf32_hppa_adjust_dynamic_symbol (info, h) /* As a special sop to the hppa ABI, we keep a .plt entry for functions in sections containing PIC code. */ - if (((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call) + 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 { @@ -1918,7 +1936,7 @@ elf32_hppa_adjust_dynamic_symbol (info, h) } /* If we didn't find any dynamic relocs in read-only sections, then - we'll be keeping the dynamic relocs and avoiding the copy reloc. */ + we'll be keeping the dynamic relocs and avoiding the copy reloc. */ if (p == NULL) { h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; @@ -1982,6 +2000,9 @@ mark_PIC_calls (h, inf) struct elf_link_hash_entry *h; PTR 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) @@ -1993,7 +2014,6 @@ mark_PIC_calls (h, inf) } h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - ((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1; ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1; return true; @@ -2011,16 +2031,19 @@ allocate_plt_static (h, inf) struct elf32_hppa_link_hash_table *htab; asection *s; - if (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) + if (h->root.type == bfd_link_hash_indirect) return true; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + info = (struct bfd_link_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; @@ -2040,7 +2063,11 @@ allocate_plt_static (h, inf) if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) { - /* Allocate these later. */ + /* Allocate these later. From this point on, h->plabel + means that the plt entry is only used by a plabel. + We'll be using a normal plt entry for this symbol, so + clear the plabel indicator. */ + ((struct elf32_hppa_link_hash_entry *) h)->plabel = 0; } else if (((struct elf32_hppa_link_hash_entry *) h)->plabel) { @@ -2080,16 +2107,18 @@ allocate_dynrelocs (h, inf) 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) + if (h->root.type == bfd_link_hash_indirect) return true; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + 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)) + && !((struct elf32_hppa_link_hash_entry *) h)->plabel) { /* Make an entry in the .plt section. */ s = htab->splt; @@ -2213,14 +2242,13 @@ clobber_millicode_symbols (h, info) struct elf_link_hash_entry *h; struct bfd_link_info *info; { + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + if (h->type == STT_PARISC_MILLI && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { elf32_hppa_hide_symbol (info, h, true); - - /* ?!? We only want to remove these from the dynamic symbol table. - Therefore we do not leave ELF_LINK_FORCED_LOCAL set. */ - h->elf_link_hash_flags &= ~ELF_LINK_FORCED_LOCAL; } return true; } @@ -2235,6 +2263,9 @@ readonly_dynrelocs (h, inf) struct elf32_hppa_link_hash_entry *eh; struct elf32_hppa_dyn_reloc_entry *p; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + eh = (struct elf32_hppa_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { @@ -2525,57 +2556,25 @@ elf32_hppa_size_dynamic_sections (output_bfd, info) /* External entry points for sizing and building linker stubs. */ -/* Determine and set the size of the stub section for a final link. +/* Set up various things so that we can make a list of input sections + for each output section included in the link. Returns -1 on error, + 0 when no stubs will be needed, and 1 on success. */ - The basic idea here is to examine all the relocations looking for - PC-relative calls to a target that is unreachable with a "bl" - instruction. */ - -boolean -elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, - add_stub_section, layout_sections_again) +int +elf32_hppa_setup_section_lists (output_bfd, info) bfd *output_bfd; - bfd *stub_bfd; struct bfd_link_info *info; - boolean multi_subspace; - bfd_signed_vma group_size; - asection * (*add_stub_section) PARAMS ((const char *, asection *)); - void (*layout_sections_again) PARAMS ((void)); { bfd *input_bfd; + unsigned int bfd_count; + int top_id, top_index; asection *section; asection **input_list, **list; - Elf_Internal_Sym *local_syms, **all_local_syms; - unsigned int bfd_indx, bfd_count; - int top_id, top_index; - struct elf32_hppa_link_hash_table *htab; - bfd_size_type stub_group_size; - boolean stubs_always_before_branch; - boolean stub_changed = 0; - boolean ret = 0; bfd_size_type amt; + struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info); - htab = hppa_link_hash_table (info); - - /* Stash our params away. */ - htab->stub_bfd = stub_bfd; - htab->multi_subspace = multi_subspace; - htab->add_stub_section = add_stub_section; - htab->layout_sections_again = layout_sections_again; - stubs_always_before_branch = group_size < 0; - if (group_size < 0) - stub_group_size = -group_size; - else - stub_group_size = group_size; - if (stub_group_size == 1) - { - /* Default values. */ - stub_group_size = 7680000; - if (htab->has_17bit_branch || htab->multi_subspace) - stub_group_size = 240000; - if (htab->has_12bit_branch) - stub_group_size = 7500; - } + if (htab->elf.root.creator->flavour != bfd_target_elf_flavour) + return 0; /* Count the number of input BFDs and find the top input section id. */ for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0; @@ -2591,16 +2590,14 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, top_id = section->id; } } + htab->bfd_count = bfd_count; amt = sizeof (struct map_stub) * (top_id + 1); htab->stub_group = (struct map_stub *) bfd_zmalloc (amt); if (htab->stub_group == NULL) - return false; - - /* Make a list of input sections for each output section included in - the link. + return -1; - We can't use output_bfd->section_count here to find the top output + /* We can't use output_bfd->section_count here to find the top output section index as some sections may have been removed, and _bfd_strip_section_from_output doesn't renumber the indices. */ for (section = output_bfd->sections, top_index = 0; @@ -2611,10 +2608,12 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, top_index = section->index; } + htab->top_index = top_index; amt = sizeof (asection *) * (top_index + 1); input_list = (asection **) bfd_malloc (amt); + htab->input_list = input_list; if (input_list == NULL) - return false; + return -1; /* For sections we aren't interested in, mark their entries with a value we can check later. */ @@ -2631,40 +2630,50 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, input_list[section->index] = NULL; } - /* Now actually build the lists. */ - for (input_bfd = info->input_bfds; - input_bfd != NULL; - input_bfd = input_bfd->link_next) + return 1; +} + +/* The linker repeatedly calls this function for each input section, + in the order that input sections are linked into output sections. + Build lists of input sections to determine groupings between which + we may insert linker stubs. */ + +void +elf32_hppa_next_input_section (info, isec) + struct bfd_link_info *info; + asection *isec; +{ + struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info); + + if (isec->output_section->index <= htab->top_index) { - for (section = input_bfd->sections; - section != NULL; - section = section->next) + asection **list = htab->input_list + isec->output_section->index; + if (*list != bfd_abs_section_ptr) { - if (section->output_section != NULL - && section->output_section->owner == output_bfd - && section->output_section->index <= top_index) - { - list = input_list + section->output_section->index; - if (*list != bfd_abs_section_ptr) - { - /* Steal the link_sec pointer for our list. */ + /* Steal the link_sec pointer for our list. */ #define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec) - /* This happens to make the list in reverse order, - which is what we want. */ - PREV_SEC (section) = *list; - *list = section; - } - } + /* This happens to make the list in reverse order, + which is what we want. */ + PREV_SEC (isec) = *list; + *list = isec; } } +} - /* See whether we can group stub sections together. Grouping stub - sections may result in fewer stubs. More importantly, we need to - put all .init* and .fini* stubs at the beginning of the .init or - .fini output sections respectively, because glibc splits the - _init and _fini functions into multiple parts. Putting a stub in - the middle of a function is not a good idea. */ - list = input_list + top_index; +/* See whether we can group stub sections together. Grouping stub + sections may result in fewer stubs. More importantly, we need to + put all .init* and .fini* stubs at the beginning of the .init or + .fini output sections respectively, because glibc splits the + _init and _fini functions into multiple parts. Putting a stub in + the middle of a function is not a good idea. */ + +static void +group_sections (htab, stub_group_size, stubs_always_before_branch) + struct elf32_hppa_link_hash_table *htab; + bfd_size_type stub_group_size; + boolean stubs_always_before_branch; +{ + asection **list = htab->input_list + htab->top_index; do { asection *tail = *list; @@ -2724,22 +2733,39 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, tail = prev; } } - while (list-- != input_list); - free (input_list); + while (list-- != htab->input_list); + free (htab->input_list); #undef PREV_SEC +} + +/* Read in all local syms for all input bfds, and create hash entries + for export stubs if we are building a multi-subspace shared lib. + Returns -1 on error, 1 if export stubs created, 0 otherwise. */ + +static int +get_local_syms (output_bfd, input_bfd, info) + bfd *output_bfd; + bfd *input_bfd; + struct bfd_link_info *info; +{ + unsigned int bfd_indx; + Elf_Internal_Sym *local_syms, **all_local_syms; + int stub_changed = 0; + struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info); /* We want to read in symbol extension records only once. To do this we need to read in the local symbols in parallel and save them for later use; so hold pointers to the local symbols in an array. */ - amt = sizeof (Elf_Internal_Sym *) * bfd_count; + bfd_size_type amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count; all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt); + htab->all_local_syms = all_local_syms; if (all_local_syms == NULL) - return false; + return -1; /* Walk over all the input BFDs, swapping in local symbols. If we are creating a shared library, create hash entries for the export stubs. */ - for (input_bfd = info->input_bfds, bfd_indx = 0; + for (bfd_indx = 0; input_bfd != NULL; input_bfd = input_bfd->link_next, bfd_indx++) { @@ -2761,21 +2787,21 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, sec_size *= sizeof (Elf_Internal_Sym); local_syms = (Elf_Internal_Sym *) bfd_malloc (sec_size); if (local_syms == NULL) - goto error_ret_free_local; + return -1; all_local_syms[bfd_indx] = local_syms; sec_size = symtab_hdr->sh_info; sec_size *= sizeof (Elf32_External_Sym); ext_syms = (Elf32_External_Sym *) bfd_malloc (sec_size); if (ext_syms == NULL) - goto error_ret_free_local; + return -1; if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 || bfd_bread ((PTR) ext_syms, sec_size, input_bfd) != sec_size) { error_ret_free_ext_syms: free (ext_syms); - goto error_ret_free_local; + return -1; } shndx_buf = NULL; @@ -2858,7 +2884,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, { stub_entry = hppa_add_stub (stub_name, sec, htab); if (!stub_entry) - goto error_ret_free_local; + return -1; stub_entry->target_value = hash->elf.root.u.def.value; stub_entry->target_section = hash->elf.root.u.def.section; @@ -2877,8 +2903,74 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, } } + return stub_changed; +} + +/* Determine and set the size of the stub section for a final link. + + The basic idea here is to examine all the relocations looking for + PC-relative calls to a target that is unreachable with a "bl" + instruction. */ + +boolean +elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, + add_stub_section, layout_sections_again) + bfd *output_bfd; + bfd *stub_bfd; + struct bfd_link_info *info; + boolean multi_subspace; + bfd_signed_vma group_size; + asection * (*add_stub_section) PARAMS ((const char *, asection *)); + void (*layout_sections_again) PARAMS ((void)); +{ + bfd_size_type stub_group_size; + boolean stubs_always_before_branch; + boolean stub_changed; + boolean ret = 0; + struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info); + + /* Stash our params away. */ + htab->stub_bfd = stub_bfd; + htab->multi_subspace = multi_subspace; + htab->add_stub_section = add_stub_section; + htab->layout_sections_again = layout_sections_again; + stubs_always_before_branch = group_size < 0; + if (group_size < 0) + stub_group_size = -group_size; + else + stub_group_size = group_size; + if (stub_group_size == 1) + { + /* Default values. */ + stub_group_size = 7680000; + if (htab->has_17bit_branch || htab->multi_subspace) + stub_group_size = 240000; + if (htab->has_12bit_branch) + stub_group_size = 7500; + } + + group_sections (htab, stub_group_size, stubs_always_before_branch); + + switch (get_local_syms (output_bfd, info->input_bfds, info)) + { + default: + if (htab->all_local_syms) + goto error_ret_free_local; + return false; + + case 0: + stub_changed = false; + break; + + case 1: + stub_changed = true; + break; + } + while (1) { + bfd *input_bfd; + unsigned int bfd_indx; asection *stub_sec; for (input_bfd = info->input_bfds, bfd_indx = 0; @@ -2886,13 +2978,15 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, input_bfd = input_bfd->link_next, bfd_indx++) { Elf_Internal_Shdr *symtab_hdr; + asection *section; + Elf_Internal_Sym *local_syms; /* We'll need the symbol table in a second. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (symtab_hdr->sh_info == 0) continue; - local_syms = all_local_syms[bfd_indx]; + local_syms = htab->all_local_syms[bfd_indx]; /* Walk over each section attached to the input bfd. */ for (section = input_bfd->sections; @@ -2902,6 +2996,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, Elf_Internal_Shdr *input_rel_hdr; Elf32_External_Rela *external_relocs, *erelaend, *erela; Elf_Internal_Rela *internal_relocs, *irelaend, *irela; + bfd_size_type amt; /* If there aren't any relocs, then there's nothing more to do. */ @@ -3033,19 +3128,9 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, + sym_sec->output_section->vma); } else if (hash->elf.root.type == bfd_link_hash_undefweak) - { - if (! info->shared) - continue; - } + ; else if (hash->elf.root.type == bfd_link_hash_undefined) - { - if (! (info->shared - && !info->no_undefined - && (ELF_ST_VISIBILITY (hash->elf.other) - == STV_DEFAULT) - && hash->elf.type != STT_PARISC_MILLI)) - continue; - } + ; else { bfd_set_error (bfd_error_bad_value); @@ -3095,7 +3180,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, stub_entry->stub_type = hppa_stub_long_branch_shared; } stub_entry->h = hash; - stub_changed = 1; + stub_changed = true; } /* We're done with the internal relocs, free them. */ @@ -3120,16 +3205,16 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); - stub_changed = 0; + stub_changed = false; } - ret = 1; + ret = true; error_ret_free_local: - while (bfd_count-- > 0) - if (all_local_syms[bfd_count]) - free (all_local_syms[bfd_count]); - free (all_local_syms); + while (htab->bfd_count-- > 0) + if (htab->all_local_syms[htab->bfd_count]) + free (htab->all_local_syms[htab->bfd_count]); + free (htab->all_local_syms); return ret; } @@ -3142,23 +3227,39 @@ elf32_hppa_set_gp (abfd, info) bfd *abfd; struct bfd_link_info *info; { + struct bfd_link_hash_entry *h; + asection *sec = NULL; + bfd_vma gp_val = 0; struct elf32_hppa_link_hash_table *htab; - struct elf_link_hash_entry *h; - asection *sec; - bfd_vma gp_val; htab = hppa_link_hash_table (info); - h = elf_link_hash_lookup (&htab->elf, "$global$", false, false, false); + h = bfd_link_hash_lookup (&htab->elf.root, "$global$", false, false, false); if (h != NULL - && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak)) + && (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak)) { - gp_val = h->root.u.def.value; - sec = h->root.u.def.section; + gp_val = h->u.def.value; + sec = h->u.def.section; } else { + asection *splt; + asection *sgot; + + if (htab->elf.root.creator->flavour == bfd_target_elf_flavour) + { + splt = htab->splt; + sgot = htab->sgot; + } + else + { + /* If we're not elf, look up the output sections in the + hope we may actually find them. */ + splt = bfd_get_section_by_name (abfd, ".plt"); + sgot = bfd_get_section_by_name (abfd, ".got"); + } + /* Choose to point our LTP at, in this order, one of .plt, .got, or .data, if these sections exist. In the case of choosing .plt try to make the LTP ideal for addressing anywhere in the @@ -3167,21 +3268,18 @@ elf32_hppa_set_gp (abfd, info) if either the .plt or .got is larger than 0x2000. If both the .plt and .got are smaller than 0x2000, choose the end of the .plt section. */ - - sec = htab->splt; + sec = splt; if (sec != NULL) { gp_val = sec->_raw_size; - if (gp_val > 0x2000 - || (htab->sgot && htab->sgot->_raw_size > 0x2000)) + if (gp_val > 0x2000 || (sgot && sgot->_raw_size > 0x2000)) { gp_val = 0x2000; } } else { - gp_val = 0; - sec = htab->sgot; + sec = sgot; if (sec != NULL) { /* We know we don't have a .plt. If .got is large, @@ -3198,12 +3296,12 @@ elf32_hppa_set_gp (abfd, info) if (h != NULL) { - h->root.type = bfd_link_hash_defined; - h->root.u.def.value = gp_val; + h->type = bfd_link_hash_defined; + h->u.def.value = gp_val; if (sec != NULL) - h->root.u.def.section = sec; + h->u.def.section = sec; else - h->root.u.def.section = bfd_abs_section_ptr; + h->u.def.section = bfd_abs_section_ptr; } } @@ -3258,37 +3356,13 @@ elf32_hppa_final_link (abfd, info) bfd *abfd; struct bfd_link_info *info; { - asection *s; - /* Invoke the regular ELF linker to do all the work. */ if (!bfd_elf32_bfd_final_link (abfd, info)) return false; /* If we're producing a final executable, sort the contents of the - unwind section. Magic section names, but this is much safer than - having elf32_hppa_relocate_section remember where SEGREL32 relocs - occurred. Consider what happens if someone inept creates a - linker script that puts unwind information in .text. */ - s = bfd_get_section_by_name (abfd, ".PARISC.unwind"); - if (s != NULL) - { - bfd_size_type size; - char *contents; - - size = s->_raw_size; - contents = bfd_malloc (size); - if (contents == NULL) - return false; - - if (! bfd_get_section_contents (abfd, s, contents, (file_ptr) 0, size)) - return false; - - qsort (contents, (size_t) (size / 16), 16, hppa_unwind_entry_compare); - - if (! bfd_set_section_contents (abfd, s, contents, (file_ptr) 0, size)) - return false; - } - return true; + unwind section. */ + return elf_hppa_sort_unwind (abfd); } /* Record the lowest address for the data and text segments. */ @@ -3361,19 +3435,14 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h) case R_PARISC_PCREL12F: case R_PARISC_PCREL17F: case R_PARISC_PCREL22F: - /* If this is a call to a function defined in another dynamic - library, or if it is a call to a PIC function in the same - object, or if this is a shared link and it is a call to a - weak symbol which may or may not be in the same object, then - find the import stub in the stub hash. */ + /* If this call should go via the plt, find the import stub in + the stub hash. */ if (sym_sec == NULL || sym_sec->output_section == NULL || (h != NULL - && ((h->maybe_pic_call - && !(input_section->flags & SEC_HAS_GOT_REF)) - || (h->elf.root.type == bfd_link_hash_defweak - && h->elf.dynindx != -1 - && h->elf.plt.offset != (bfd_vma) -1)))) + && h->elf.plt.offset != (bfd_vma) -1 + && (h->elf.dynindx != -1 || h->pic_call) + && !h->plabel)) { stub_entry = hppa_get_stub_entry (input_section, sym_sec, h, rel, htab); @@ -3428,7 +3497,7 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h) == (((int) OP_ADDIL << 26) | (27 << 21))) { insn &= ~ (0x1f << 21); -#if 1 /* debug them. */ +#if 0 /* debug them. */ (*_bfd_error_handler) (_("%s(%s+0x%lx): fixing %s"), bfd_archive_filename (input_bfd), @@ -3475,21 +3544,27 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h) r_field = e_fsel; break; - case R_PARISC_DIR21L: + case R_PARISC_DLTIND21L: case R_PARISC_PCREL21L: - case R_PARISC_DPREL21L: case R_PARISC_PLABEL21L: - case R_PARISC_DLTIND21L: + r_field = e_lsel; + break; + + case R_PARISC_DIR21L: + case R_PARISC_DPREL21L: r_field = e_lrsel; break; - case R_PARISC_DIR17R: case R_PARISC_PCREL17R: - case R_PARISC_DIR14R: case R_PARISC_PCREL14R: - case R_PARISC_DPREL14R: case R_PARISC_PLABEL14R: case R_PARISC_DLTIND14R: + r_field = e_rsel; + break; + + case R_PARISC_DIR17R: + case R_PARISC_DIR14R: + case R_PARISC_DPREL14R: r_field = e_rrsel; break; @@ -4093,32 +4168,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, return true; } -/* Comparison function for qsort to sort unwind section during a - final link. */ - -static int -hppa_unwind_entry_compare (a, b) - const PTR a; - const PTR b; -{ - const bfd_byte *ap, *bp; - unsigned long av, bv; - - ap = (const bfd_byte *) a; - av = (unsigned long) ap[0] << 24; - av |= (unsigned long) ap[1] << 16; - av |= (unsigned long) ap[2] << 8; - av |= (unsigned long) ap[3]; - - bp = (const bfd_byte *) b; - bv = (unsigned long) bp[0] << 24; - bv |= (unsigned long) bp[1] << 16; - bv |= (unsigned long) bp[2] << 8; - bv |= (unsigned long) bp[3]; - - return av < bv ? -1 : av > bv ? 1 : 0; -} - /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ @@ -4462,6 +4511,7 @@ elf32_hppa_elf_get_symbol_type (elf_sym, type) /* Stuff for the BFD linker. */ #define bfd_elf32_bfd_final_link elf32_hppa_final_link #define bfd_elf32_bfd_link_hash_table_create elf32_hppa_link_hash_table_create +#define bfd_elf32_bfd_link_hash_table_free elf32_hppa_link_hash_table_free #define elf_backend_add_symbol_hook elf32_hppa_add_symbol_hook #define elf_backend_adjust_dynamic_symbol elf32_hppa_adjust_dynamic_symbol #define elf_backend_copy_indirect_symbol elf32_hppa_copy_indirect_symbol |