13d8817e4Smiod /* BFD back-end for HP PA-RISC ELF files.
23d8817e4Smiod Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
33d8817e4Smiod 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
43d8817e4Smiod
53d8817e4Smiod Original code by
63d8817e4Smiod Center for Software Science
73d8817e4Smiod Department of Computer Science
83d8817e4Smiod University of Utah
93d8817e4Smiod Largely rewritten by Alan Modra <alan@linuxcare.com.au>
103d8817e4Smiod
113d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
123d8817e4Smiod
133d8817e4Smiod This program is free software; you can redistribute it and/or modify
143d8817e4Smiod it under the terms of the GNU General Public License as published by
153d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
163d8817e4Smiod (at your option) any later version.
173d8817e4Smiod
183d8817e4Smiod This program is distributed in the hope that it will be useful,
193d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
203d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
213d8817e4Smiod GNU General Public License for more details.
223d8817e4Smiod
233d8817e4Smiod You should have received a copy of the GNU General Public License
243d8817e4Smiod along with this program; if not, write to the Free Software
253d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
263d8817e4Smiod
273d8817e4Smiod #include "bfd.h"
283d8817e4Smiod #include "sysdep.h"
293d8817e4Smiod #include "libbfd.h"
303d8817e4Smiod #include "elf-bfd.h"
313d8817e4Smiod #include "elf/hppa.h"
323d8817e4Smiod #include "libhppa.h"
333d8817e4Smiod #include "elf32-hppa.h"
343d8817e4Smiod #define ARCH_SIZE 32
353d8817e4Smiod #include "elf32-hppa.h"
363d8817e4Smiod #include "elf-hppa.h"
373d8817e4Smiod
383d8817e4Smiod /* In order to gain some understanding of code in this file without
393d8817e4Smiod knowing all the intricate details of the linker, note the
403d8817e4Smiod following:
413d8817e4Smiod
423d8817e4Smiod Functions named elf32_hppa_* are called by external routines, other
433d8817e4Smiod functions are only called locally. elf32_hppa_* functions appear
443d8817e4Smiod in this file more or less in the order in which they are called
453d8817e4Smiod from external routines. eg. elf32_hppa_check_relocs is called
463d8817e4Smiod early in the link process, elf32_hppa_finish_dynamic_sections is
473d8817e4Smiod one of the last functions. */
483d8817e4Smiod
493d8817e4Smiod /* We use two hash tables to hold information for linking PA ELF objects.
503d8817e4Smiod
513d8817e4Smiod The first is the elf32_hppa_link_hash_table which is derived
523d8817e4Smiod from the standard ELF linker hash table. We use this as a place to
533d8817e4Smiod attach other hash tables and static information.
543d8817e4Smiod
553d8817e4Smiod The second is the stub hash table which is derived from the
563d8817e4Smiod base BFD hash table. The stub hash table holds the information
573d8817e4Smiod necessary to build the linker stubs during a link.
583d8817e4Smiod
593d8817e4Smiod There are a number of different stubs generated by the linker.
603d8817e4Smiod
613d8817e4Smiod Long branch stub:
623d8817e4Smiod : ldil LR'X,%r1
633d8817e4Smiod : be,n RR'X(%sr4,%r1)
643d8817e4Smiod
653d8817e4Smiod PIC long branch stub:
663d8817e4Smiod : b,l .+8,%r1
673d8817e4Smiod : addil LR'X - ($PIC_pcrel$0 - 4),%r1
683d8817e4Smiod : be,n RR'X - ($PIC_pcrel$0 - 8)(%sr4,%r1)
693d8817e4Smiod
703d8817e4Smiod Import stub to call shared library routine from normal object file
713d8817e4Smiod (single sub-space version)
723d8817e4Smiod : addil LR'lt_ptr+ltoff,%dp ; get procedure entry point
733d8817e4Smiod : ldw RR'lt_ptr+ltoff(%r1),%r21
743d8817e4Smiod : bv %r0(%r21)
753d8817e4Smiod : ldw RR'lt_ptr+ltoff+4(%r1),%r19 ; get new dlt value.
763d8817e4Smiod
773d8817e4Smiod Import stub to call shared library routine from shared library
783d8817e4Smiod (single sub-space version)
793d8817e4Smiod : addil LR'ltoff,%r19 ; get procedure entry point
803d8817e4Smiod : ldw RR'ltoff(%r1),%r21
813d8817e4Smiod : bv %r0(%r21)
823d8817e4Smiod : ldw RR'ltoff+4(%r1),%r19 ; get new dlt value.
833d8817e4Smiod
843d8817e4Smiod Import stub to call shared library routine from normal object file
853d8817e4Smiod (multiple sub-space support)
863d8817e4Smiod : addil LR'lt_ptr+ltoff,%dp ; get procedure entry point
873d8817e4Smiod : ldw RR'lt_ptr+ltoff(%r1),%r21
883d8817e4Smiod : ldw RR'lt_ptr+ltoff+4(%r1),%r19 ; get new dlt value.
893d8817e4Smiod : ldsid (%r21),%r1
903d8817e4Smiod : mtsp %r1,%sr0
913d8817e4Smiod : be 0(%sr0,%r21) ; branch to target
923d8817e4Smiod : stw %rp,-24(%sp) ; save rp
933d8817e4Smiod
943d8817e4Smiod Import stub to call shared library routine from shared library
953d8817e4Smiod (multiple sub-space support)
963d8817e4Smiod : addil LR'ltoff,%r19 ; get procedure entry point
973d8817e4Smiod : ldw RR'ltoff(%r1),%r21
983d8817e4Smiod : ldw RR'ltoff+4(%r1),%r19 ; get new dlt value.
993d8817e4Smiod : ldsid (%r21),%r1
1003d8817e4Smiod : mtsp %r1,%sr0
1013d8817e4Smiod : be 0(%sr0,%r21) ; branch to target
1023d8817e4Smiod : stw %rp,-24(%sp) ; save rp
1033d8817e4Smiod
1043d8817e4Smiod Export stub to return from shared lib routine (multiple sub-space support)
1053d8817e4Smiod One of these is created for each exported procedure in a shared
1063d8817e4Smiod library (and stored in the shared lib). Shared lib routines are
1073d8817e4Smiod called via the first instruction in the export stub so that we can
1083d8817e4Smiod do an inter-space return. Not required for single sub-space.
1093d8817e4Smiod : bl,n X,%rp ; trap the return
1103d8817e4Smiod : nop
1113d8817e4Smiod : ldw -24(%sp),%rp ; restore the original rp
1123d8817e4Smiod : ldsid (%rp),%r1
1133d8817e4Smiod : mtsp %r1,%sr0
1143d8817e4Smiod : be,n 0(%sr0,%rp) ; inter-space return. */
1153d8817e4Smiod
1163d8817e4Smiod
1173d8817e4Smiod /* Variable names follow a coding style.
1183d8817e4Smiod Please follow this (Apps Hungarian) style:
1193d8817e4Smiod
1203d8817e4Smiod Structure/Variable Prefix
1213d8817e4Smiod elf_link_hash_table "etab"
1223d8817e4Smiod elf_link_hash_entry "eh"
1233d8817e4Smiod
1243d8817e4Smiod elf32_hppa_link_hash_table "htab"
1253d8817e4Smiod elf32_hppa_link_hash_entry "hh"
1263d8817e4Smiod
1273d8817e4Smiod bfd_hash_table "btab"
1283d8817e4Smiod bfd_hash_entry "bh"
1293d8817e4Smiod
1303d8817e4Smiod bfd_hash_table containing stubs "bstab"
1313d8817e4Smiod elf32_hppa_stub_hash_entry "hsh"
1323d8817e4Smiod
1333d8817e4Smiod elf32_hppa_dyn_reloc_entry "hdh"
1343d8817e4Smiod
1353d8817e4Smiod Always remember to use GNU Coding Style. */
1363d8817e4Smiod
1373d8817e4Smiod #define PLT_ENTRY_SIZE 8
1383d8817e4Smiod #define GOT_ENTRY_SIZE 4
1393d8817e4Smiod #define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
1403d8817e4Smiod
1413d8817e4Smiod static const bfd_byte plt_stub[] =
1423d8817e4Smiod {
1433d8817e4Smiod 0x0e, 0x80, 0x10, 0x96, /* 1: ldw 0(%r20),%r22 */
1443d8817e4Smiod 0xea, 0xc0, 0xc0, 0x00, /* bv %r0(%r22) */
1453d8817e4Smiod 0x0e, 0x88, 0x10, 0x95, /* ldw 4(%r20),%r21 */
1463d8817e4Smiod #define PLT_STUB_ENTRY (3*4)
1473d8817e4Smiod 0xea, 0x9f, 0x1f, 0xdd, /* b,l 1b,%r20 */
1483d8817e4Smiod 0xd6, 0x80, 0x1c, 0x1e, /* depi 0,31,2,%r20 */
1493d8817e4Smiod 0x00, 0xc0, 0xff, 0xee, /* 9: .word fixup_func */
1503d8817e4Smiod 0xde, 0xad, 0xbe, 0xef /* .word fixup_ltp */
1513d8817e4Smiod };
1523d8817e4Smiod
1533d8817e4Smiod /* Section name for stubs is the associated section name plus this
1543d8817e4Smiod string. */
1553d8817e4Smiod #define STUB_SUFFIX ".stub"
1563d8817e4Smiod
1573d8817e4Smiod /* We don't need to copy certain PC- or GP-relative dynamic relocs
1583d8817e4Smiod into a shared object's dynamic section. All the relocs of the
1593d8817e4Smiod limited class we are interested in, are absolute. */
1603d8817e4Smiod #ifndef RELATIVE_DYNRELOCS
1613d8817e4Smiod #define RELATIVE_DYNRELOCS 0
1623d8817e4Smiod #define IS_ABSOLUTE_RELOC(r_type) 1
1633d8817e4Smiod #endif
1643d8817e4Smiod
1653d8817e4Smiod /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
1663d8817e4Smiod copying dynamic variables from a shared lib into an app's dynbss
1673d8817e4Smiod section, and instead use a dynamic relocation to point into the
1683d8817e4Smiod shared lib. */
1693d8817e4Smiod #define ELIMINATE_COPY_RELOCS 1
1703d8817e4Smiod
1713d8817e4Smiod enum elf32_hppa_stub_type {
1723d8817e4Smiod hppa_stub_long_branch,
1733d8817e4Smiod hppa_stub_long_branch_shared,
1743d8817e4Smiod hppa_stub_import,
1753d8817e4Smiod hppa_stub_import_shared,
1763d8817e4Smiod hppa_stub_export,
1773d8817e4Smiod hppa_stub_none
1783d8817e4Smiod };
1793d8817e4Smiod
1803d8817e4Smiod struct elf32_hppa_stub_hash_entry {
1813d8817e4Smiod
1823d8817e4Smiod /* Base hash table entry structure. */
1833d8817e4Smiod struct bfd_hash_entry bh_root;
1843d8817e4Smiod
1853d8817e4Smiod /* The stub section. */
1863d8817e4Smiod asection *stub_sec;
1873d8817e4Smiod
1883d8817e4Smiod /* Offset within stub_sec of the beginning of this stub. */
1893d8817e4Smiod bfd_vma stub_offset;
1903d8817e4Smiod
1913d8817e4Smiod /* Given the symbol's value and its section we can determine its final
1923d8817e4Smiod value when building the stubs (so the stub knows where to jump. */
1933d8817e4Smiod bfd_vma target_value;
1943d8817e4Smiod asection *target_section;
1953d8817e4Smiod
1963d8817e4Smiod enum elf32_hppa_stub_type stub_type;
1973d8817e4Smiod
1983d8817e4Smiod /* The symbol table entry, if any, that this was derived from. */
1993d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
2003d8817e4Smiod
2013d8817e4Smiod /* Where this stub is being called from, or, in the case of combined
2023d8817e4Smiod stub sections, the first input section in the group. */
2033d8817e4Smiod asection *id_sec;
2043d8817e4Smiod };
2053d8817e4Smiod
2063d8817e4Smiod struct elf32_hppa_link_hash_entry {
2073d8817e4Smiod
2083d8817e4Smiod struct elf_link_hash_entry eh;
2093d8817e4Smiod
2103d8817e4Smiod /* A pointer to the most recently used stub hash entry against this
2113d8817e4Smiod symbol. */
2123d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh_cache;
2133d8817e4Smiod
2143d8817e4Smiod /* Used to count relocations for delayed sizing of relocation
2153d8817e4Smiod sections. */
2163d8817e4Smiod struct elf32_hppa_dyn_reloc_entry {
2173d8817e4Smiod
2183d8817e4Smiod /* Next relocation in the chain. */
2193d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_next;
2203d8817e4Smiod
2213d8817e4Smiod /* The input section of the reloc. */
2223d8817e4Smiod asection *sec;
2233d8817e4Smiod
2243d8817e4Smiod /* Number of relocs copied in this section. */
2253d8817e4Smiod bfd_size_type count;
2263d8817e4Smiod
2273d8817e4Smiod #if RELATIVE_DYNRELOCS
2283d8817e4Smiod /* Number of relative relocs copied for the input section. */
2293d8817e4Smiod bfd_size_type relative_count;
2303d8817e4Smiod #endif
2313d8817e4Smiod } *dyn_relocs;
2323d8817e4Smiod
2333d8817e4Smiod /* Set if this symbol is used by a plabel reloc. */
2343d8817e4Smiod unsigned int plabel:1;
2353d8817e4Smiod };
2363d8817e4Smiod
2373d8817e4Smiod struct elf32_hppa_link_hash_table {
2383d8817e4Smiod
2393d8817e4Smiod /* The main hash table. */
2403d8817e4Smiod struct elf_link_hash_table etab;
2413d8817e4Smiod
2423d8817e4Smiod /* The stub hash table. */
2433d8817e4Smiod struct bfd_hash_table bstab;
2443d8817e4Smiod
2453d8817e4Smiod /* Linker stub bfd. */
2463d8817e4Smiod bfd *stub_bfd;
2473d8817e4Smiod
2483d8817e4Smiod /* Linker call-backs. */
2493d8817e4Smiod asection * (*add_stub_section) (const char *, asection *);
2503d8817e4Smiod void (*layout_sections_again) (void);
2513d8817e4Smiod
2523d8817e4Smiod /* Array to keep track of which stub sections have been created, and
2533d8817e4Smiod information on stub grouping. */
2543d8817e4Smiod struct map_stub {
2553d8817e4Smiod /* This is the section to which stubs in the group will be
2563d8817e4Smiod attached. */
2573d8817e4Smiod asection *link_sec;
2583d8817e4Smiod /* The stub section. */
2593d8817e4Smiod asection *stub_sec;
2603d8817e4Smiod } *stub_group;
2613d8817e4Smiod
2623d8817e4Smiod /* Assorted information used by elf32_hppa_size_stubs. */
2633d8817e4Smiod unsigned int bfd_count;
2643d8817e4Smiod int top_index;
2653d8817e4Smiod asection **input_list;
2663d8817e4Smiod Elf_Internal_Sym **all_local_syms;
2673d8817e4Smiod
2683d8817e4Smiod /* Short-cuts to get to dynamic linker sections. */
2693d8817e4Smiod asection *sgot;
2703d8817e4Smiod asection *srelgot;
2713d8817e4Smiod asection *splt;
2723d8817e4Smiod asection *srelplt;
2733d8817e4Smiod asection *sdynbss;
2743d8817e4Smiod asection *srelbss;
2753d8817e4Smiod
2763d8817e4Smiod /* Used during a final link to store the base of the text and data
2773d8817e4Smiod segments so that we can perform SEGREL relocations. */
2783d8817e4Smiod bfd_vma text_segment_base;
2793d8817e4Smiod bfd_vma data_segment_base;
2803d8817e4Smiod
2813d8817e4Smiod /* Whether we support multiple sub-spaces for shared libs. */
2823d8817e4Smiod unsigned int multi_subspace:1;
2833d8817e4Smiod
2843d8817e4Smiod /* Flags set when various size branches are detected. Used to
2853d8817e4Smiod select suitable defaults for the stub group size. */
2863d8817e4Smiod unsigned int has_12bit_branch:1;
2873d8817e4Smiod unsigned int has_17bit_branch:1;
2883d8817e4Smiod unsigned int has_22bit_branch:1;
2893d8817e4Smiod
2903d8817e4Smiod /* Set if we need a .plt stub to support lazy dynamic linking. */
2913d8817e4Smiod unsigned int need_plt_stub:1;
2923d8817e4Smiod
2933d8817e4Smiod /* Small local sym to section mapping cache. */
2943d8817e4Smiod struct sym_sec_cache sym_sec;
2953d8817e4Smiod };
2963d8817e4Smiod
2973d8817e4Smiod /* Various hash macros and functions. */
2983d8817e4Smiod #define hppa_link_hash_table(p) \
2993d8817e4Smiod ((struct elf32_hppa_link_hash_table *) ((p)->hash))
3003d8817e4Smiod
3013d8817e4Smiod #define hppa_elf_hash_entry(ent) \
3023d8817e4Smiod ((struct elf32_hppa_link_hash_entry *)(ent))
3033d8817e4Smiod
3043d8817e4Smiod #define hppa_stub_hash_entry(ent) \
3053d8817e4Smiod ((struct elf32_hppa_stub_hash_entry *)(ent))
3063d8817e4Smiod
3073d8817e4Smiod #define hppa_stub_hash_lookup(table, string, create, copy) \
3083d8817e4Smiod ((struct elf32_hppa_stub_hash_entry *) \
3093d8817e4Smiod bfd_hash_lookup ((table), (string), (create), (copy)))
3103d8817e4Smiod
3113d8817e4Smiod /* Assorted hash table functions. */
3123d8817e4Smiod
3133d8817e4Smiod /* Initialize an entry in the stub hash table. */
3143d8817e4Smiod
3153d8817e4Smiod static struct bfd_hash_entry *
stub_hash_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)3163d8817e4Smiod stub_hash_newfunc (struct bfd_hash_entry *entry,
3173d8817e4Smiod struct bfd_hash_table *table,
3183d8817e4Smiod const char *string)
3193d8817e4Smiod {
3203d8817e4Smiod /* Allocate the structure if it has not already been allocated by a
3213d8817e4Smiod subclass. */
3223d8817e4Smiod if (entry == NULL)
3233d8817e4Smiod {
3243d8817e4Smiod entry = bfd_hash_allocate (table,
3253d8817e4Smiod sizeof (struct elf32_hppa_stub_hash_entry));
3263d8817e4Smiod if (entry == NULL)
3273d8817e4Smiod return entry;
3283d8817e4Smiod }
3293d8817e4Smiod
3303d8817e4Smiod /* Call the allocation method of the superclass. */
3313d8817e4Smiod entry = bfd_hash_newfunc (entry, table, string);
3323d8817e4Smiod if (entry != NULL)
3333d8817e4Smiod {
3343d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh;
3353d8817e4Smiod
3363d8817e4Smiod /* Initialize the local fields. */
3373d8817e4Smiod hsh = hppa_stub_hash_entry (entry);
3383d8817e4Smiod hsh->stub_sec = NULL;
3393d8817e4Smiod hsh->stub_offset = 0;
3403d8817e4Smiod hsh->target_value = 0;
3413d8817e4Smiod hsh->target_section = NULL;
3423d8817e4Smiod hsh->stub_type = hppa_stub_long_branch;
3433d8817e4Smiod hsh->hh = NULL;
3443d8817e4Smiod hsh->id_sec = NULL;
3453d8817e4Smiod }
3463d8817e4Smiod
3473d8817e4Smiod return entry;
3483d8817e4Smiod }
3493d8817e4Smiod
3503d8817e4Smiod /* Initialize an entry in the link hash table. */
3513d8817e4Smiod
3523d8817e4Smiod static struct bfd_hash_entry *
hppa_link_hash_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)3533d8817e4Smiod hppa_link_hash_newfunc (struct bfd_hash_entry *entry,
3543d8817e4Smiod struct bfd_hash_table *table,
3553d8817e4Smiod const char *string)
3563d8817e4Smiod {
3573d8817e4Smiod /* Allocate the structure if it has not already been allocated by a
3583d8817e4Smiod subclass. */
3593d8817e4Smiod if (entry == NULL)
3603d8817e4Smiod {
3613d8817e4Smiod entry = bfd_hash_allocate (table,
3623d8817e4Smiod sizeof (struct elf32_hppa_link_hash_entry));
3633d8817e4Smiod if (entry == NULL)
3643d8817e4Smiod return entry;
3653d8817e4Smiod }
3663d8817e4Smiod
3673d8817e4Smiod /* Call the allocation method of the superclass. */
3683d8817e4Smiod entry = _bfd_elf_link_hash_newfunc (entry, table, string);
3693d8817e4Smiod if (entry != NULL)
3703d8817e4Smiod {
3713d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
3723d8817e4Smiod
3733d8817e4Smiod /* Initialize the local fields. */
3743d8817e4Smiod hh = hppa_elf_hash_entry (entry);
3753d8817e4Smiod hh->hsh_cache = NULL;
3763d8817e4Smiod hh->dyn_relocs = NULL;
3773d8817e4Smiod hh->plabel = 0;
3783d8817e4Smiod }
3793d8817e4Smiod
3803d8817e4Smiod return entry;
3813d8817e4Smiod }
3823d8817e4Smiod
3833d8817e4Smiod /* Create the derived linker hash table. The PA ELF port uses the derived
3843d8817e4Smiod hash table to keep information specific to the PA ELF linker (without
3853d8817e4Smiod using static variables). */
3863d8817e4Smiod
3873d8817e4Smiod static struct bfd_link_hash_table *
elf32_hppa_link_hash_table_create(bfd * abfd)3883d8817e4Smiod elf32_hppa_link_hash_table_create (bfd *abfd)
3893d8817e4Smiod {
3903d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
3913d8817e4Smiod bfd_size_type amt = sizeof (*htab);
3923d8817e4Smiod
3933d8817e4Smiod htab = (struct elf32_hppa_link_hash_table *) bfd_malloc (amt);
3943d8817e4Smiod if (htab == NULL)
3953d8817e4Smiod return NULL;
3963d8817e4Smiod
3973d8817e4Smiod if (!_bfd_elf_link_hash_table_init (&htab->etab, abfd, hppa_link_hash_newfunc,
3983d8817e4Smiod sizeof (struct elf32_hppa_link_hash_entry)))
3993d8817e4Smiod {
4003d8817e4Smiod free (htab);
4013d8817e4Smiod return NULL;
4023d8817e4Smiod }
4033d8817e4Smiod
4043d8817e4Smiod /* Init the stub hash table too. */
4053d8817e4Smiod if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
4063d8817e4Smiod sizeof (struct elf32_hppa_stub_hash_entry)))
4073d8817e4Smiod return NULL;
4083d8817e4Smiod
4093d8817e4Smiod htab->stub_bfd = NULL;
4103d8817e4Smiod htab->add_stub_section = NULL;
4113d8817e4Smiod htab->layout_sections_again = NULL;
4123d8817e4Smiod htab->stub_group = NULL;
4133d8817e4Smiod htab->sgot = NULL;
4143d8817e4Smiod htab->srelgot = NULL;
4153d8817e4Smiod htab->splt = NULL;
4163d8817e4Smiod htab->srelplt = NULL;
4173d8817e4Smiod htab->sdynbss = NULL;
4183d8817e4Smiod htab->srelbss = NULL;
4193d8817e4Smiod htab->text_segment_base = (bfd_vma) -1;
4203d8817e4Smiod htab->data_segment_base = (bfd_vma) -1;
4213d8817e4Smiod htab->multi_subspace = 0;
4223d8817e4Smiod htab->has_12bit_branch = 0;
4233d8817e4Smiod htab->has_17bit_branch = 0;
4243d8817e4Smiod htab->has_22bit_branch = 0;
4253d8817e4Smiod htab->need_plt_stub = 0;
4263d8817e4Smiod htab->sym_sec.abfd = NULL;
4273d8817e4Smiod
4283d8817e4Smiod return &htab->etab.root;
4293d8817e4Smiod }
4303d8817e4Smiod
4313d8817e4Smiod /* Free the derived linker hash table. */
4323d8817e4Smiod
4333d8817e4Smiod static void
elf32_hppa_link_hash_table_free(struct bfd_link_hash_table * btab)4343d8817e4Smiod elf32_hppa_link_hash_table_free (struct bfd_link_hash_table *btab)
4353d8817e4Smiod {
4363d8817e4Smiod struct elf32_hppa_link_hash_table *htab
4373d8817e4Smiod = (struct elf32_hppa_link_hash_table *) btab;
4383d8817e4Smiod
4393d8817e4Smiod bfd_hash_table_free (&htab->bstab);
4403d8817e4Smiod _bfd_generic_link_hash_table_free (btab);
4413d8817e4Smiod }
4423d8817e4Smiod
4433d8817e4Smiod /* Build a name for an entry in the stub hash table. */
4443d8817e4Smiod
4453d8817e4Smiod static char *
hppa_stub_name(const asection * input_section,const asection * sym_sec,const struct elf32_hppa_link_hash_entry * hh,const Elf_Internal_Rela * rela)4463d8817e4Smiod hppa_stub_name (const asection *input_section,
4473d8817e4Smiod const asection *sym_sec,
4483d8817e4Smiod const struct elf32_hppa_link_hash_entry *hh,
4493d8817e4Smiod const Elf_Internal_Rela *rela)
4503d8817e4Smiod {
4513d8817e4Smiod char *stub_name;
4523d8817e4Smiod bfd_size_type len;
4533d8817e4Smiod
4543d8817e4Smiod if (hh)
4553d8817e4Smiod {
4563d8817e4Smiod len = 8 + 1 + strlen (hh->eh.root.root.string) + 1 + 8 + 1;
4573d8817e4Smiod stub_name = bfd_malloc (len);
4583d8817e4Smiod if (stub_name != NULL)
4593d8817e4Smiod {
4603d8817e4Smiod sprintf (stub_name, "%08x_%s+%x",
4613d8817e4Smiod input_section->id & 0xffffffff,
4623d8817e4Smiod hh->eh.root.root.string,
4633d8817e4Smiod (int) rela->r_addend & 0xffffffff);
4643d8817e4Smiod }
4653d8817e4Smiod }
4663d8817e4Smiod else
4673d8817e4Smiod {
4683d8817e4Smiod len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
4693d8817e4Smiod stub_name = bfd_malloc (len);
4703d8817e4Smiod if (stub_name != NULL)
4713d8817e4Smiod {
4723d8817e4Smiod sprintf (stub_name, "%08x_%x:%x+%x",
4733d8817e4Smiod input_section->id & 0xffffffff,
4743d8817e4Smiod sym_sec->id & 0xffffffff,
4753d8817e4Smiod (int) ELF32_R_SYM (rela->r_info) & 0xffffffff,
4763d8817e4Smiod (int) rela->r_addend & 0xffffffff);
4773d8817e4Smiod }
4783d8817e4Smiod }
4793d8817e4Smiod return stub_name;
4803d8817e4Smiod }
4813d8817e4Smiod
4823d8817e4Smiod /* Look up an entry in the stub hash. Stub entries are cached because
4833d8817e4Smiod creating the stub name takes a bit of time. */
4843d8817e4Smiod
4853d8817e4Smiod static struct elf32_hppa_stub_hash_entry *
hppa_get_stub_entry(const asection * input_section,const asection * sym_sec,struct elf32_hppa_link_hash_entry * hh,const Elf_Internal_Rela * rela,struct elf32_hppa_link_hash_table * htab)4863d8817e4Smiod hppa_get_stub_entry (const asection *input_section,
4873d8817e4Smiod const asection *sym_sec,
4883d8817e4Smiod struct elf32_hppa_link_hash_entry *hh,
4893d8817e4Smiod const Elf_Internal_Rela *rela,
4903d8817e4Smiod struct elf32_hppa_link_hash_table *htab)
4913d8817e4Smiod {
4923d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh_entry;
4933d8817e4Smiod const asection *id_sec;
4943d8817e4Smiod
4953d8817e4Smiod /* If this input section is part of a group of sections sharing one
4963d8817e4Smiod stub section, then use the id of the first section in the group.
4973d8817e4Smiod Stub names need to include a section id, as there may well be
4983d8817e4Smiod more than one stub used to reach say, printf, and we need to
4993d8817e4Smiod distinguish between them. */
5003d8817e4Smiod id_sec = htab->stub_group[input_section->id].link_sec;
5013d8817e4Smiod
5023d8817e4Smiod if (hh != NULL && hh->hsh_cache != NULL
5033d8817e4Smiod && hh->hsh_cache->hh == hh
5043d8817e4Smiod && hh->hsh_cache->id_sec == id_sec)
5053d8817e4Smiod {
5063d8817e4Smiod hsh_entry = hh->hsh_cache;
5073d8817e4Smiod }
5083d8817e4Smiod else
5093d8817e4Smiod {
5103d8817e4Smiod char *stub_name;
5113d8817e4Smiod
5123d8817e4Smiod stub_name = hppa_stub_name (id_sec, sym_sec, hh, rela);
5133d8817e4Smiod if (stub_name == NULL)
5143d8817e4Smiod return NULL;
5153d8817e4Smiod
5163d8817e4Smiod hsh_entry = hppa_stub_hash_lookup (&htab->bstab,
5173d8817e4Smiod stub_name, FALSE, FALSE);
5183d8817e4Smiod if (hh != NULL)
5193d8817e4Smiod hh->hsh_cache = hsh_entry;
5203d8817e4Smiod
5213d8817e4Smiod free (stub_name);
5223d8817e4Smiod }
5233d8817e4Smiod
5243d8817e4Smiod return hsh_entry;
5253d8817e4Smiod }
5263d8817e4Smiod
5273d8817e4Smiod /* Add a new stub entry to the stub hash. Not all fields of the new
5283d8817e4Smiod stub entry are initialised. */
5293d8817e4Smiod
5303d8817e4Smiod static struct elf32_hppa_stub_hash_entry *
hppa_add_stub(const char * stub_name,asection * section,struct elf32_hppa_link_hash_table * htab)5313d8817e4Smiod hppa_add_stub (const char *stub_name,
5323d8817e4Smiod asection *section,
5333d8817e4Smiod struct elf32_hppa_link_hash_table *htab)
5343d8817e4Smiod {
5353d8817e4Smiod asection *link_sec;
5363d8817e4Smiod asection *stub_sec;
5373d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh;
5383d8817e4Smiod
5393d8817e4Smiod link_sec = htab->stub_group[section->id].link_sec;
5403d8817e4Smiod stub_sec = htab->stub_group[section->id].stub_sec;
5413d8817e4Smiod if (stub_sec == NULL)
5423d8817e4Smiod {
5433d8817e4Smiod stub_sec = htab->stub_group[link_sec->id].stub_sec;
5443d8817e4Smiod if (stub_sec == NULL)
5453d8817e4Smiod {
5463d8817e4Smiod size_t namelen;
5473d8817e4Smiod bfd_size_type len;
5483d8817e4Smiod char *s_name;
5493d8817e4Smiod
5503d8817e4Smiod namelen = strlen (link_sec->name);
5513d8817e4Smiod len = namelen + sizeof (STUB_SUFFIX);
5523d8817e4Smiod s_name = bfd_alloc (htab->stub_bfd, len);
5533d8817e4Smiod if (s_name == NULL)
5543d8817e4Smiod return NULL;
5553d8817e4Smiod
5563d8817e4Smiod memcpy (s_name, link_sec->name, namelen);
5573d8817e4Smiod memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
5583d8817e4Smiod stub_sec = (*htab->add_stub_section) (s_name, link_sec);
5593d8817e4Smiod if (stub_sec == NULL)
5603d8817e4Smiod return NULL;
5613d8817e4Smiod htab->stub_group[link_sec->id].stub_sec = stub_sec;
5623d8817e4Smiod }
5633d8817e4Smiod htab->stub_group[section->id].stub_sec = stub_sec;
5643d8817e4Smiod }
5653d8817e4Smiod
5663d8817e4Smiod /* Enter this entry into the linker stub hash table. */
5673d8817e4Smiod hsh = hppa_stub_hash_lookup (&htab->bstab, stub_name,
5683d8817e4Smiod TRUE, FALSE);
5693d8817e4Smiod if (hsh == NULL)
5703d8817e4Smiod {
5713d8817e4Smiod (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
5723d8817e4Smiod section->owner,
5733d8817e4Smiod stub_name);
5743d8817e4Smiod return NULL;
5753d8817e4Smiod }
5763d8817e4Smiod
5773d8817e4Smiod hsh->stub_sec = stub_sec;
5783d8817e4Smiod hsh->stub_offset = 0;
5793d8817e4Smiod hsh->id_sec = link_sec;
5803d8817e4Smiod return hsh;
5813d8817e4Smiod }
5823d8817e4Smiod
5833d8817e4Smiod /* Determine the type of stub needed, if any, for a call. */
5843d8817e4Smiod
5853d8817e4Smiod static enum elf32_hppa_stub_type
hppa_type_of_stub(asection * input_sec,const Elf_Internal_Rela * rela,struct elf32_hppa_link_hash_entry * hh,bfd_vma destination,struct bfd_link_info * info)5863d8817e4Smiod hppa_type_of_stub (asection *input_sec,
5873d8817e4Smiod const Elf_Internal_Rela *rela,
5883d8817e4Smiod struct elf32_hppa_link_hash_entry *hh,
5893d8817e4Smiod bfd_vma destination,
5903d8817e4Smiod struct bfd_link_info *info)
5913d8817e4Smiod {
5923d8817e4Smiod bfd_vma location;
5933d8817e4Smiod bfd_vma branch_offset;
5943d8817e4Smiod bfd_vma max_branch_offset;
5953d8817e4Smiod unsigned int r_type;
5963d8817e4Smiod
5973d8817e4Smiod if (hh != NULL
5983d8817e4Smiod && hh->eh.plt.offset != (bfd_vma) -1
5993d8817e4Smiod && hh->eh.dynindx != -1
6003d8817e4Smiod && !hh->plabel
6013d8817e4Smiod && (info->shared
6023d8817e4Smiod || !hh->eh.def_regular
6033d8817e4Smiod || hh->eh.root.type == bfd_link_hash_defweak))
6043d8817e4Smiod {
6053d8817e4Smiod /* We need an import stub. Decide between hppa_stub_import
6063d8817e4Smiod and hppa_stub_import_shared later. */
6073d8817e4Smiod return hppa_stub_import;
6083d8817e4Smiod }
6093d8817e4Smiod
6103d8817e4Smiod /* Determine where the call point is. */
6113d8817e4Smiod location = (input_sec->output_offset
6123d8817e4Smiod + input_sec->output_section->vma
6133d8817e4Smiod + rela->r_offset);
6143d8817e4Smiod
6153d8817e4Smiod branch_offset = destination - location - 8;
6163d8817e4Smiod r_type = ELF32_R_TYPE (rela->r_info);
6173d8817e4Smiod
6183d8817e4Smiod /* Determine if a long branch stub is needed. parisc branch offsets
6193d8817e4Smiod are relative to the second instruction past the branch, ie. +8
6203d8817e4Smiod bytes on from the branch instruction location. The offset is
6213d8817e4Smiod signed and counts in units of 4 bytes. */
6223d8817e4Smiod if (r_type == (unsigned int) R_PARISC_PCREL17F)
6233d8817e4Smiod {
6243d8817e4Smiod max_branch_offset = (1 << (17-1)) << 2;
6253d8817e4Smiod }
6263d8817e4Smiod else if (r_type == (unsigned int) R_PARISC_PCREL12F)
6273d8817e4Smiod {
6283d8817e4Smiod max_branch_offset = (1 << (12-1)) << 2;
6293d8817e4Smiod }
6303d8817e4Smiod else /* R_PARISC_PCREL22F. */
6313d8817e4Smiod {
6323d8817e4Smiod max_branch_offset = (1 << (22-1)) << 2;
6333d8817e4Smiod }
6343d8817e4Smiod
6353d8817e4Smiod if (branch_offset + max_branch_offset >= 2*max_branch_offset)
6363d8817e4Smiod return hppa_stub_long_branch;
6373d8817e4Smiod
6383d8817e4Smiod return hppa_stub_none;
6393d8817e4Smiod }
6403d8817e4Smiod
6413d8817e4Smiod /* Build one linker stub as defined by the stub hash table entry GEN_ENTRY.
6423d8817e4Smiod IN_ARG contains the link info pointer. */
6433d8817e4Smiod
6443d8817e4Smiod #define LDIL_R1 0x20200000 /* ldil LR'XXX,%r1 */
6453d8817e4Smiod #define BE_SR4_R1 0xe0202002 /* be,n RR'XXX(%sr4,%r1) */
6463d8817e4Smiod
6473d8817e4Smiod #define BL_R1 0xe8200000 /* b,l .+8,%r1 */
6483d8817e4Smiod #define ADDIL_R1 0x28200000 /* addil LR'XXX,%r1,%r1 */
6493d8817e4Smiod #define DEPI_R1 0xd4201c1e /* depi 0,31,2,%r1 */
6503d8817e4Smiod
6513d8817e4Smiod #define ADDIL_DP 0x2b600000 /* addil LR'XXX,%dp,%r1 */
6523d8817e4Smiod #define LDW_R1_R21 0x48350000 /* ldw RR'XXX(%sr0,%r1),%r21 */
6533d8817e4Smiod #define BV_R0_R21 0xeaa0c000 /* bv %r0(%r21) */
6543d8817e4Smiod #define LDW_R1_R19 0x48330000 /* ldw RR'XXX(%sr0,%r1),%r19 */
6553d8817e4Smiod
6563d8817e4Smiod #define ADDIL_R19 0x2a600000 /* addil LR'XXX,%r19,%r1 */
6573d8817e4Smiod #define LDW_R1_DP 0x483b0000 /* ldw RR'XXX(%sr0,%r1),%dp */
6583d8817e4Smiod
6593d8817e4Smiod #define LDSID_R21_R1 0x02a010a1 /* ldsid (%sr0,%r21),%r1 */
6603d8817e4Smiod #define MTSP_R1 0x00011820 /* mtsp %r1,%sr0 */
6613d8817e4Smiod #define BE_SR0_R21 0xe2a00000 /* be 0(%sr0,%r21) */
6623d8817e4Smiod #define STW_RP 0x6bc23fd1 /* stw %rp,-24(%sr0,%sp) */
6633d8817e4Smiod
6643d8817e4Smiod #define BL22_RP 0xe800a002 /* b,l,n XXX,%rp */
6653d8817e4Smiod #define BL_RP 0xe8400002 /* b,l,n XXX,%rp */
6663d8817e4Smiod #define NOP 0x08000240 /* nop */
6673d8817e4Smiod #define LDW_RP 0x4bc23fd1 /* ldw -24(%sr0,%sp),%rp */
6683d8817e4Smiod #define LDSID_RP_R1 0x004010a1 /* ldsid (%sr0,%rp),%r1 */
6693d8817e4Smiod #define BE_SR0_RP 0xe0400002 /* be,n 0(%sr0,%rp) */
6703d8817e4Smiod
6713d8817e4Smiod #ifndef R19_STUBS
6723d8817e4Smiod #define R19_STUBS 1
6733d8817e4Smiod #endif
6743d8817e4Smiod
6753d8817e4Smiod #if R19_STUBS
6763d8817e4Smiod #define LDW_R1_DLT LDW_R1_R19
6773d8817e4Smiod #else
6783d8817e4Smiod #define LDW_R1_DLT LDW_R1_DP
6793d8817e4Smiod #endif
6803d8817e4Smiod
6813d8817e4Smiod static bfd_boolean
hppa_build_one_stub(struct bfd_hash_entry * bh,void * in_arg)6823d8817e4Smiod hppa_build_one_stub (struct bfd_hash_entry *bh, void *in_arg)
6833d8817e4Smiod {
6843d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh;
6853d8817e4Smiod struct bfd_link_info *info;
6863d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
6873d8817e4Smiod asection *stub_sec;
6883d8817e4Smiod bfd *stub_bfd;
6893d8817e4Smiod bfd_byte *loc;
6903d8817e4Smiod bfd_vma sym_value;
6913d8817e4Smiod bfd_vma insn;
6923d8817e4Smiod bfd_vma off;
6933d8817e4Smiod int val;
6943d8817e4Smiod int size;
6953d8817e4Smiod
6963d8817e4Smiod /* Massage our args to the form they really have. */
6973d8817e4Smiod hsh = hppa_stub_hash_entry (bh);
6983d8817e4Smiod info = (struct bfd_link_info *)in_arg;
6993d8817e4Smiod
7003d8817e4Smiod htab = hppa_link_hash_table (info);
7013d8817e4Smiod stub_sec = hsh->stub_sec;
7023d8817e4Smiod
7033d8817e4Smiod /* Make a note of the offset within the stubs for this entry. */
7043d8817e4Smiod hsh->stub_offset = stub_sec->size;
7053d8817e4Smiod loc = stub_sec->contents + hsh->stub_offset;
7063d8817e4Smiod
7073d8817e4Smiod stub_bfd = stub_sec->owner;
7083d8817e4Smiod
7093d8817e4Smiod switch (hsh->stub_type)
7103d8817e4Smiod {
7113d8817e4Smiod case hppa_stub_long_branch:
7123d8817e4Smiod /* Create the long branch. A long branch is formed with "ldil"
7133d8817e4Smiod loading the upper bits of the target address into a register,
7143d8817e4Smiod then branching with "be" which adds in the lower bits.
7153d8817e4Smiod The "be" has its delay slot nullified. */
7163d8817e4Smiod sym_value = (hsh->target_value
7173d8817e4Smiod + hsh->target_section->output_offset
7183d8817e4Smiod + hsh->target_section->output_section->vma);
7193d8817e4Smiod
7203d8817e4Smiod val = hppa_field_adjust (sym_value, 0, e_lrsel);
7213d8817e4Smiod insn = hppa_rebuild_insn ((int) LDIL_R1, val, 21);
7223d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc);
7233d8817e4Smiod
7243d8817e4Smiod val = hppa_field_adjust (sym_value, 0, e_rrsel) >> 2;
7253d8817e4Smiod insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);
7263d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc + 4);
7273d8817e4Smiod
7283d8817e4Smiod size = 8;
7293d8817e4Smiod break;
7303d8817e4Smiod
7313d8817e4Smiod case hppa_stub_long_branch_shared:
7323d8817e4Smiod /* Branches are relative. This is where we are going to. */
7333d8817e4Smiod sym_value = (hsh->target_value
7343d8817e4Smiod + hsh->target_section->output_offset
7353d8817e4Smiod + hsh->target_section->output_section->vma);
7363d8817e4Smiod
7373d8817e4Smiod /* And this is where we are coming from, more or less. */
7383d8817e4Smiod sym_value -= (hsh->stub_offset
7393d8817e4Smiod + stub_sec->output_offset
7403d8817e4Smiod + stub_sec->output_section->vma);
7413d8817e4Smiod
7423d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) BL_R1, loc);
7433d8817e4Smiod val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_lrsel);
7443d8817e4Smiod insn = hppa_rebuild_insn ((int) ADDIL_R1, val, 21);
7453d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc + 4);
7463d8817e4Smiod
7473d8817e4Smiod val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_rrsel) >> 2;
7483d8817e4Smiod insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);
7493d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc + 8);
7503d8817e4Smiod size = 12;
7513d8817e4Smiod break;
7523d8817e4Smiod
7533d8817e4Smiod case hppa_stub_import:
7543d8817e4Smiod case hppa_stub_import_shared:
7553d8817e4Smiod off = hsh->hh->eh.plt.offset;
7563d8817e4Smiod if (off >= (bfd_vma) -2)
7573d8817e4Smiod abort ();
7583d8817e4Smiod
7593d8817e4Smiod off &= ~ (bfd_vma) 1;
7603d8817e4Smiod sym_value = (off
7613d8817e4Smiod + htab->splt->output_offset
7623d8817e4Smiod + htab->splt->output_section->vma
7633d8817e4Smiod - elf_gp (htab->splt->output_section->owner));
7643d8817e4Smiod
7653d8817e4Smiod insn = ADDIL_DP;
7663d8817e4Smiod #if R19_STUBS
7673d8817e4Smiod if (hsh->stub_type == hppa_stub_import_shared)
7683d8817e4Smiod insn = ADDIL_R19;
7693d8817e4Smiod #endif
7703d8817e4Smiod val = hppa_field_adjust (sym_value, 0, e_lrsel),
7713d8817e4Smiod insn = hppa_rebuild_insn ((int) insn, val, 21);
7723d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc);
7733d8817e4Smiod
7743d8817e4Smiod /* It is critical to use lrsel/rrsel here because we are using
7753d8817e4Smiod two different offsets (+0 and +4) from sym_value. If we use
7763d8817e4Smiod lsel/rsel then with unfortunate sym_values we will round
7773d8817e4Smiod sym_value+4 up to the next 2k block leading to a mis-match
7783d8817e4Smiod between the lsel and rsel value. */
7793d8817e4Smiod val = hppa_field_adjust (sym_value, 0, e_rrsel);
7803d8817e4Smiod insn = hppa_rebuild_insn ((int) LDW_R1_R21, val, 14);
7813d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc + 4);
7823d8817e4Smiod
7833d8817e4Smiod if (htab->multi_subspace)
7843d8817e4Smiod {
7853d8817e4Smiod val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);
7863d8817e4Smiod insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);
7873d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc + 8);
7883d8817e4Smiod
7893d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) LDSID_R21_R1, loc + 12);
7903d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) MTSP_R1, loc + 16);
7913d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) BE_SR0_R21, loc + 20);
7923d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) STW_RP, loc + 24);
7933d8817e4Smiod
7943d8817e4Smiod size = 28;
7953d8817e4Smiod }
7963d8817e4Smiod else
7973d8817e4Smiod {
7983d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) BV_R0_R21, loc + 8);
7993d8817e4Smiod val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);
8003d8817e4Smiod insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);
8013d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc + 12);
8023d8817e4Smiod
8033d8817e4Smiod size = 16;
8043d8817e4Smiod }
8053d8817e4Smiod
8063d8817e4Smiod break;
8073d8817e4Smiod
8083d8817e4Smiod case hppa_stub_export:
8093d8817e4Smiod /* Branches are relative. This is where we are going to. */
8103d8817e4Smiod sym_value = (hsh->target_value
8113d8817e4Smiod + hsh->target_section->output_offset
8123d8817e4Smiod + hsh->target_section->output_section->vma);
8133d8817e4Smiod
8143d8817e4Smiod /* And this is where we are coming from. */
8153d8817e4Smiod sym_value -= (hsh->stub_offset
8163d8817e4Smiod + stub_sec->output_offset
8173d8817e4Smiod + stub_sec->output_section->vma);
8183d8817e4Smiod
8193d8817e4Smiod if (sym_value - 8 + (1 << (17 + 1)) >= (1 << (17 + 2))
8203d8817e4Smiod && (!htab->has_22bit_branch
8213d8817e4Smiod || sym_value - 8 + (1 << (22 + 1)) >= (1 << (22 + 2))))
8223d8817e4Smiod {
8233d8817e4Smiod (*_bfd_error_handler)
8243d8817e4Smiod (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
8253d8817e4Smiod hsh->target_section->owner,
8263d8817e4Smiod stub_sec,
8273d8817e4Smiod (long) hsh->stub_offset,
8283d8817e4Smiod hsh->bh_root.string);
8293d8817e4Smiod bfd_set_error (bfd_error_bad_value);
8303d8817e4Smiod return FALSE;
8313d8817e4Smiod }
8323d8817e4Smiod
8333d8817e4Smiod val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_fsel) >> 2;
8343d8817e4Smiod if (!htab->has_22bit_branch)
8353d8817e4Smiod insn = hppa_rebuild_insn ((int) BL_RP, val, 17);
8363d8817e4Smiod else
8373d8817e4Smiod insn = hppa_rebuild_insn ((int) BL22_RP, val, 22);
8383d8817e4Smiod bfd_put_32 (stub_bfd, insn, loc);
8393d8817e4Smiod
8403d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) NOP, loc + 4);
8413d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) LDW_RP, loc + 8);
8423d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) LDSID_RP_R1, loc + 12);
8433d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) MTSP_R1, loc + 16);
8443d8817e4Smiod bfd_put_32 (stub_bfd, (bfd_vma) BE_SR0_RP, loc + 20);
8453d8817e4Smiod
8463d8817e4Smiod /* Point the function symbol at the stub. */
8473d8817e4Smiod hsh->hh->eh.root.u.def.section = stub_sec;
8483d8817e4Smiod hsh->hh->eh.root.u.def.value = stub_sec->size;
8493d8817e4Smiod
8503d8817e4Smiod size = 24;
8513d8817e4Smiod break;
8523d8817e4Smiod
8533d8817e4Smiod default:
8543d8817e4Smiod BFD_FAIL ();
8553d8817e4Smiod return FALSE;
8563d8817e4Smiod }
8573d8817e4Smiod
8583d8817e4Smiod stub_sec->size += size;
8593d8817e4Smiod return TRUE;
8603d8817e4Smiod }
8613d8817e4Smiod
8623d8817e4Smiod #undef LDIL_R1
8633d8817e4Smiod #undef BE_SR4_R1
8643d8817e4Smiod #undef BL_R1
8653d8817e4Smiod #undef ADDIL_R1
8663d8817e4Smiod #undef DEPI_R1
8673d8817e4Smiod #undef LDW_R1_R21
8683d8817e4Smiod #undef LDW_R1_DLT
8693d8817e4Smiod #undef LDW_R1_R19
8703d8817e4Smiod #undef ADDIL_R19
8713d8817e4Smiod #undef LDW_R1_DP
8723d8817e4Smiod #undef LDSID_R21_R1
8733d8817e4Smiod #undef MTSP_R1
8743d8817e4Smiod #undef BE_SR0_R21
8753d8817e4Smiod #undef STW_RP
8763d8817e4Smiod #undef BV_R0_R21
8773d8817e4Smiod #undef BL_RP
8783d8817e4Smiod #undef NOP
8793d8817e4Smiod #undef LDW_RP
8803d8817e4Smiod #undef LDSID_RP_R1
8813d8817e4Smiod #undef BE_SR0_RP
8823d8817e4Smiod
8833d8817e4Smiod /* As above, but don't actually build the stub. Just bump offset so
8843d8817e4Smiod we know stub section sizes. */
8853d8817e4Smiod
8863d8817e4Smiod static bfd_boolean
hppa_size_one_stub(struct bfd_hash_entry * bh,void * in_arg)8873d8817e4Smiod hppa_size_one_stub (struct bfd_hash_entry *bh, void *in_arg)
8883d8817e4Smiod {
8893d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh;
8903d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
8913d8817e4Smiod int size;
8923d8817e4Smiod
8933d8817e4Smiod /* Massage our args to the form they really have. */
8943d8817e4Smiod hsh = hppa_stub_hash_entry (bh);
8953d8817e4Smiod htab = in_arg;
8963d8817e4Smiod
8973d8817e4Smiod if (hsh->stub_type == hppa_stub_long_branch)
8983d8817e4Smiod size = 8;
8993d8817e4Smiod else if (hsh->stub_type == hppa_stub_long_branch_shared)
9003d8817e4Smiod size = 12;
9013d8817e4Smiod else if (hsh->stub_type == hppa_stub_export)
9023d8817e4Smiod size = 24;
9033d8817e4Smiod else /* hppa_stub_import or hppa_stub_import_shared. */
9043d8817e4Smiod {
9053d8817e4Smiod if (htab->multi_subspace)
9063d8817e4Smiod size = 28;
9073d8817e4Smiod else
9083d8817e4Smiod size = 16;
9093d8817e4Smiod }
9103d8817e4Smiod
9113d8817e4Smiod hsh->stub_sec->size += size;
9123d8817e4Smiod return TRUE;
9133d8817e4Smiod }
9143d8817e4Smiod
9153d8817e4Smiod /* Return nonzero if ABFD represents an HPPA ELF32 file.
9163d8817e4Smiod Additionally we set the default architecture and machine. */
9173d8817e4Smiod
9183d8817e4Smiod static bfd_boolean
elf32_hppa_object_p(bfd * abfd)9193d8817e4Smiod elf32_hppa_object_p (bfd *abfd)
9203d8817e4Smiod {
9213d8817e4Smiod Elf_Internal_Ehdr * i_ehdrp;
9223d8817e4Smiod unsigned int flags;
9233d8817e4Smiod
9243d8817e4Smiod i_ehdrp = elf_elfheader (abfd);
9253d8817e4Smiod if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)
9263d8817e4Smiod {
9273d8817e4Smiod /* GCC on hppa-linux produces binaries with OSABI=Linux,
9283d8817e4Smiod but the kernel produces corefiles with OSABI=SysV. */
9293d8817e4Smiod if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX &&
9303d8817e4Smiod i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
9313d8817e4Smiod return FALSE;
9323d8817e4Smiod }
9333d8817e4Smiod else if (strcmp (bfd_get_target (abfd), "elf32-hppa-netbsd") == 0)
9343d8817e4Smiod {
9353d8817e4Smiod /* GCC on hppa-netbsd produces binaries with OSABI=NetBSD,
9363d8817e4Smiod but the kernel produces corefiles with OSABI=SysV. */
9373d8817e4Smiod if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NETBSD &&
9383d8817e4Smiod i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
9393d8817e4Smiod return FALSE;
9403d8817e4Smiod }
9413d8817e4Smiod else
9423d8817e4Smiod {
9433d8817e4Smiod if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
9443d8817e4Smiod return FALSE;
9453d8817e4Smiod }
9463d8817e4Smiod
9473d8817e4Smiod flags = i_ehdrp->e_flags;
9483d8817e4Smiod switch (flags & (EF_PARISC_ARCH | EF_PARISC_WIDE))
9493d8817e4Smiod {
9503d8817e4Smiod case EFA_PARISC_1_0:
9513d8817e4Smiod return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 10);
9523d8817e4Smiod case EFA_PARISC_1_1:
9533d8817e4Smiod return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 11);
9543d8817e4Smiod case EFA_PARISC_2_0:
9553d8817e4Smiod return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);
9563d8817e4Smiod case EFA_PARISC_2_0 | EF_PARISC_WIDE:
9573d8817e4Smiod return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
9583d8817e4Smiod }
9593d8817e4Smiod return TRUE;
9603d8817e4Smiod }
9613d8817e4Smiod
9623d8817e4Smiod /* Create the .plt and .got sections, and set up our hash table
9633d8817e4Smiod short-cuts to various dynamic sections. */
9643d8817e4Smiod
9653d8817e4Smiod static bfd_boolean
elf32_hppa_create_dynamic_sections(bfd * abfd,struct bfd_link_info * info)9663d8817e4Smiod elf32_hppa_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
9673d8817e4Smiod {
9683d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
9693d8817e4Smiod struct elf_link_hash_entry *eh;
9703d8817e4Smiod
9713d8817e4Smiod /* Don't try to create the .plt and .got twice. */
9723d8817e4Smiod htab = hppa_link_hash_table (info);
9733d8817e4Smiod if (htab->splt != NULL)
9743d8817e4Smiod return TRUE;
9753d8817e4Smiod
9763d8817e4Smiod /* Call the generic code to do most of the work. */
9773d8817e4Smiod if (! _bfd_elf_create_dynamic_sections (abfd, info))
9783d8817e4Smiod return FALSE;
9793d8817e4Smiod
9803d8817e4Smiod htab->splt = bfd_get_section_by_name (abfd, ".plt");
9813d8817e4Smiod htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
9823d8817e4Smiod
9833d8817e4Smiod htab->sgot = bfd_get_section_by_name (abfd, ".got");
9843d8817e4Smiod htab->srelgot = bfd_make_section_with_flags (abfd, ".rela.got",
9853d8817e4Smiod (SEC_ALLOC
9863d8817e4Smiod | SEC_LOAD
9873d8817e4Smiod | SEC_HAS_CONTENTS
9883d8817e4Smiod | SEC_IN_MEMORY
9893d8817e4Smiod | SEC_LINKER_CREATED
9903d8817e4Smiod | SEC_READONLY));
9913d8817e4Smiod if (htab->srelgot == NULL
9923d8817e4Smiod || ! bfd_set_section_alignment (abfd, htab->srelgot, 2))
9933d8817e4Smiod return FALSE;
9943d8817e4Smiod
9953d8817e4Smiod htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
9963d8817e4Smiod htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
9973d8817e4Smiod
9983d8817e4Smiod /* hppa-linux needs _GLOBAL_OFFSET_TABLE_ to be visible from the main
9993d8817e4Smiod application, because __canonicalize_funcptr_for_compare needs it. */
10003d8817e4Smiod eh = elf_hash_table (info)->hgot;
10013d8817e4Smiod eh->forced_local = 0;
10023d8817e4Smiod eh->other = STV_DEFAULT;
10033d8817e4Smiod return bfd_elf_link_record_dynamic_symbol (info, eh);
10043d8817e4Smiod }
10053d8817e4Smiod
10063d8817e4Smiod /* Copy the extra info we tack onto an elf_link_hash_entry. */
10073d8817e4Smiod
10083d8817e4Smiod static void
elf32_hppa_copy_indirect_symbol(struct bfd_link_info * info,struct elf_link_hash_entry * eh_dir,struct elf_link_hash_entry * eh_ind)10093d8817e4Smiod elf32_hppa_copy_indirect_symbol (struct bfd_link_info *info,
10103d8817e4Smiod struct elf_link_hash_entry *eh_dir,
10113d8817e4Smiod struct elf_link_hash_entry *eh_ind)
10123d8817e4Smiod {
10133d8817e4Smiod struct elf32_hppa_link_hash_entry *hh_dir, *hh_ind;
10143d8817e4Smiod
10153d8817e4Smiod hh_dir = hppa_elf_hash_entry (eh_dir);
10163d8817e4Smiod hh_ind = hppa_elf_hash_entry (eh_ind);
10173d8817e4Smiod
10183d8817e4Smiod if (hh_ind->dyn_relocs != NULL)
10193d8817e4Smiod {
10203d8817e4Smiod if (hh_dir->dyn_relocs != NULL)
10213d8817e4Smiod {
10223d8817e4Smiod struct elf32_hppa_dyn_reloc_entry **hdh_pp;
10233d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
10243d8817e4Smiod
10253d8817e4Smiod /* Add reloc counts against the indirect sym to the direct sym
10263d8817e4Smiod list. Merge any entries against the same section. */
10273d8817e4Smiod for (hdh_pp = &hh_ind->dyn_relocs; (hdh_p = *hdh_pp) != NULL; )
10283d8817e4Smiod {
10293d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_q;
10303d8817e4Smiod
10313d8817e4Smiod for (hdh_q = hh_dir->dyn_relocs;
10323d8817e4Smiod hdh_q != NULL;
10333d8817e4Smiod hdh_q = hdh_q->hdh_next)
10343d8817e4Smiod if (hdh_q->sec == hdh_p->sec)
10353d8817e4Smiod {
10363d8817e4Smiod #if RELATIVE_DYNRELOCS
10373d8817e4Smiod hdh_q->relative_count += hdh_p->relative_count;
10383d8817e4Smiod #endif
10393d8817e4Smiod hdh_q->count += hdh_p->count;
10403d8817e4Smiod *hdh_pp = hdh_p->hdh_next;
10413d8817e4Smiod break;
10423d8817e4Smiod }
10433d8817e4Smiod if (hdh_q == NULL)
10443d8817e4Smiod hdh_pp = &hdh_p->hdh_next;
10453d8817e4Smiod }
10463d8817e4Smiod *hdh_pp = hh_dir->dyn_relocs;
10473d8817e4Smiod }
10483d8817e4Smiod
10493d8817e4Smiod hh_dir->dyn_relocs = hh_ind->dyn_relocs;
10503d8817e4Smiod hh_ind->dyn_relocs = NULL;
10513d8817e4Smiod }
10523d8817e4Smiod
10533d8817e4Smiod if (ELIMINATE_COPY_RELOCS
10543d8817e4Smiod && eh_ind->root.type != bfd_link_hash_indirect
10553d8817e4Smiod && eh_dir->dynamic_adjusted)
10563d8817e4Smiod {
10573d8817e4Smiod /* If called to transfer flags for a weakdef during processing
10583d8817e4Smiod of elf_adjust_dynamic_symbol, don't copy non_got_ref.
10593d8817e4Smiod We clear it ourselves for ELIMINATE_COPY_RELOCS. */
10603d8817e4Smiod eh_dir->ref_dynamic |= eh_ind->ref_dynamic;
10613d8817e4Smiod eh_dir->ref_regular |= eh_ind->ref_regular;
10623d8817e4Smiod eh_dir->ref_regular_nonweak |= eh_ind->ref_regular_nonweak;
10633d8817e4Smiod eh_dir->needs_plt |= eh_ind->needs_plt;
10643d8817e4Smiod }
10653d8817e4Smiod else
10663d8817e4Smiod _bfd_elf_link_hash_copy_indirect (info, eh_dir, eh_ind);
10673d8817e4Smiod }
10683d8817e4Smiod
10693d8817e4Smiod /* Look through the relocs for a section during the first phase, and
10703d8817e4Smiod calculate needed space in the global offset table, procedure linkage
10713d8817e4Smiod table, and dynamic reloc sections. At this point we haven't
10723d8817e4Smiod necessarily read all the input files. */
10733d8817e4Smiod
10743d8817e4Smiod static bfd_boolean
elf32_hppa_check_relocs(bfd * abfd,struct bfd_link_info * info,asection * sec,const Elf_Internal_Rela * relocs)10753d8817e4Smiod elf32_hppa_check_relocs (bfd *abfd,
10763d8817e4Smiod struct bfd_link_info *info,
10773d8817e4Smiod asection *sec,
10783d8817e4Smiod const Elf_Internal_Rela *relocs)
10793d8817e4Smiod {
10803d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
10813d8817e4Smiod struct elf_link_hash_entry **eh_syms;
10823d8817e4Smiod const Elf_Internal_Rela *rela;
10833d8817e4Smiod const Elf_Internal_Rela *rela_end;
10843d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
10853d8817e4Smiod asection *sreloc;
10863d8817e4Smiod asection *stubreloc;
10873d8817e4Smiod
10883d8817e4Smiod if (info->relocatable)
10893d8817e4Smiod return TRUE;
10903d8817e4Smiod
10913d8817e4Smiod htab = hppa_link_hash_table (info);
10923d8817e4Smiod symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
10933d8817e4Smiod eh_syms = elf_sym_hashes (abfd);
10943d8817e4Smiod sreloc = NULL;
10953d8817e4Smiod stubreloc = NULL;
10963d8817e4Smiod
10973d8817e4Smiod rela_end = relocs + sec->reloc_count;
10983d8817e4Smiod for (rela = relocs; rela < rela_end; rela++)
10993d8817e4Smiod {
11003d8817e4Smiod enum {
11013d8817e4Smiod NEED_GOT = 1,
11023d8817e4Smiod NEED_PLT = 2,
11033d8817e4Smiod NEED_DYNREL = 4,
11043d8817e4Smiod PLT_PLABEL = 8
11053d8817e4Smiod };
11063d8817e4Smiod
11073d8817e4Smiod unsigned int r_symndx, r_type;
11083d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
11093d8817e4Smiod int need_entry = 0;
11103d8817e4Smiod
11113d8817e4Smiod r_symndx = ELF32_R_SYM (rela->r_info);
11123d8817e4Smiod
11133d8817e4Smiod if (r_symndx < symtab_hdr->sh_info)
11143d8817e4Smiod hh = NULL;
11153d8817e4Smiod else
11163d8817e4Smiod {
11173d8817e4Smiod hh = hppa_elf_hash_entry (eh_syms[r_symndx - symtab_hdr->sh_info]);
11183d8817e4Smiod while (hh->eh.root.type == bfd_link_hash_indirect
11193d8817e4Smiod || hh->eh.root.type == bfd_link_hash_warning)
11203d8817e4Smiod hh = hppa_elf_hash_entry (hh->eh.root.u.i.link);
11213d8817e4Smiod }
11223d8817e4Smiod
11233d8817e4Smiod r_type = ELF32_R_TYPE (rela->r_info);
11243d8817e4Smiod
11253d8817e4Smiod switch (r_type)
11263d8817e4Smiod {
11273d8817e4Smiod case R_PARISC_DLTIND14F:
11283d8817e4Smiod case R_PARISC_DLTIND14R:
11293d8817e4Smiod case R_PARISC_DLTIND21L:
11303d8817e4Smiod /* This symbol requires a global offset table entry. */
11313d8817e4Smiod need_entry = NEED_GOT;
11323d8817e4Smiod break;
11333d8817e4Smiod
11343d8817e4Smiod case R_PARISC_PLABEL14R: /* "Official" procedure labels. */
11353d8817e4Smiod case R_PARISC_PLABEL21L:
11363d8817e4Smiod case R_PARISC_PLABEL32:
11373d8817e4Smiod /* If the addend is non-zero, we break badly. */
11383d8817e4Smiod if (rela->r_addend != 0)
11393d8817e4Smiod abort ();
11403d8817e4Smiod
11413d8817e4Smiod /* If we are creating a shared library, then we need to
11423d8817e4Smiod create a PLT entry for all PLABELs, because PLABELs with
11433d8817e4Smiod local symbols may be passed via a pointer to another
11443d8817e4Smiod object. Additionally, output a dynamic relocation
11453d8817e4Smiod pointing to the PLT entry.
11463d8817e4Smiod
11473d8817e4Smiod For executables, the original 32-bit ABI allowed two
11483d8817e4Smiod different styles of PLABELs (function pointers): For
11493d8817e4Smiod global functions, the PLABEL word points into the .plt
11503d8817e4Smiod two bytes past a (function address, gp) pair, and for
11513d8817e4Smiod local functions the PLABEL points directly at the
11523d8817e4Smiod function. The magic +2 for the first type allows us to
11533d8817e4Smiod differentiate between the two. As you can imagine, this
11543d8817e4Smiod is a real pain when it comes to generating code to call
11553d8817e4Smiod functions indirectly or to compare function pointers.
11563d8817e4Smiod We avoid the mess by always pointing a PLABEL into the
11573d8817e4Smiod .plt, even for local functions. */
11583d8817e4Smiod need_entry = PLT_PLABEL | NEED_PLT | NEED_DYNREL;
11593d8817e4Smiod break;
11603d8817e4Smiod
11613d8817e4Smiod case R_PARISC_PCREL12F:
11623d8817e4Smiod htab->has_12bit_branch = 1;
11633d8817e4Smiod goto branch_common;
11643d8817e4Smiod
11653d8817e4Smiod case R_PARISC_PCREL17C:
11663d8817e4Smiod case R_PARISC_PCREL17F:
11673d8817e4Smiod htab->has_17bit_branch = 1;
11683d8817e4Smiod goto branch_common;
11693d8817e4Smiod
11703d8817e4Smiod case R_PARISC_PCREL22F:
11713d8817e4Smiod htab->has_22bit_branch = 1;
11723d8817e4Smiod branch_common:
11733d8817e4Smiod /* Function calls might need to go through the .plt, and
11743d8817e4Smiod might require long branch stubs. */
11753d8817e4Smiod if (hh == NULL)
11763d8817e4Smiod {
11773d8817e4Smiod /* We know local syms won't need a .plt entry, and if
11783d8817e4Smiod they need a long branch stub we can't guarantee that
11793d8817e4Smiod we can reach the stub. So just flag an error later
11803d8817e4Smiod if we're doing a shared link and find we need a long
11813d8817e4Smiod branch stub. */
11823d8817e4Smiod continue;
11833d8817e4Smiod }
11843d8817e4Smiod else
11853d8817e4Smiod {
11863d8817e4Smiod /* Global symbols will need a .plt entry if they remain
11873d8817e4Smiod global, and in most cases won't need a long branch
11883d8817e4Smiod stub. Unfortunately, we have to cater for the case
11893d8817e4Smiod where a symbol is forced local by versioning, or due
11903d8817e4Smiod to symbolic linking, and we lose the .plt entry. */
11913d8817e4Smiod need_entry = NEED_PLT;
11923d8817e4Smiod if (hh->eh.type == STT_PARISC_MILLI)
11933d8817e4Smiod need_entry = 0;
11943d8817e4Smiod }
11953d8817e4Smiod break;
11963d8817e4Smiod
11973d8817e4Smiod case R_PARISC_SEGBASE: /* Used to set segment base. */
11983d8817e4Smiod case R_PARISC_SEGREL32: /* Relative reloc, used for unwind. */
11993d8817e4Smiod case R_PARISC_PCREL14F: /* PC relative load/store. */
12003d8817e4Smiod case R_PARISC_PCREL14R:
12013d8817e4Smiod case R_PARISC_PCREL17R: /* External branches. */
12023d8817e4Smiod case R_PARISC_PCREL21L: /* As above, and for load/store too. */
12033d8817e4Smiod case R_PARISC_PCREL32:
12043d8817e4Smiod /* We don't need to propagate the relocation if linking a
12053d8817e4Smiod shared object since these are section relative. */
12063d8817e4Smiod continue;
12073d8817e4Smiod
12083d8817e4Smiod case R_PARISC_DPREL14F: /* Used for gp rel data load/store. */
12093d8817e4Smiod case R_PARISC_DPREL14R:
12103d8817e4Smiod case R_PARISC_DPREL21L:
12113d8817e4Smiod if (info->shared)
12123d8817e4Smiod {
12133d8817e4Smiod (*_bfd_error_handler)
12143d8817e4Smiod (_("%B: relocation %s can not be used when making a shared object; recompile with -fPIC"),
12153d8817e4Smiod abfd,
12163d8817e4Smiod elf_hppa_howto_table[r_type].name);
12173d8817e4Smiod bfd_set_error (bfd_error_bad_value);
12183d8817e4Smiod return FALSE;
12193d8817e4Smiod }
12203d8817e4Smiod /* Fall through. */
12213d8817e4Smiod
12223d8817e4Smiod case R_PARISC_DIR17F: /* Used for external branches. */
12233d8817e4Smiod case R_PARISC_DIR17R:
12243d8817e4Smiod case R_PARISC_DIR14F: /* Used for load/store from absolute locn. */
12253d8817e4Smiod case R_PARISC_DIR14R:
12263d8817e4Smiod case R_PARISC_DIR21L: /* As above, and for ext branches too. */
12273d8817e4Smiod case R_PARISC_DIR32: /* .word relocs. */
12283d8817e4Smiod /* We may want to output a dynamic relocation later. */
12293d8817e4Smiod need_entry = NEED_DYNREL;
12303d8817e4Smiod break;
12313d8817e4Smiod
12323d8817e4Smiod /* This relocation describes the C++ object vtable hierarchy.
12333d8817e4Smiod Reconstruct it for later use during GC. */
12343d8817e4Smiod case R_PARISC_GNU_VTINHERIT:
12353d8817e4Smiod if (!bfd_elf_gc_record_vtinherit (abfd, sec, &hh->eh, rela->r_offset))
12363d8817e4Smiod return FALSE;
12373d8817e4Smiod continue;
12383d8817e4Smiod
12393d8817e4Smiod /* This relocation describes which C++ vtable entries are actually
12403d8817e4Smiod used. Record for later use during GC. */
12413d8817e4Smiod case R_PARISC_GNU_VTENTRY:
12423d8817e4Smiod if (!bfd_elf_gc_record_vtentry (abfd, sec, &hh->eh, rela->r_addend))
12433d8817e4Smiod return FALSE;
12443d8817e4Smiod continue;
12453d8817e4Smiod
12463d8817e4Smiod default:
12473d8817e4Smiod continue;
12483d8817e4Smiod }
12493d8817e4Smiod
12503d8817e4Smiod /* Now carry out our orders. */
12513d8817e4Smiod if (need_entry & NEED_GOT)
12523d8817e4Smiod {
12533d8817e4Smiod /* Allocate space for a GOT entry, as well as a dynamic
12543d8817e4Smiod relocation for this entry. */
12553d8817e4Smiod if (htab->sgot == NULL)
12563d8817e4Smiod {
12573d8817e4Smiod if (htab->etab.dynobj == NULL)
12583d8817e4Smiod htab->etab.dynobj = abfd;
12593d8817e4Smiod if (!elf32_hppa_create_dynamic_sections (htab->etab.dynobj, info))
12603d8817e4Smiod return FALSE;
12613d8817e4Smiod }
12623d8817e4Smiod
12633d8817e4Smiod if (hh != NULL)
12643d8817e4Smiod {
12653d8817e4Smiod hh->eh.got.refcount += 1;
12663d8817e4Smiod }
12673d8817e4Smiod else
12683d8817e4Smiod {
12693d8817e4Smiod bfd_signed_vma *local_got_refcounts;
12703d8817e4Smiod /* This is a global offset table entry for a local symbol. */
12713d8817e4Smiod local_got_refcounts = elf_local_got_refcounts (abfd);
12723d8817e4Smiod if (local_got_refcounts == NULL)
12733d8817e4Smiod {
12743d8817e4Smiod bfd_size_type size;
12753d8817e4Smiod
12763d8817e4Smiod /* Allocate space for local got offsets and local
12773d8817e4Smiod plt offsets. Done this way to save polluting
12783d8817e4Smiod elf_obj_tdata with another target specific
12793d8817e4Smiod pointer. */
12803d8817e4Smiod size = symtab_hdr->sh_info;
12813d8817e4Smiod size *= 2 * sizeof (bfd_signed_vma);
12823d8817e4Smiod local_got_refcounts = bfd_zalloc (abfd, size);
12833d8817e4Smiod if (local_got_refcounts == NULL)
12843d8817e4Smiod return FALSE;
12853d8817e4Smiod elf_local_got_refcounts (abfd) = local_got_refcounts;
12863d8817e4Smiod }
12873d8817e4Smiod local_got_refcounts[r_symndx] += 1;
12883d8817e4Smiod }
12893d8817e4Smiod }
12903d8817e4Smiod
12913d8817e4Smiod if (need_entry & NEED_PLT)
12923d8817e4Smiod {
12933d8817e4Smiod /* If we are creating a shared library, and this is a reloc
12943d8817e4Smiod against a weak symbol or a global symbol in a dynamic
12953d8817e4Smiod object, then we will be creating an import stub and a
12963d8817e4Smiod .plt entry for the symbol. Similarly, on a normal link
12973d8817e4Smiod to symbols defined in a dynamic object we'll need the
12983d8817e4Smiod import stub and a .plt entry. We don't know yet whether
12993d8817e4Smiod the symbol is defined or not, so make an entry anyway and
13003d8817e4Smiod clean up later in adjust_dynamic_symbol. */
13013d8817e4Smiod if ((sec->flags & SEC_ALLOC) != 0)
13023d8817e4Smiod {
13033d8817e4Smiod if (hh != NULL)
13043d8817e4Smiod {
13053d8817e4Smiod hh->eh.needs_plt = 1;
13063d8817e4Smiod hh->eh.plt.refcount += 1;
13073d8817e4Smiod
13083d8817e4Smiod /* If this .plt entry is for a plabel, mark it so
13093d8817e4Smiod that adjust_dynamic_symbol will keep the entry
13103d8817e4Smiod even if it appears to be local. */
13113d8817e4Smiod if (need_entry & PLT_PLABEL)
13123d8817e4Smiod hh->plabel = 1;
13133d8817e4Smiod }
13143d8817e4Smiod else if (need_entry & PLT_PLABEL)
13153d8817e4Smiod {
13163d8817e4Smiod bfd_signed_vma *local_got_refcounts;
13173d8817e4Smiod bfd_signed_vma *local_plt_refcounts;
13183d8817e4Smiod
13193d8817e4Smiod local_got_refcounts = elf_local_got_refcounts (abfd);
13203d8817e4Smiod if (local_got_refcounts == NULL)
13213d8817e4Smiod {
13223d8817e4Smiod bfd_size_type size;
13233d8817e4Smiod
13243d8817e4Smiod /* Allocate space for local got offsets and local
13253d8817e4Smiod plt offsets. */
13263d8817e4Smiod size = symtab_hdr->sh_info;
13273d8817e4Smiod size *= 2 * sizeof (bfd_signed_vma);
13283d8817e4Smiod local_got_refcounts = bfd_zalloc (abfd, size);
13293d8817e4Smiod if (local_got_refcounts == NULL)
13303d8817e4Smiod return FALSE;
13313d8817e4Smiod elf_local_got_refcounts (abfd) = local_got_refcounts;
13323d8817e4Smiod }
13333d8817e4Smiod local_plt_refcounts = (local_got_refcounts
13343d8817e4Smiod + symtab_hdr->sh_info);
13353d8817e4Smiod local_plt_refcounts[r_symndx] += 1;
13363d8817e4Smiod }
13373d8817e4Smiod }
13383d8817e4Smiod }
13393d8817e4Smiod
13403d8817e4Smiod if (need_entry & NEED_DYNREL)
13413d8817e4Smiod {
13423d8817e4Smiod /* Flag this symbol as having a non-got, non-plt reference
13433d8817e4Smiod so that we generate copy relocs if it turns out to be
13443d8817e4Smiod dynamic. */
13453d8817e4Smiod if (hh != NULL && !info->shared)
13463d8817e4Smiod hh->eh.non_got_ref = 1;
13473d8817e4Smiod
13483d8817e4Smiod /* If we are creating a shared library then we need to copy
13493d8817e4Smiod the reloc into the shared library. However, if we are
13503d8817e4Smiod linking with -Bsymbolic, we need only copy absolute
13513d8817e4Smiod relocs or relocs against symbols that are not defined in
13523d8817e4Smiod an object we are including in the link. PC- or DP- or
13533d8817e4Smiod DLT-relative relocs against any local sym or global sym
13543d8817e4Smiod with DEF_REGULAR set, can be discarded. At this point we
13553d8817e4Smiod have not seen all the input files, so it is possible that
13563d8817e4Smiod DEF_REGULAR is not set now but will be set later (it is
13573d8817e4Smiod never cleared). We account for that possibility below by
13583d8817e4Smiod storing information in the dyn_relocs field of the
13593d8817e4Smiod hash table entry.
13603d8817e4Smiod
13613d8817e4Smiod A similar situation to the -Bsymbolic case occurs when
13623d8817e4Smiod creating shared libraries and symbol visibility changes
13633d8817e4Smiod render the symbol local.
13643d8817e4Smiod
13653d8817e4Smiod As it turns out, all the relocs we will be creating here
13663d8817e4Smiod are absolute, so we cannot remove them on -Bsymbolic
13673d8817e4Smiod links or visibility changes anyway. A STUB_REL reloc
13683d8817e4Smiod is absolute too, as in that case it is the reloc in the
13693d8817e4Smiod stub we will be creating, rather than copying the PCREL
13703d8817e4Smiod reloc in the branch.
13713d8817e4Smiod
13723d8817e4Smiod If on the other hand, we are creating an executable, we
13733d8817e4Smiod may need to keep relocations for symbols satisfied by a
13743d8817e4Smiod dynamic library if we manage to avoid copy relocs for the
13753d8817e4Smiod symbol. */
13763d8817e4Smiod if ((info->shared
13773d8817e4Smiod && (sec->flags & SEC_ALLOC) != 0
13783d8817e4Smiod && (IS_ABSOLUTE_RELOC (r_type)
13793d8817e4Smiod || (hh != NULL
13803d8817e4Smiod && (!info->symbolic
13813d8817e4Smiod || hh->eh.root.type == bfd_link_hash_defweak
13823d8817e4Smiod || !hh->eh.def_regular))))
13833d8817e4Smiod || (ELIMINATE_COPY_RELOCS
13843d8817e4Smiod && !info->shared
13853d8817e4Smiod && (sec->flags & SEC_ALLOC) != 0
13863d8817e4Smiod && hh != NULL
13873d8817e4Smiod && (hh->eh.root.type == bfd_link_hash_defweak
13883d8817e4Smiod || !hh->eh.def_regular)))
13893d8817e4Smiod {
13903d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
13913d8817e4Smiod struct elf32_hppa_dyn_reloc_entry **hdh_head;
13923d8817e4Smiod
13933d8817e4Smiod /* Create a reloc section in dynobj and make room for
13943d8817e4Smiod this reloc. */
13953d8817e4Smiod if (sreloc == NULL)
13963d8817e4Smiod {
13973d8817e4Smiod char *name;
13983d8817e4Smiod bfd *dynobj;
13993d8817e4Smiod
14003d8817e4Smiod name = (bfd_elf_string_from_elf_section
14013d8817e4Smiod (abfd,
14023d8817e4Smiod elf_elfheader (abfd)->e_shstrndx,
14033d8817e4Smiod elf_section_data (sec)->rel_hdr.sh_name));
14043d8817e4Smiod if (name == NULL)
14053d8817e4Smiod {
14063d8817e4Smiod (*_bfd_error_handler)
14073d8817e4Smiod (_("Could not find relocation section for %s"),
14083d8817e4Smiod sec->name);
14093d8817e4Smiod bfd_set_error (bfd_error_bad_value);
14103d8817e4Smiod return FALSE;
14113d8817e4Smiod }
14123d8817e4Smiod
14133d8817e4Smiod if (htab->etab.dynobj == NULL)
14143d8817e4Smiod htab->etab.dynobj = abfd;
14153d8817e4Smiod
14163d8817e4Smiod dynobj = htab->etab.dynobj;
14173d8817e4Smiod sreloc = bfd_get_section_by_name (dynobj, name);
14183d8817e4Smiod if (sreloc == NULL)
14193d8817e4Smiod {
14203d8817e4Smiod flagword flags;
14213d8817e4Smiod
14223d8817e4Smiod flags = (SEC_HAS_CONTENTS | SEC_READONLY
14233d8817e4Smiod | SEC_IN_MEMORY | SEC_LINKER_CREATED);
14243d8817e4Smiod if ((sec->flags & SEC_ALLOC) != 0)
14253d8817e4Smiod flags |= SEC_ALLOC | SEC_LOAD;
14263d8817e4Smiod sreloc = bfd_make_section_with_flags (dynobj,
14273d8817e4Smiod name,
14283d8817e4Smiod flags);
14293d8817e4Smiod if (sreloc == NULL
14303d8817e4Smiod || !bfd_set_section_alignment (dynobj, sreloc, 2))
14313d8817e4Smiod return FALSE;
14323d8817e4Smiod }
14333d8817e4Smiod
14343d8817e4Smiod elf_section_data (sec)->sreloc = sreloc;
14353d8817e4Smiod }
14363d8817e4Smiod
14373d8817e4Smiod /* If this is a global symbol, we count the number of
14383d8817e4Smiod relocations we need for this symbol. */
14393d8817e4Smiod if (hh != NULL)
14403d8817e4Smiod {
14413d8817e4Smiod hdh_head = &hh->dyn_relocs;
14423d8817e4Smiod }
14433d8817e4Smiod else
14443d8817e4Smiod {
14453d8817e4Smiod /* Track dynamic relocs needed for local syms too.
14463d8817e4Smiod We really need local syms available to do this
14473d8817e4Smiod easily. Oh well. */
14483d8817e4Smiod
14493d8817e4Smiod asection *sr;
14503d8817e4Smiod void *vpp;
14513d8817e4Smiod
14523d8817e4Smiod sr = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
14533d8817e4Smiod sec, r_symndx);
14543d8817e4Smiod if (sr == NULL)
14553d8817e4Smiod return FALSE;
14563d8817e4Smiod
14573d8817e4Smiod vpp = &elf_section_data (sr)->local_dynrel;
14583d8817e4Smiod hdh_head = (struct elf32_hppa_dyn_reloc_entry **) vpp;
14593d8817e4Smiod }
14603d8817e4Smiod
14613d8817e4Smiod hdh_p = *hdh_head;
14623d8817e4Smiod if (hdh_p == NULL || hdh_p->sec != sec)
14633d8817e4Smiod {
14643d8817e4Smiod hdh_p = bfd_alloc (htab->etab.dynobj, sizeof *hdh_p);
14653d8817e4Smiod if (hdh_p == NULL)
14663d8817e4Smiod return FALSE;
14673d8817e4Smiod hdh_p->hdh_next = *hdh_head;
14683d8817e4Smiod *hdh_head = hdh_p;
14693d8817e4Smiod hdh_p->sec = sec;
14703d8817e4Smiod hdh_p->count = 0;
14713d8817e4Smiod #if RELATIVE_DYNRELOCS
14723d8817e4Smiod hdh_p->relative_count = 0;
14733d8817e4Smiod #endif
14743d8817e4Smiod }
14753d8817e4Smiod
14763d8817e4Smiod hdh_p->count += 1;
14773d8817e4Smiod #if RELATIVE_DYNRELOCS
14783d8817e4Smiod if (!IS_ABSOLUTE_RELOC (rtype))
14793d8817e4Smiod hdh_p->relative_count += 1;
14803d8817e4Smiod #endif
14813d8817e4Smiod }
14823d8817e4Smiod }
14833d8817e4Smiod }
14843d8817e4Smiod
14853d8817e4Smiod return TRUE;
14863d8817e4Smiod }
14873d8817e4Smiod
14883d8817e4Smiod /* Return the section that should be marked against garbage collection
14893d8817e4Smiod for a given relocation. */
14903d8817e4Smiod
14913d8817e4Smiod static asection *
elf32_hppa_gc_mark_hook(asection * sec,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Rela * rela,struct elf_link_hash_entry * hh,Elf_Internal_Sym * sym)14923d8817e4Smiod elf32_hppa_gc_mark_hook (asection *sec,
14933d8817e4Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED,
14943d8817e4Smiod Elf_Internal_Rela *rela,
14953d8817e4Smiod struct elf_link_hash_entry *hh,
14963d8817e4Smiod Elf_Internal_Sym *sym)
14973d8817e4Smiod {
14983d8817e4Smiod if (hh != NULL)
14993d8817e4Smiod {
15003d8817e4Smiod switch ((unsigned int) ELF32_R_TYPE (rela->r_info))
15013d8817e4Smiod {
15023d8817e4Smiod case R_PARISC_GNU_VTINHERIT:
15033d8817e4Smiod case R_PARISC_GNU_VTENTRY:
15043d8817e4Smiod break;
15053d8817e4Smiod
15063d8817e4Smiod default:
15073d8817e4Smiod switch (hh->root.type)
15083d8817e4Smiod {
15093d8817e4Smiod case bfd_link_hash_defined:
15103d8817e4Smiod case bfd_link_hash_defweak:
15113d8817e4Smiod return hh->root.u.def.section;
15123d8817e4Smiod
15133d8817e4Smiod case bfd_link_hash_common:
15143d8817e4Smiod return hh->root.u.c.p->section;
15153d8817e4Smiod
15163d8817e4Smiod default:
15173d8817e4Smiod break;
15183d8817e4Smiod }
15193d8817e4Smiod }
15203d8817e4Smiod }
15213d8817e4Smiod else
15223d8817e4Smiod return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
15233d8817e4Smiod
15243d8817e4Smiod return NULL;
15253d8817e4Smiod }
15263d8817e4Smiod
15273d8817e4Smiod /* Update the got and plt entry reference counts for the section being
15283d8817e4Smiod removed. */
15293d8817e4Smiod
15303d8817e4Smiod static bfd_boolean
elf32_hppa_gc_sweep_hook(bfd * abfd,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sec,const Elf_Internal_Rela * relocs)15313d8817e4Smiod elf32_hppa_gc_sweep_hook (bfd *abfd,
15323d8817e4Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED,
15333d8817e4Smiod asection *sec,
15343d8817e4Smiod const Elf_Internal_Rela *relocs)
15353d8817e4Smiod {
15363d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
15373d8817e4Smiod struct elf_link_hash_entry **eh_syms;
15383d8817e4Smiod bfd_signed_vma *local_got_refcounts;
15393d8817e4Smiod bfd_signed_vma *local_plt_refcounts;
15403d8817e4Smiod const Elf_Internal_Rela *rela, *relend;
15413d8817e4Smiod
15423d8817e4Smiod elf_section_data (sec)->local_dynrel = NULL;
15433d8817e4Smiod
15443d8817e4Smiod symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
15453d8817e4Smiod eh_syms = elf_sym_hashes (abfd);
15463d8817e4Smiod local_got_refcounts = elf_local_got_refcounts (abfd);
15473d8817e4Smiod local_plt_refcounts = local_got_refcounts;
15483d8817e4Smiod if (local_plt_refcounts != NULL)
15493d8817e4Smiod local_plt_refcounts += symtab_hdr->sh_info;
15503d8817e4Smiod
15513d8817e4Smiod relend = relocs + sec->reloc_count;
15523d8817e4Smiod for (rela = relocs; rela < relend; rela++)
15533d8817e4Smiod {
15543d8817e4Smiod unsigned long r_symndx;
15553d8817e4Smiod unsigned int r_type;
15563d8817e4Smiod struct elf_link_hash_entry *eh = NULL;
15573d8817e4Smiod
15583d8817e4Smiod r_symndx = ELF32_R_SYM (rela->r_info);
15593d8817e4Smiod if (r_symndx >= symtab_hdr->sh_info)
15603d8817e4Smiod {
15613d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
15623d8817e4Smiod struct elf32_hppa_dyn_reloc_entry **hdh_pp;
15633d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
15643d8817e4Smiod
15653d8817e4Smiod eh = eh_syms[r_symndx - symtab_hdr->sh_info];
15663d8817e4Smiod while (eh->root.type == bfd_link_hash_indirect
15673d8817e4Smiod || eh->root.type == bfd_link_hash_warning)
15683d8817e4Smiod eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
15693d8817e4Smiod hh = hppa_elf_hash_entry (eh);
15703d8817e4Smiod
15713d8817e4Smiod for (hdh_pp = &hh->dyn_relocs; (hdh_p = *hdh_pp) != NULL; hdh_pp = &hdh_p->hdh_next)
15723d8817e4Smiod if (hdh_p->sec == sec)
15733d8817e4Smiod {
15743d8817e4Smiod /* Everything must go for SEC. */
15753d8817e4Smiod *hdh_pp = hdh_p->hdh_next;
15763d8817e4Smiod break;
15773d8817e4Smiod }
15783d8817e4Smiod }
15793d8817e4Smiod
15803d8817e4Smiod r_type = ELF32_R_TYPE (rela->r_info);
15813d8817e4Smiod switch (r_type)
15823d8817e4Smiod {
15833d8817e4Smiod case R_PARISC_DLTIND14F:
15843d8817e4Smiod case R_PARISC_DLTIND14R:
15853d8817e4Smiod case R_PARISC_DLTIND21L:
15863d8817e4Smiod if (eh != NULL)
15873d8817e4Smiod {
15883d8817e4Smiod if (eh->got.refcount > 0)
15893d8817e4Smiod eh->got.refcount -= 1;
15903d8817e4Smiod }
15913d8817e4Smiod else if (local_got_refcounts != NULL)
15923d8817e4Smiod {
15933d8817e4Smiod if (local_got_refcounts[r_symndx] > 0)
15943d8817e4Smiod local_got_refcounts[r_symndx] -= 1;
15953d8817e4Smiod }
15963d8817e4Smiod break;
15973d8817e4Smiod
15983d8817e4Smiod case R_PARISC_PCREL12F:
15993d8817e4Smiod case R_PARISC_PCREL17C:
16003d8817e4Smiod case R_PARISC_PCREL17F:
16013d8817e4Smiod case R_PARISC_PCREL22F:
16023d8817e4Smiod if (eh != NULL)
16033d8817e4Smiod {
16043d8817e4Smiod if (eh->plt.refcount > 0)
16053d8817e4Smiod eh->plt.refcount -= 1;
16063d8817e4Smiod }
16073d8817e4Smiod break;
16083d8817e4Smiod
16093d8817e4Smiod case R_PARISC_PLABEL14R:
16103d8817e4Smiod case R_PARISC_PLABEL21L:
16113d8817e4Smiod case R_PARISC_PLABEL32:
16123d8817e4Smiod if (eh != NULL)
16133d8817e4Smiod {
16143d8817e4Smiod if (eh->plt.refcount > 0)
16153d8817e4Smiod eh->plt.refcount -= 1;
16163d8817e4Smiod }
16173d8817e4Smiod else if (local_plt_refcounts != NULL)
16183d8817e4Smiod {
16193d8817e4Smiod if (local_plt_refcounts[r_symndx] > 0)
16203d8817e4Smiod local_plt_refcounts[r_symndx] -= 1;
16213d8817e4Smiod }
16223d8817e4Smiod break;
16233d8817e4Smiod
16243d8817e4Smiod default:
16253d8817e4Smiod break;
16263d8817e4Smiod }
16273d8817e4Smiod }
16283d8817e4Smiod
16293d8817e4Smiod return TRUE;
16303d8817e4Smiod }
16313d8817e4Smiod
16323d8817e4Smiod /* Support for core dump NOTE sections. */
16333d8817e4Smiod
16343d8817e4Smiod static bfd_boolean
elf32_hppa_grok_prstatus(bfd * abfd,Elf_Internal_Note * note)16353d8817e4Smiod elf32_hppa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
16363d8817e4Smiod {
16373d8817e4Smiod int offset;
16383d8817e4Smiod size_t size;
16393d8817e4Smiod
16403d8817e4Smiod switch (note->descsz)
16413d8817e4Smiod {
16423d8817e4Smiod default:
16433d8817e4Smiod return FALSE;
16443d8817e4Smiod
16453d8817e4Smiod case 396: /* Linux/hppa */
16463d8817e4Smiod /* pr_cursig */
16473d8817e4Smiod elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
16483d8817e4Smiod
16493d8817e4Smiod /* pr_pid */
16503d8817e4Smiod elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
16513d8817e4Smiod
16523d8817e4Smiod /* pr_reg */
16533d8817e4Smiod offset = 72;
16543d8817e4Smiod size = 320;
16553d8817e4Smiod
16563d8817e4Smiod break;
16573d8817e4Smiod }
16583d8817e4Smiod
16593d8817e4Smiod /* Make a ".reg/999" section. */
16603d8817e4Smiod return _bfd_elfcore_make_pseudosection (abfd, ".reg",
16613d8817e4Smiod size, note->descpos + offset);
16623d8817e4Smiod }
16633d8817e4Smiod
16643d8817e4Smiod static bfd_boolean
elf32_hppa_grok_psinfo(bfd * abfd,Elf_Internal_Note * note)16653d8817e4Smiod elf32_hppa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
16663d8817e4Smiod {
16673d8817e4Smiod switch (note->descsz)
16683d8817e4Smiod {
16693d8817e4Smiod default:
16703d8817e4Smiod return FALSE;
16713d8817e4Smiod
16723d8817e4Smiod case 124: /* Linux/hppa elf_prpsinfo. */
16733d8817e4Smiod elf_tdata (abfd)->core_program
16743d8817e4Smiod = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
16753d8817e4Smiod elf_tdata (abfd)->core_command
16763d8817e4Smiod = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
16773d8817e4Smiod }
16783d8817e4Smiod
16793d8817e4Smiod /* Note that for some reason, a spurious space is tacked
16803d8817e4Smiod onto the end of the args in some (at least one anyway)
16813d8817e4Smiod implementations, so strip it off if it exists. */
16823d8817e4Smiod {
16833d8817e4Smiod char *command = elf_tdata (abfd)->core_command;
16843d8817e4Smiod int n = strlen (command);
16853d8817e4Smiod
16863d8817e4Smiod if (0 < n && command[n - 1] == ' ')
16873d8817e4Smiod command[n - 1] = '\0';
16883d8817e4Smiod }
16893d8817e4Smiod
16903d8817e4Smiod return TRUE;
16913d8817e4Smiod }
16923d8817e4Smiod
16933d8817e4Smiod /* Our own version of hide_symbol, so that we can keep plt entries for
16943d8817e4Smiod plabels. */
16953d8817e4Smiod
16963d8817e4Smiod static void
elf32_hppa_hide_symbol(struct bfd_link_info * info,struct elf_link_hash_entry * eh,bfd_boolean force_local)16973d8817e4Smiod elf32_hppa_hide_symbol (struct bfd_link_info *info,
16983d8817e4Smiod struct elf_link_hash_entry *eh,
16993d8817e4Smiod bfd_boolean force_local)
17003d8817e4Smiod {
17013d8817e4Smiod if (force_local)
17023d8817e4Smiod {
17033d8817e4Smiod eh->forced_local = 1;
17043d8817e4Smiod if (eh->dynindx != -1)
17053d8817e4Smiod {
17063d8817e4Smiod eh->dynindx = -1;
17073d8817e4Smiod _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
17083d8817e4Smiod eh->dynstr_index);
17093d8817e4Smiod }
17103d8817e4Smiod }
17113d8817e4Smiod
17123d8817e4Smiod if (! hppa_elf_hash_entry(eh)->plabel)
17133d8817e4Smiod {
17143d8817e4Smiod eh->needs_plt = 0;
1715*39e16c99Skettenis eh->plt = elf_hash_table (info)->init_plt_offset;
17163d8817e4Smiod }
17173d8817e4Smiod }
17183d8817e4Smiod
17193d8817e4Smiod /* Adjust a symbol defined by a dynamic object and referenced by a
17203d8817e4Smiod regular object. The current definition is in some section of the
17213d8817e4Smiod dynamic object, but we're not including those sections. We have to
17223d8817e4Smiod change the definition to something the rest of the link can
17233d8817e4Smiod understand. */
17243d8817e4Smiod
17253d8817e4Smiod static bfd_boolean
elf32_hppa_adjust_dynamic_symbol(struct bfd_link_info * info,struct elf_link_hash_entry * eh)17263d8817e4Smiod elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
17273d8817e4Smiod struct elf_link_hash_entry *eh)
17283d8817e4Smiod {
17293d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
17303d8817e4Smiod asection *sec;
17313d8817e4Smiod unsigned int power_of_two;
17323d8817e4Smiod
17333d8817e4Smiod /* If this is a function, put it in the procedure linkage table. We
17343d8817e4Smiod will fill in the contents of the procedure linkage table later. */
17353d8817e4Smiod if (eh->type == STT_FUNC
17363d8817e4Smiod || eh->needs_plt)
17373d8817e4Smiod {
1738*39e16c99Skettenis /* We must always allocate a .plt entry if the symbol is used by
1739*39e16c99Skettenis a plabel. For hidden symbols the refcount may have been
1740*39e16c99Skettenis reset . Fix it here to avoidlosing the .plt entry later. */
1741*39e16c99Skettenis if (hppa_elf_hash_entry (eh)->plabel)
1742*39e16c99Skettenis eh->plt.refcount = 1;
1743*39e16c99Skettenis
17443d8817e4Smiod if (eh->plt.refcount <= 0
17453d8817e4Smiod || (eh->def_regular
17463d8817e4Smiod && eh->root.type != bfd_link_hash_defweak
17473d8817e4Smiod && ! hppa_elf_hash_entry (eh)->plabel
17483d8817e4Smiod && (!info->shared || info->symbolic)))
17493d8817e4Smiod {
17503d8817e4Smiod /* The .plt entry is not needed when:
17513d8817e4Smiod a) Garbage collection has removed all references to the
17523d8817e4Smiod symbol, or
17533d8817e4Smiod b) We know for certain the symbol is defined in this
17543d8817e4Smiod object, and it's not a weak definition, nor is the symbol
17553d8817e4Smiod used by a plabel relocation. Either this object is the
17563d8817e4Smiod application or we are doing a shared symbolic link. */
17573d8817e4Smiod
17583d8817e4Smiod eh->plt.offset = (bfd_vma) -1;
17593d8817e4Smiod eh->needs_plt = 0;
17603d8817e4Smiod }
17613d8817e4Smiod
17623d8817e4Smiod return TRUE;
17633d8817e4Smiod }
17643d8817e4Smiod else
17653d8817e4Smiod eh->plt.offset = (bfd_vma) -1;
17663d8817e4Smiod
17673d8817e4Smiod /* If this is a weak symbol, and there is a real definition, the
17683d8817e4Smiod processor independent code will have arranged for us to see the
17693d8817e4Smiod real definition first, and we can just use the same value. */
17703d8817e4Smiod if (eh->u.weakdef != NULL)
17713d8817e4Smiod {
17723d8817e4Smiod if (eh->u.weakdef->root.type != bfd_link_hash_defined
17733d8817e4Smiod && eh->u.weakdef->root.type != bfd_link_hash_defweak)
17743d8817e4Smiod abort ();
17753d8817e4Smiod eh->root.u.def.section = eh->u.weakdef->root.u.def.section;
17763d8817e4Smiod eh->root.u.def.value = eh->u.weakdef->root.u.def.value;
17773d8817e4Smiod if (ELIMINATE_COPY_RELOCS)
17783d8817e4Smiod eh->non_got_ref = eh->u.weakdef->non_got_ref;
17793d8817e4Smiod return TRUE;
17803d8817e4Smiod }
17813d8817e4Smiod
17823d8817e4Smiod /* This is a reference to a symbol defined by a dynamic object which
17833d8817e4Smiod is not a function. */
17843d8817e4Smiod
17853d8817e4Smiod /* If we are creating a shared library, we must presume that the
17863d8817e4Smiod only references to the symbol are via the global offset table.
17873d8817e4Smiod For such cases we need not do anything here; the relocations will
17883d8817e4Smiod be handled correctly by relocate_section. */
17893d8817e4Smiod if (info->shared)
17903d8817e4Smiod return TRUE;
17913d8817e4Smiod
17923d8817e4Smiod /* If there are no references to this symbol that do not use the
17933d8817e4Smiod GOT, we don't need to generate a copy reloc. */
17943d8817e4Smiod if (!eh->non_got_ref)
17953d8817e4Smiod return TRUE;
17963d8817e4Smiod
17973d8817e4Smiod if (ELIMINATE_COPY_RELOCS)
17983d8817e4Smiod {
17993d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
18003d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
18013d8817e4Smiod
18023d8817e4Smiod hh = hppa_elf_hash_entry (eh);
18033d8817e4Smiod for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next)
18043d8817e4Smiod {
18053d8817e4Smiod sec = hdh_p->sec->output_section;
18063d8817e4Smiod if (sec != NULL && (sec->flags & SEC_READONLY) != 0)
18073d8817e4Smiod break;
18083d8817e4Smiod }
18093d8817e4Smiod
18103d8817e4Smiod /* If we didn't find any dynamic relocs in read-only sections, then
18113d8817e4Smiod we'll be keeping the dynamic relocs and avoiding the copy reloc. */
18123d8817e4Smiod if (hdh_p == NULL)
18133d8817e4Smiod {
18143d8817e4Smiod eh->non_got_ref = 0;
18153d8817e4Smiod return TRUE;
18163d8817e4Smiod }
18173d8817e4Smiod }
18183d8817e4Smiod
18193d8817e4Smiod if (eh->size == 0)
18203d8817e4Smiod {
18213d8817e4Smiod (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
18223d8817e4Smiod eh->root.root.string);
18233d8817e4Smiod return TRUE;
18243d8817e4Smiod }
18253d8817e4Smiod
18263d8817e4Smiod /* We must allocate the symbol in our .dynbss section, which will
18273d8817e4Smiod become part of the .bss section of the executable. There will be
18283d8817e4Smiod an entry for this symbol in the .dynsym section. The dynamic
18293d8817e4Smiod object will contain position independent code, so all references
18303d8817e4Smiod from the dynamic object to this symbol will go through the global
18313d8817e4Smiod offset table. The dynamic linker will use the .dynsym entry to
18323d8817e4Smiod determine the address it must put in the global offset table, so
18333d8817e4Smiod both the dynamic object and the regular object will refer to the
18343d8817e4Smiod same memory location for the variable. */
18353d8817e4Smiod
18363d8817e4Smiod htab = hppa_link_hash_table (info);
18373d8817e4Smiod
18383d8817e4Smiod /* We must generate a COPY reloc to tell the dynamic linker to
18393d8817e4Smiod copy the initial value out of the dynamic object and into the
18403d8817e4Smiod runtime process image. */
18413d8817e4Smiod if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0)
18423d8817e4Smiod {
18433d8817e4Smiod htab->srelbss->size += sizeof (Elf32_External_Rela);
18443d8817e4Smiod eh->needs_copy = 1;
18453d8817e4Smiod }
18463d8817e4Smiod
18473d8817e4Smiod /* We need to figure out the alignment required for this symbol. I
18483d8817e4Smiod have no idea how other ELF linkers handle this. */
18493d8817e4Smiod
18503d8817e4Smiod power_of_two = bfd_log2 (eh->size);
18513d8817e4Smiod if (power_of_two > 3)
18523d8817e4Smiod power_of_two = 3;
18533d8817e4Smiod
18543d8817e4Smiod /* Apply the required alignment. */
18553d8817e4Smiod sec = htab->sdynbss;
18563d8817e4Smiod sec->size = BFD_ALIGN (sec->size, (bfd_size_type) (1 << power_of_two));
18573d8817e4Smiod if (power_of_two > bfd_get_section_alignment (htab->etab.dynobj, sec))
18583d8817e4Smiod {
18593d8817e4Smiod if (! bfd_set_section_alignment (htab->etab.dynobj, sec, power_of_two))
18603d8817e4Smiod return FALSE;
18613d8817e4Smiod }
18623d8817e4Smiod
18633d8817e4Smiod /* Define the symbol as being at this point in the section. */
18643d8817e4Smiod eh->root.u.def.section = sec;
18653d8817e4Smiod eh->root.u.def.value = sec->size;
18663d8817e4Smiod
18673d8817e4Smiod /* Increment the section size to make room for the symbol. */
18683d8817e4Smiod sec->size += eh->size;
18693d8817e4Smiod
18703d8817e4Smiod return TRUE;
18713d8817e4Smiod }
18723d8817e4Smiod
18733d8817e4Smiod /* Allocate space in the .plt for entries that won't have relocations.
18743d8817e4Smiod ie. plabel entries. */
18753d8817e4Smiod
18763d8817e4Smiod static bfd_boolean
allocate_plt_static(struct elf_link_hash_entry * eh,void * inf)18773d8817e4Smiod allocate_plt_static (struct elf_link_hash_entry *eh, void *inf)
18783d8817e4Smiod {
18793d8817e4Smiod struct bfd_link_info *info;
18803d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
18813d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
18823d8817e4Smiod asection *sec;
18833d8817e4Smiod
18843d8817e4Smiod if (eh->root.type == bfd_link_hash_indirect)
18853d8817e4Smiod return TRUE;
18863d8817e4Smiod
18873d8817e4Smiod if (eh->root.type == bfd_link_hash_warning)
18883d8817e4Smiod eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
18893d8817e4Smiod
18903d8817e4Smiod info = (struct bfd_link_info *) inf;
18913d8817e4Smiod hh = hppa_elf_hash_entry(eh);
18923d8817e4Smiod htab = hppa_link_hash_table (info);
18933d8817e4Smiod if (htab->etab.dynamic_sections_created
18943d8817e4Smiod && eh->plt.refcount > 0)
18953d8817e4Smiod {
18963d8817e4Smiod /* Make sure this symbol is output as a dynamic symbol.
18973d8817e4Smiod Undefined weak syms won't yet be marked as dynamic. */
18983d8817e4Smiod if (eh->dynindx == -1
18993d8817e4Smiod && !eh->forced_local
19003d8817e4Smiod && eh->type != STT_PARISC_MILLI)
19013d8817e4Smiod {
19023d8817e4Smiod if (! bfd_elf_link_record_dynamic_symbol (info, eh))
19033d8817e4Smiod return FALSE;
19043d8817e4Smiod }
19053d8817e4Smiod
19063d8817e4Smiod if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, eh))
19073d8817e4Smiod {
19083d8817e4Smiod /* Allocate these later. From this point on, h->plabel
19093d8817e4Smiod means that the plt entry is only used by a plabel.
19103d8817e4Smiod We'll be using a normal plt entry for this symbol, so
19113d8817e4Smiod clear the plabel indicator. */
19123d8817e4Smiod
19133d8817e4Smiod hh->plabel = 0;
19143d8817e4Smiod }
19153d8817e4Smiod else if (hh->plabel)
19163d8817e4Smiod {
19173d8817e4Smiod /* Make an entry in the .plt section for plabel references
19183d8817e4Smiod that won't have a .plt entry for other reasons. */
19193d8817e4Smiod sec = htab->splt;
19203d8817e4Smiod eh->plt.offset = sec->size;
19213d8817e4Smiod sec->size += PLT_ENTRY_SIZE;
19223d8817e4Smiod }
19233d8817e4Smiod else
19243d8817e4Smiod {
19253d8817e4Smiod /* No .plt entry needed. */
19263d8817e4Smiod eh->plt.offset = (bfd_vma) -1;
19273d8817e4Smiod eh->needs_plt = 0;
19283d8817e4Smiod }
19293d8817e4Smiod }
19303d8817e4Smiod else
19313d8817e4Smiod {
19323d8817e4Smiod eh->plt.offset = (bfd_vma) -1;
19333d8817e4Smiod eh->needs_plt = 0;
19343d8817e4Smiod }
19353d8817e4Smiod
19363d8817e4Smiod return TRUE;
19373d8817e4Smiod }
19383d8817e4Smiod
19393d8817e4Smiod /* Allocate space in .plt, .got and associated reloc sections for
19403d8817e4Smiod global syms. */
19413d8817e4Smiod
19423d8817e4Smiod static bfd_boolean
allocate_dynrelocs(struct elf_link_hash_entry * eh,void * inf)19433d8817e4Smiod allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
19443d8817e4Smiod {
19453d8817e4Smiod struct bfd_link_info *info;
19463d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
19473d8817e4Smiod asection *sec;
19483d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
19493d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
19503d8817e4Smiod
19513d8817e4Smiod if (eh->root.type == bfd_link_hash_indirect)
19523d8817e4Smiod return TRUE;
19533d8817e4Smiod
19543d8817e4Smiod if (eh->root.type == bfd_link_hash_warning)
19553d8817e4Smiod eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
19563d8817e4Smiod
19573d8817e4Smiod info = inf;
19583d8817e4Smiod htab = hppa_link_hash_table (info);
19593d8817e4Smiod hh = hppa_elf_hash_entry (eh);
19603d8817e4Smiod
19613d8817e4Smiod if (htab->etab.dynamic_sections_created
19623d8817e4Smiod && eh->plt.offset != (bfd_vma) -1
19633d8817e4Smiod && !hh->plabel
19643d8817e4Smiod && eh->plt.refcount > 0)
19653d8817e4Smiod {
19663d8817e4Smiod /* Make an entry in the .plt section. */
19673d8817e4Smiod sec = htab->splt;
19683d8817e4Smiod eh->plt.offset = sec->size;
19693d8817e4Smiod sec->size += PLT_ENTRY_SIZE;
19703d8817e4Smiod
19713d8817e4Smiod /* We also need to make an entry in the .rela.plt section. */
19723d8817e4Smiod htab->srelplt->size += sizeof (Elf32_External_Rela);
19733d8817e4Smiod htab->need_plt_stub = 1;
19743d8817e4Smiod }
19753d8817e4Smiod
19763d8817e4Smiod if (eh->got.refcount > 0)
19773d8817e4Smiod {
19783d8817e4Smiod /* Make sure this symbol is output as a dynamic symbol.
19793d8817e4Smiod Undefined weak syms won't yet be marked as dynamic. */
19803d8817e4Smiod if (eh->dynindx == -1
19813d8817e4Smiod && !eh->forced_local
19823d8817e4Smiod && eh->type != STT_PARISC_MILLI)
19833d8817e4Smiod {
19843d8817e4Smiod if (! bfd_elf_link_record_dynamic_symbol (info, eh))
19853d8817e4Smiod return FALSE;
19863d8817e4Smiod }
19873d8817e4Smiod
19883d8817e4Smiod sec = htab->sgot;
19893d8817e4Smiod eh->got.offset = sec->size;
19903d8817e4Smiod sec->size += GOT_ENTRY_SIZE;
19913d8817e4Smiod if (htab->etab.dynamic_sections_created
19923d8817e4Smiod && (info->shared
19933d8817e4Smiod || (eh->dynindx != -1
19943d8817e4Smiod && !eh->forced_local)))
19953d8817e4Smiod {
19963d8817e4Smiod htab->srelgot->size += sizeof (Elf32_External_Rela);
19973d8817e4Smiod }
19983d8817e4Smiod }
19993d8817e4Smiod else
20003d8817e4Smiod eh->got.offset = (bfd_vma) -1;
20013d8817e4Smiod
20023d8817e4Smiod if (hh->dyn_relocs == NULL)
20033d8817e4Smiod return TRUE;
20043d8817e4Smiod
20053d8817e4Smiod /* If this is a -Bsymbolic shared link, then we need to discard all
20063d8817e4Smiod space allocated for dynamic pc-relative relocs against symbols
20073d8817e4Smiod defined in a regular object. For the normal shared case, discard
20083d8817e4Smiod space for relocs that have become local due to symbol visibility
20093d8817e4Smiod changes. */
20103d8817e4Smiod if (info->shared)
20113d8817e4Smiod {
20123d8817e4Smiod #if RELATIVE_DYNRELOCS
20133d8817e4Smiod if (SYMBOL_CALLS_LOCAL (info, eh))
20143d8817e4Smiod {
20153d8817e4Smiod struct elf32_hppa_dyn_reloc_entry **hdh_pp;
20163d8817e4Smiod
20173d8817e4Smiod for (hdh_pp = &hh->dyn_relocs; (hdh_p = *hdh_pp) != NULL; )
20183d8817e4Smiod {
20193d8817e4Smiod hdh_p->count -= hdh_p->relative_count;
20203d8817e4Smiod hdh_p->relative_count = 0;
20213d8817e4Smiod if (hdh_p->count == 0)
20223d8817e4Smiod *hdh_pp = hdh_p->hdh_next;
20233d8817e4Smiod else
20243d8817e4Smiod hdh_pp = &hdh_p->hdh_next;
20253d8817e4Smiod }
20263d8817e4Smiod }
20273d8817e4Smiod #endif
20283d8817e4Smiod
20293d8817e4Smiod /* Also discard relocs on undefined weak syms with non-default
20303d8817e4Smiod visibility. */
20313d8817e4Smiod if (hh->dyn_relocs != NULL
20323d8817e4Smiod && eh->root.type == bfd_link_hash_undefweak)
20333d8817e4Smiod {
20343d8817e4Smiod if (ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
20353d8817e4Smiod hh->dyn_relocs = NULL;
20363d8817e4Smiod
20373d8817e4Smiod /* Make sure undefined weak symbols are output as a dynamic
20383d8817e4Smiod symbol in PIEs. */
20393d8817e4Smiod else if (eh->dynindx == -1
20403d8817e4Smiod && !eh->forced_local)
20413d8817e4Smiod {
20423d8817e4Smiod if (! bfd_elf_link_record_dynamic_symbol (info, eh))
20433d8817e4Smiod return FALSE;
20443d8817e4Smiod }
20453d8817e4Smiod }
20463d8817e4Smiod }
20473d8817e4Smiod else
20483d8817e4Smiod {
20493d8817e4Smiod /* For the non-shared case, discard space for relocs against
20503d8817e4Smiod symbols which turn out to need copy relocs or are not
20513d8817e4Smiod dynamic. */
20523d8817e4Smiod
20533d8817e4Smiod if (!eh->non_got_ref
20543d8817e4Smiod && ((ELIMINATE_COPY_RELOCS
20553d8817e4Smiod && eh->def_dynamic
20563d8817e4Smiod && !eh->def_regular)
20573d8817e4Smiod || (htab->etab.dynamic_sections_created
20583d8817e4Smiod && (eh->root.type == bfd_link_hash_undefweak
20593d8817e4Smiod || eh->root.type == bfd_link_hash_undefined))))
20603d8817e4Smiod {
20613d8817e4Smiod /* Make sure this symbol is output as a dynamic symbol.
20623d8817e4Smiod Undefined weak syms won't yet be marked as dynamic. */
20633d8817e4Smiod if (eh->dynindx == -1
20643d8817e4Smiod && !eh->forced_local
20653d8817e4Smiod && eh->type != STT_PARISC_MILLI)
20663d8817e4Smiod {
20673d8817e4Smiod if (! bfd_elf_link_record_dynamic_symbol (info, eh))
20683d8817e4Smiod return FALSE;
20693d8817e4Smiod }
20703d8817e4Smiod
20713d8817e4Smiod /* If that succeeded, we know we'll be keeping all the
20723d8817e4Smiod relocs. */
20733d8817e4Smiod if (eh->dynindx != -1)
20743d8817e4Smiod goto keep;
20753d8817e4Smiod }
20763d8817e4Smiod
20773d8817e4Smiod hh->dyn_relocs = NULL;
20783d8817e4Smiod return TRUE;
20793d8817e4Smiod
20803d8817e4Smiod keep: ;
20813d8817e4Smiod }
20823d8817e4Smiod
20833d8817e4Smiod /* Finally, allocate space. */
20843d8817e4Smiod for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next)
20853d8817e4Smiod {
20863d8817e4Smiod asection *sreloc = elf_section_data (hdh_p->sec)->sreloc;
20873d8817e4Smiod sreloc->size += hdh_p->count * sizeof (Elf32_External_Rela);
20883d8817e4Smiod }
20893d8817e4Smiod
20903d8817e4Smiod return TRUE;
20913d8817e4Smiod }
20923d8817e4Smiod
20933d8817e4Smiod /* This function is called via elf_link_hash_traverse to force
20943d8817e4Smiod millicode symbols local so they do not end up as globals in the
20953d8817e4Smiod dynamic symbol table. We ought to be able to do this in
20963d8817e4Smiod adjust_dynamic_symbol, but our adjust_dynamic_symbol is not called
20973d8817e4Smiod for all dynamic symbols. Arguably, this is a bug in
20983d8817e4Smiod elf_adjust_dynamic_symbol. */
20993d8817e4Smiod
21003d8817e4Smiod static bfd_boolean
clobber_millicode_symbols(struct elf_link_hash_entry * eh,struct bfd_link_info * info)21013d8817e4Smiod clobber_millicode_symbols (struct elf_link_hash_entry *eh,
21023d8817e4Smiod struct bfd_link_info *info)
21033d8817e4Smiod {
21043d8817e4Smiod if (eh->root.type == bfd_link_hash_warning)
21053d8817e4Smiod eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
21063d8817e4Smiod
21073d8817e4Smiod if (eh->type == STT_PARISC_MILLI
21083d8817e4Smiod && !eh->forced_local)
21093d8817e4Smiod {
21103d8817e4Smiod elf32_hppa_hide_symbol (info, eh, TRUE);
21113d8817e4Smiod }
21123d8817e4Smiod return TRUE;
21133d8817e4Smiod }
21143d8817e4Smiod
21153d8817e4Smiod /* Find any dynamic relocs that apply to read-only sections. */
21163d8817e4Smiod
21173d8817e4Smiod static bfd_boolean
readonly_dynrelocs(struct elf_link_hash_entry * eh,void * inf)21183d8817e4Smiod readonly_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
21193d8817e4Smiod {
21203d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
21213d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
21223d8817e4Smiod
21233d8817e4Smiod if (eh->root.type == bfd_link_hash_warning)
21243d8817e4Smiod eh = (struct elf_link_hash_entry *) eh->root.u.i.link;
21253d8817e4Smiod
21263d8817e4Smiod hh = hppa_elf_hash_entry (eh);
21273d8817e4Smiod for (hdh_p = hh->dyn_relocs; hdh_p != NULL; hdh_p = hdh_p->hdh_next)
21283d8817e4Smiod {
21293d8817e4Smiod asection *sec = hdh_p->sec->output_section;
21303d8817e4Smiod
21313d8817e4Smiod if (sec != NULL && (sec->flags & SEC_READONLY) != 0)
21323d8817e4Smiod {
21333d8817e4Smiod struct bfd_link_info *info = inf;
21343d8817e4Smiod
21353d8817e4Smiod info->flags |= DF_TEXTREL;
21363d8817e4Smiod
21373d8817e4Smiod /* Not an error, just cut short the traversal. */
21383d8817e4Smiod return FALSE;
21393d8817e4Smiod }
21403d8817e4Smiod }
21413d8817e4Smiod return TRUE;
21423d8817e4Smiod }
21433d8817e4Smiod
21443d8817e4Smiod /* Set the sizes of the dynamic sections. */
21453d8817e4Smiod
21463d8817e4Smiod static bfd_boolean
elf32_hppa_size_dynamic_sections(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info)21473d8817e4Smiod elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
21483d8817e4Smiod struct bfd_link_info *info)
21493d8817e4Smiod {
21503d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
21513d8817e4Smiod bfd *dynobj;
21523d8817e4Smiod bfd *ibfd;
21533d8817e4Smiod asection *sec;
21543d8817e4Smiod bfd_boolean relocs;
21553d8817e4Smiod
21563d8817e4Smiod htab = hppa_link_hash_table (info);
21573d8817e4Smiod dynobj = htab->etab.dynobj;
21583d8817e4Smiod if (dynobj == NULL)
21593d8817e4Smiod abort ();
21603d8817e4Smiod
21613d8817e4Smiod if (htab->etab.dynamic_sections_created)
21623d8817e4Smiod {
21633d8817e4Smiod /* Set the contents of the .interp section to the interpreter. */
2164ebca08eeSkettenis if (info->executable && !info->static_link)
21653d8817e4Smiod {
21663d8817e4Smiod sec = bfd_get_section_by_name (dynobj, ".interp");
21673d8817e4Smiod if (sec == NULL)
21683d8817e4Smiod abort ();
21693d8817e4Smiod sec->size = sizeof ELF_DYNAMIC_INTERPRETER;
21703d8817e4Smiod sec->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
21713d8817e4Smiod }
21723d8817e4Smiod
21733d8817e4Smiod /* Force millicode symbols local. */
21743d8817e4Smiod elf_link_hash_traverse (&htab->etab,
21753d8817e4Smiod clobber_millicode_symbols,
21763d8817e4Smiod info);
21773d8817e4Smiod }
21783d8817e4Smiod
21793d8817e4Smiod /* Set up .got and .plt offsets for local syms, and space for local
21803d8817e4Smiod dynamic relocs. */
21813d8817e4Smiod for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
21823d8817e4Smiod {
21833d8817e4Smiod bfd_signed_vma *local_got;
21843d8817e4Smiod bfd_signed_vma *end_local_got;
21853d8817e4Smiod bfd_signed_vma *local_plt;
21863d8817e4Smiod bfd_signed_vma *end_local_plt;
21873d8817e4Smiod bfd_size_type locsymcount;
21883d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
21893d8817e4Smiod asection *srel;
21903d8817e4Smiod
21913d8817e4Smiod if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
21923d8817e4Smiod continue;
21933d8817e4Smiod
21943d8817e4Smiod for (sec = ibfd->sections; sec != NULL; sec = sec->next)
21953d8817e4Smiod {
21963d8817e4Smiod struct elf32_hppa_dyn_reloc_entry *hdh_p;
21973d8817e4Smiod
21983d8817e4Smiod for (hdh_p = ((struct elf32_hppa_dyn_reloc_entry *)
21993d8817e4Smiod elf_section_data (sec)->local_dynrel);
22003d8817e4Smiod hdh_p != NULL;
22013d8817e4Smiod hdh_p = hdh_p->hdh_next)
22023d8817e4Smiod {
22033d8817e4Smiod if (!bfd_is_abs_section (hdh_p->sec)
22043d8817e4Smiod && bfd_is_abs_section (hdh_p->sec->output_section))
22053d8817e4Smiod {
22063d8817e4Smiod /* Input section has been discarded, either because
22073d8817e4Smiod it is a copy of a linkonce section or due to
22083d8817e4Smiod linker script /DISCARD/, so we'll be discarding
22093d8817e4Smiod the relocs too. */
22103d8817e4Smiod }
22113d8817e4Smiod else if (hdh_p->count != 0)
22123d8817e4Smiod {
22133d8817e4Smiod srel = elf_section_data (hdh_p->sec)->sreloc;
22143d8817e4Smiod srel->size += hdh_p->count * sizeof (Elf32_External_Rela);
22153d8817e4Smiod if ((hdh_p->sec->output_section->flags & SEC_READONLY) != 0)
22163d8817e4Smiod info->flags |= DF_TEXTREL;
22173d8817e4Smiod }
22183d8817e4Smiod }
22193d8817e4Smiod }
22203d8817e4Smiod
22213d8817e4Smiod local_got = elf_local_got_refcounts (ibfd);
22223d8817e4Smiod if (!local_got)
22233d8817e4Smiod continue;
22243d8817e4Smiod
22253d8817e4Smiod symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
22263d8817e4Smiod locsymcount = symtab_hdr->sh_info;
22273d8817e4Smiod end_local_got = local_got + locsymcount;
22283d8817e4Smiod sec = htab->sgot;
22293d8817e4Smiod srel = htab->srelgot;
22303d8817e4Smiod for (; local_got < end_local_got; ++local_got)
22313d8817e4Smiod {
22323d8817e4Smiod if (*local_got > 0)
22333d8817e4Smiod {
22343d8817e4Smiod *local_got = sec->size;
22353d8817e4Smiod sec->size += GOT_ENTRY_SIZE;
22363d8817e4Smiod if (info->shared)
22373d8817e4Smiod srel->size += sizeof (Elf32_External_Rela);
22383d8817e4Smiod }
22393d8817e4Smiod else
22403d8817e4Smiod *local_got = (bfd_vma) -1;
22413d8817e4Smiod }
22423d8817e4Smiod
22433d8817e4Smiod local_plt = end_local_got;
22443d8817e4Smiod end_local_plt = local_plt + locsymcount;
22453d8817e4Smiod if (! htab->etab.dynamic_sections_created)
22463d8817e4Smiod {
22473d8817e4Smiod /* Won't be used, but be safe. */
22483d8817e4Smiod for (; local_plt < end_local_plt; ++local_plt)
22493d8817e4Smiod *local_plt = (bfd_vma) -1;
22503d8817e4Smiod }
22513d8817e4Smiod else
22523d8817e4Smiod {
22533d8817e4Smiod sec = htab->splt;
22543d8817e4Smiod srel = htab->srelplt;
22553d8817e4Smiod for (; local_plt < end_local_plt; ++local_plt)
22563d8817e4Smiod {
22573d8817e4Smiod if (*local_plt > 0)
22583d8817e4Smiod {
22593d8817e4Smiod *local_plt = sec->size;
22603d8817e4Smiod sec->size += PLT_ENTRY_SIZE;
22613d8817e4Smiod if (info->shared)
22623d8817e4Smiod srel->size += sizeof (Elf32_External_Rela);
22633d8817e4Smiod }
22643d8817e4Smiod else
22653d8817e4Smiod *local_plt = (bfd_vma) -1;
22663d8817e4Smiod }
22673d8817e4Smiod }
22683d8817e4Smiod }
22693d8817e4Smiod
22703d8817e4Smiod /* Do all the .plt entries without relocs first. The dynamic linker
22713d8817e4Smiod uses the last .plt reloc to find the end of the .plt (and hence
22723d8817e4Smiod the start of the .got) for lazy linking. */
22733d8817e4Smiod elf_link_hash_traverse (&htab->etab, allocate_plt_static, info);
22743d8817e4Smiod
22753d8817e4Smiod /* Allocate global sym .plt and .got entries, and space for global
22763d8817e4Smiod sym dynamic relocs. */
22773d8817e4Smiod elf_link_hash_traverse (&htab->etab, allocate_dynrelocs, info);
22783d8817e4Smiod
22793d8817e4Smiod /* The check_relocs and adjust_dynamic_symbol entry points have
22803d8817e4Smiod determined the sizes of the various dynamic sections. Allocate
22813d8817e4Smiod memory for them. */
22823d8817e4Smiod relocs = FALSE;
22833d8817e4Smiod for (sec = dynobj->sections; sec != NULL; sec = sec->next)
22843d8817e4Smiod {
22853d8817e4Smiod if ((sec->flags & SEC_LINKER_CREATED) == 0)
22863d8817e4Smiod continue;
22873d8817e4Smiod
22883d8817e4Smiod if (sec == htab->splt)
22893d8817e4Smiod {
22903d8817e4Smiod if (htab->need_plt_stub)
22913d8817e4Smiod {
22923d8817e4Smiod /* Make space for the plt stub at the end of the .plt
22933d8817e4Smiod section. We want this stub right at the end, up
22943d8817e4Smiod against the .got section. */
22953d8817e4Smiod int gotalign = bfd_section_alignment (dynobj, htab->sgot);
22963d8817e4Smiod int pltalign = bfd_section_alignment (dynobj, sec);
22973d8817e4Smiod bfd_size_type mask;
22983d8817e4Smiod
22993d8817e4Smiod if (gotalign > pltalign)
23003d8817e4Smiod bfd_set_section_alignment (dynobj, sec, gotalign);
23013d8817e4Smiod mask = ((bfd_size_type) 1 << gotalign) - 1;
23023d8817e4Smiod sec->size = (sec->size + sizeof (plt_stub) + mask) & ~mask;
23033d8817e4Smiod }
23043d8817e4Smiod }
23053d8817e4Smiod else if (sec == htab->sgot
23063d8817e4Smiod || sec == htab->sdynbss)
23073d8817e4Smiod ;
23083d8817e4Smiod else if (strncmp (bfd_get_section_name (dynobj, sec), ".rela", 5) == 0)
23093d8817e4Smiod {
23103d8817e4Smiod if (sec->size != 0)
23113d8817e4Smiod {
23123d8817e4Smiod /* Remember whether there are any reloc sections other
23133d8817e4Smiod than .rela.plt. */
23143d8817e4Smiod if (sec != htab->srelplt)
23153d8817e4Smiod relocs = TRUE;
23163d8817e4Smiod
23173d8817e4Smiod /* We use the reloc_count field as a counter if we need
23183d8817e4Smiod to copy relocs into the output file. */
23193d8817e4Smiod sec->reloc_count = 0;
23203d8817e4Smiod }
23213d8817e4Smiod }
23223d8817e4Smiod else
23233d8817e4Smiod {
23243d8817e4Smiod /* It's not one of our sections, so don't allocate space. */
23253d8817e4Smiod continue;
23263d8817e4Smiod }
23273d8817e4Smiod
23283d8817e4Smiod if (sec->size == 0)
23293d8817e4Smiod {
23303d8817e4Smiod /* If we don't need this section, strip it from the
23313d8817e4Smiod output file. This is mostly to handle .rela.bss and
23323d8817e4Smiod .rela.plt. We must create both sections in
23333d8817e4Smiod create_dynamic_sections, because they must be created
23343d8817e4Smiod before the linker maps input sections to output
23353d8817e4Smiod sections. The linker does that before
23363d8817e4Smiod adjust_dynamic_symbol is called, and it is that
23373d8817e4Smiod function which decides whether anything needs to go
23383d8817e4Smiod into these sections. */
23393d8817e4Smiod sec->flags |= SEC_EXCLUDE;
23403d8817e4Smiod continue;
23413d8817e4Smiod }
23423d8817e4Smiod
23433d8817e4Smiod if ((sec->flags & SEC_HAS_CONTENTS) == 0)
23443d8817e4Smiod continue;
23453d8817e4Smiod
23463d8817e4Smiod /* Allocate memory for the section contents. Zero it, because
23473d8817e4Smiod we may not fill in all the reloc sections. */
23483d8817e4Smiod sec->contents = bfd_zalloc (dynobj, sec->size);
23493d8817e4Smiod if (sec->contents == NULL)
23503d8817e4Smiod return FALSE;
23513d8817e4Smiod }
23523d8817e4Smiod
23533d8817e4Smiod if (htab->etab.dynamic_sections_created)
23543d8817e4Smiod {
23553d8817e4Smiod /* Like IA-64 and HPPA64, always create a DT_PLTGOT. It
23563d8817e4Smiod actually has nothing to do with the PLT, it is how we
23573d8817e4Smiod communicate the LTP value of a load module to the dynamic
23583d8817e4Smiod linker. */
23593d8817e4Smiod #define add_dynamic_entry(TAG, VAL) \
23603d8817e4Smiod _bfd_elf_add_dynamic_entry (info, TAG, VAL)
23613d8817e4Smiod
23623d8817e4Smiod if (!add_dynamic_entry (DT_PLTGOT, 0))
23633d8817e4Smiod return FALSE;
23643d8817e4Smiod
23653d8817e4Smiod /* Add some entries to the .dynamic section. We fill in the
23663d8817e4Smiod values later, in elf32_hppa_finish_dynamic_sections, but we
23673d8817e4Smiod must add the entries now so that we get the correct size for
23683d8817e4Smiod the .dynamic section. The DT_DEBUG entry is filled in by the
23693d8817e4Smiod dynamic linker and used by the debugger. */
23703d8817e4Smiod if (info->executable)
23713d8817e4Smiod {
23723d8817e4Smiod if (!add_dynamic_entry (DT_DEBUG, 0))
23733d8817e4Smiod return FALSE;
23743d8817e4Smiod }
23753d8817e4Smiod
23763d8817e4Smiod if (htab->srelplt->size != 0)
23773d8817e4Smiod {
23783d8817e4Smiod if (!add_dynamic_entry (DT_PLTRELSZ, 0)
23793d8817e4Smiod || !add_dynamic_entry (DT_PLTREL, DT_RELA)
23803d8817e4Smiod || !add_dynamic_entry (DT_JMPREL, 0))
23813d8817e4Smiod return FALSE;
23823d8817e4Smiod }
23833d8817e4Smiod
23843d8817e4Smiod if (relocs)
23853d8817e4Smiod {
23863d8817e4Smiod if (!add_dynamic_entry (DT_RELA, 0)
23873d8817e4Smiod || !add_dynamic_entry (DT_RELASZ, 0)
23883d8817e4Smiod || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
23893d8817e4Smiod return FALSE;
23903d8817e4Smiod
23913d8817e4Smiod /* If any dynamic relocs apply to a read-only section,
23923d8817e4Smiod then we need a DT_TEXTREL entry. */
23933d8817e4Smiod if ((info->flags & DF_TEXTREL) == 0)
23943d8817e4Smiod elf_link_hash_traverse (&htab->etab, readonly_dynrelocs, info);
23953d8817e4Smiod
23963d8817e4Smiod if ((info->flags & DF_TEXTREL) != 0)
23973d8817e4Smiod {
23983d8817e4Smiod if (!add_dynamic_entry (DT_TEXTREL, 0))
23993d8817e4Smiod return FALSE;
24003d8817e4Smiod }
24013d8817e4Smiod }
24023d8817e4Smiod }
24033d8817e4Smiod #undef add_dynamic_entry
24043d8817e4Smiod
24053d8817e4Smiod return TRUE;
24063d8817e4Smiod }
24073d8817e4Smiod
24083d8817e4Smiod /* External entry points for sizing and building linker stubs. */
24093d8817e4Smiod
24103d8817e4Smiod /* Set up various things so that we can make a list of input sections
24113d8817e4Smiod for each output section included in the link. Returns -1 on error,
24123d8817e4Smiod 0 when no stubs will be needed, and 1 on success. */
24133d8817e4Smiod
24143d8817e4Smiod int
elf32_hppa_setup_section_lists(bfd * output_bfd,struct bfd_link_info * info)24153d8817e4Smiod elf32_hppa_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
24163d8817e4Smiod {
24173d8817e4Smiod bfd *input_bfd;
24183d8817e4Smiod unsigned int bfd_count;
24193d8817e4Smiod int top_id, top_index;
24203d8817e4Smiod asection *section;
24213d8817e4Smiod asection **input_list, **list;
24223d8817e4Smiod bfd_size_type amt;
24233d8817e4Smiod struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
24243d8817e4Smiod
24253d8817e4Smiod /* Count the number of input BFDs and find the top input section id. */
24263d8817e4Smiod for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
24273d8817e4Smiod input_bfd != NULL;
24283d8817e4Smiod input_bfd = input_bfd->link_next)
24293d8817e4Smiod {
24303d8817e4Smiod bfd_count += 1;
24313d8817e4Smiod for (section = input_bfd->sections;
24323d8817e4Smiod section != NULL;
24333d8817e4Smiod section = section->next)
24343d8817e4Smiod {
24353d8817e4Smiod if (top_id < section->id)
24363d8817e4Smiod top_id = section->id;
24373d8817e4Smiod }
24383d8817e4Smiod }
24393d8817e4Smiod htab->bfd_count = bfd_count;
24403d8817e4Smiod
24413d8817e4Smiod amt = sizeof (struct map_stub) * (top_id + 1);
24423d8817e4Smiod htab->stub_group = bfd_zmalloc (amt);
24433d8817e4Smiod if (htab->stub_group == NULL)
24443d8817e4Smiod return -1;
24453d8817e4Smiod
24463d8817e4Smiod /* We can't use output_bfd->section_count here to find the top output
24473d8817e4Smiod section index as some sections may have been removed, and
24483d8817e4Smiod strip_excluded_output_sections doesn't renumber the indices. */
24493d8817e4Smiod for (section = output_bfd->sections, top_index = 0;
24503d8817e4Smiod section != NULL;
24513d8817e4Smiod section = section->next)
24523d8817e4Smiod {
24533d8817e4Smiod if (top_index < section->index)
24543d8817e4Smiod top_index = section->index;
24553d8817e4Smiod }
24563d8817e4Smiod
24573d8817e4Smiod htab->top_index = top_index;
24583d8817e4Smiod amt = sizeof (asection *) * (top_index + 1);
24593d8817e4Smiod input_list = bfd_malloc (amt);
24603d8817e4Smiod htab->input_list = input_list;
24613d8817e4Smiod if (input_list == NULL)
24623d8817e4Smiod return -1;
24633d8817e4Smiod
24643d8817e4Smiod /* For sections we aren't interested in, mark their entries with a
24653d8817e4Smiod value we can check later. */
24663d8817e4Smiod list = input_list + top_index;
24673d8817e4Smiod do
24683d8817e4Smiod *list = bfd_abs_section_ptr;
24693d8817e4Smiod while (list-- != input_list);
24703d8817e4Smiod
24713d8817e4Smiod for (section = output_bfd->sections;
24723d8817e4Smiod section != NULL;
24733d8817e4Smiod section = section->next)
24743d8817e4Smiod {
24753d8817e4Smiod if ((section->flags & SEC_CODE) != 0)
24763d8817e4Smiod input_list[section->index] = NULL;
24773d8817e4Smiod }
24783d8817e4Smiod
24793d8817e4Smiod return 1;
24803d8817e4Smiod }
24813d8817e4Smiod
24823d8817e4Smiod /* The linker repeatedly calls this function for each input section,
24833d8817e4Smiod in the order that input sections are linked into output sections.
24843d8817e4Smiod Build lists of input sections to determine groupings between which
24853d8817e4Smiod we may insert linker stubs. */
24863d8817e4Smiod
24873d8817e4Smiod void
elf32_hppa_next_input_section(struct bfd_link_info * info,asection * isec)24883d8817e4Smiod elf32_hppa_next_input_section (struct bfd_link_info *info, asection *isec)
24893d8817e4Smiod {
24903d8817e4Smiod struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
24913d8817e4Smiod
24923d8817e4Smiod if (isec->output_section->index <= htab->top_index)
24933d8817e4Smiod {
24943d8817e4Smiod asection **list = htab->input_list + isec->output_section->index;
24953d8817e4Smiod if (*list != bfd_abs_section_ptr)
24963d8817e4Smiod {
24973d8817e4Smiod /* Steal the link_sec pointer for our list. */
24983d8817e4Smiod #define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
24993d8817e4Smiod /* This happens to make the list in reverse order,
25003d8817e4Smiod which is what we want. */
25013d8817e4Smiod PREV_SEC (isec) = *list;
25023d8817e4Smiod *list = isec;
25033d8817e4Smiod }
25043d8817e4Smiod }
25053d8817e4Smiod }
25063d8817e4Smiod
25073d8817e4Smiod /* See whether we can group stub sections together. Grouping stub
25083d8817e4Smiod sections may result in fewer stubs. More importantly, we need to
25093d8817e4Smiod put all .init* and .fini* stubs at the beginning of the .init or
25103d8817e4Smiod .fini output sections respectively, because glibc splits the
25113d8817e4Smiod _init and _fini functions into multiple parts. Putting a stub in
25123d8817e4Smiod the middle of a function is not a good idea. */
25133d8817e4Smiod
25143d8817e4Smiod static void
group_sections(struct elf32_hppa_link_hash_table * htab,bfd_size_type stub_group_size,bfd_boolean stubs_always_before_branch)25153d8817e4Smiod group_sections (struct elf32_hppa_link_hash_table *htab,
25163d8817e4Smiod bfd_size_type stub_group_size,
25173d8817e4Smiod bfd_boolean stubs_always_before_branch)
25183d8817e4Smiod {
25193d8817e4Smiod asection **list = htab->input_list + htab->top_index;
25203d8817e4Smiod do
25213d8817e4Smiod {
25223d8817e4Smiod asection *tail = *list;
25233d8817e4Smiod if (tail == bfd_abs_section_ptr)
25243d8817e4Smiod continue;
25253d8817e4Smiod while (tail != NULL)
25263d8817e4Smiod {
25273d8817e4Smiod asection *curr;
25283d8817e4Smiod asection *prev;
25293d8817e4Smiod bfd_size_type total;
25303d8817e4Smiod bfd_boolean big_sec;
25313d8817e4Smiod
25323d8817e4Smiod curr = tail;
25333d8817e4Smiod total = tail->size;
25343d8817e4Smiod big_sec = total >= stub_group_size;
25353d8817e4Smiod
25363d8817e4Smiod while ((prev = PREV_SEC (curr)) != NULL
25373d8817e4Smiod && ((total += curr->output_offset - prev->output_offset)
25383d8817e4Smiod < stub_group_size))
25393d8817e4Smiod curr = prev;
25403d8817e4Smiod
25413d8817e4Smiod /* OK, the size from the start of CURR to the end is less
25423d8817e4Smiod than 240000 bytes and thus can be handled by one stub
25433d8817e4Smiod section. (or the tail section is itself larger than
25443d8817e4Smiod 240000 bytes, in which case we may be toast.)
25453d8817e4Smiod We should really be keeping track of the total size of
25463d8817e4Smiod stubs added here, as stubs contribute to the final output
25473d8817e4Smiod section size. That's a little tricky, and this way will
25483d8817e4Smiod only break if stubs added total more than 22144 bytes, or
25493d8817e4Smiod 2768 long branch stubs. It seems unlikely for more than
25503d8817e4Smiod 2768 different functions to be called, especially from
25513d8817e4Smiod code only 240000 bytes long. This limit used to be
25523d8817e4Smiod 250000, but c++ code tends to generate lots of little
25533d8817e4Smiod functions, and sometimes violated the assumption. */
25543d8817e4Smiod do
25553d8817e4Smiod {
25563d8817e4Smiod prev = PREV_SEC (tail);
25573d8817e4Smiod /* Set up this stub group. */
25583d8817e4Smiod htab->stub_group[tail->id].link_sec = curr;
25593d8817e4Smiod }
25603d8817e4Smiod while (tail != curr && (tail = prev) != NULL);
25613d8817e4Smiod
25623d8817e4Smiod /* But wait, there's more! Input sections up to 240000
25633d8817e4Smiod bytes before the stub section can be handled by it too.
25643d8817e4Smiod Don't do this if we have a really large section after the
25653d8817e4Smiod stubs, as adding more stubs increases the chance that
25663d8817e4Smiod branches may not reach into the stub section. */
25673d8817e4Smiod if (!stubs_always_before_branch && !big_sec)
25683d8817e4Smiod {
25693d8817e4Smiod total = 0;
25703d8817e4Smiod while (prev != NULL
25713d8817e4Smiod && ((total += tail->output_offset - prev->output_offset)
25723d8817e4Smiod < stub_group_size))
25733d8817e4Smiod {
25743d8817e4Smiod tail = prev;
25753d8817e4Smiod prev = PREV_SEC (tail);
25763d8817e4Smiod htab->stub_group[tail->id].link_sec = curr;
25773d8817e4Smiod }
25783d8817e4Smiod }
25793d8817e4Smiod tail = prev;
25803d8817e4Smiod }
25813d8817e4Smiod }
25823d8817e4Smiod while (list-- != htab->input_list);
25833d8817e4Smiod free (htab->input_list);
25843d8817e4Smiod #undef PREV_SEC
25853d8817e4Smiod }
25863d8817e4Smiod
25873d8817e4Smiod /* Read in all local syms for all input bfds, and create hash entries
25883d8817e4Smiod for export stubs if we are building a multi-subspace shared lib.
25893d8817e4Smiod Returns -1 on error, 1 if export stubs created, 0 otherwise. */
25903d8817e4Smiod
25913d8817e4Smiod static int
get_local_syms(bfd * output_bfd,bfd * input_bfd,struct bfd_link_info * info)25923d8817e4Smiod get_local_syms (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info)
25933d8817e4Smiod {
25943d8817e4Smiod unsigned int bfd_indx;
25953d8817e4Smiod Elf_Internal_Sym *local_syms, **all_local_syms;
25963d8817e4Smiod int stub_changed = 0;
25973d8817e4Smiod struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
25983d8817e4Smiod
25993d8817e4Smiod /* We want to read in symbol extension records only once. To do this
26003d8817e4Smiod we need to read in the local symbols in parallel and save them for
26013d8817e4Smiod later use; so hold pointers to the local symbols in an array. */
26023d8817e4Smiod bfd_size_type amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
26033d8817e4Smiod all_local_syms = bfd_zmalloc (amt);
26043d8817e4Smiod htab->all_local_syms = all_local_syms;
26053d8817e4Smiod if (all_local_syms == NULL)
26063d8817e4Smiod return -1;
26073d8817e4Smiod
26083d8817e4Smiod /* Walk over all the input BFDs, swapping in local symbols.
26093d8817e4Smiod If we are creating a shared library, create hash entries for the
26103d8817e4Smiod export stubs. */
26113d8817e4Smiod for (bfd_indx = 0;
26123d8817e4Smiod input_bfd != NULL;
26133d8817e4Smiod input_bfd = input_bfd->link_next, bfd_indx++)
26143d8817e4Smiod {
26153d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
26163d8817e4Smiod
26173d8817e4Smiod /* We'll need the symbol table in a second. */
26183d8817e4Smiod symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
26193d8817e4Smiod if (symtab_hdr->sh_info == 0)
26203d8817e4Smiod continue;
26213d8817e4Smiod
26223d8817e4Smiod /* We need an array of the local symbols attached to the input bfd. */
26233d8817e4Smiod local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
26243d8817e4Smiod if (local_syms == NULL)
26253d8817e4Smiod {
26263d8817e4Smiod local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
26273d8817e4Smiod symtab_hdr->sh_info, 0,
26283d8817e4Smiod NULL, NULL, NULL);
26293d8817e4Smiod /* Cache them for elf_link_input_bfd. */
26303d8817e4Smiod symtab_hdr->contents = (unsigned char *) local_syms;
26313d8817e4Smiod }
26323d8817e4Smiod if (local_syms == NULL)
26333d8817e4Smiod return -1;
26343d8817e4Smiod
26353d8817e4Smiod all_local_syms[bfd_indx] = local_syms;
26363d8817e4Smiod
26373d8817e4Smiod if (info->shared && htab->multi_subspace)
26383d8817e4Smiod {
26393d8817e4Smiod struct elf_link_hash_entry **eh_syms;
26403d8817e4Smiod struct elf_link_hash_entry **eh_symend;
26413d8817e4Smiod unsigned int symcount;
26423d8817e4Smiod
26433d8817e4Smiod symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
26443d8817e4Smiod - symtab_hdr->sh_info);
26453d8817e4Smiod eh_syms = (struct elf_link_hash_entry **) elf_sym_hashes (input_bfd);
26463d8817e4Smiod eh_symend = (struct elf_link_hash_entry **) (eh_syms + symcount);
26473d8817e4Smiod
26483d8817e4Smiod /* Look through the global syms for functions; We need to
26493d8817e4Smiod build export stubs for all globally visible functions. */
26503d8817e4Smiod for (; eh_syms < eh_symend; eh_syms++)
26513d8817e4Smiod {
26523d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
26533d8817e4Smiod
26543d8817e4Smiod hh = hppa_elf_hash_entry (*eh_syms);
26553d8817e4Smiod
26563d8817e4Smiod while (hh->eh.root.type == bfd_link_hash_indirect
26573d8817e4Smiod || hh->eh.root.type == bfd_link_hash_warning)
26583d8817e4Smiod hh = hppa_elf_hash_entry (hh->eh.root.u.i.link);
26593d8817e4Smiod
26603d8817e4Smiod /* At this point in the link, undefined syms have been
26613d8817e4Smiod resolved, so we need to check that the symbol was
26623d8817e4Smiod defined in this BFD. */
26633d8817e4Smiod if ((hh->eh.root.type == bfd_link_hash_defined
26643d8817e4Smiod || hh->eh.root.type == bfd_link_hash_defweak)
26653d8817e4Smiod && hh->eh.type == STT_FUNC
26663d8817e4Smiod && hh->eh.root.u.def.section->output_section != NULL
26673d8817e4Smiod && (hh->eh.root.u.def.section->output_section->owner
26683d8817e4Smiod == output_bfd)
26693d8817e4Smiod && hh->eh.root.u.def.section->owner == input_bfd
26703d8817e4Smiod && hh->eh.def_regular
26713d8817e4Smiod && !hh->eh.forced_local
26723d8817e4Smiod && ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT)
26733d8817e4Smiod {
26743d8817e4Smiod asection *sec;
26753d8817e4Smiod const char *stub_name;
26763d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh;
26773d8817e4Smiod
26783d8817e4Smiod sec = hh->eh.root.u.def.section;
26793d8817e4Smiod stub_name = hh->eh.root.root.string;
26803d8817e4Smiod hsh = hppa_stub_hash_lookup (&htab->bstab,
26813d8817e4Smiod stub_name,
26823d8817e4Smiod FALSE, FALSE);
26833d8817e4Smiod if (hsh == NULL)
26843d8817e4Smiod {
26853d8817e4Smiod hsh = hppa_add_stub (stub_name, sec, htab);
26863d8817e4Smiod if (!hsh)
26873d8817e4Smiod return -1;
26883d8817e4Smiod
26893d8817e4Smiod hsh->target_value = hh->eh.root.u.def.value;
26903d8817e4Smiod hsh->target_section = hh->eh.root.u.def.section;
26913d8817e4Smiod hsh->stub_type = hppa_stub_export;
26923d8817e4Smiod hsh->hh = hh;
26933d8817e4Smiod stub_changed = 1;
26943d8817e4Smiod }
26953d8817e4Smiod else
26963d8817e4Smiod {
26973d8817e4Smiod (*_bfd_error_handler) (_("%B: duplicate export stub %s"),
26983d8817e4Smiod input_bfd,
26993d8817e4Smiod stub_name);
27003d8817e4Smiod }
27013d8817e4Smiod }
27023d8817e4Smiod }
27033d8817e4Smiod }
27043d8817e4Smiod }
27053d8817e4Smiod
27063d8817e4Smiod return stub_changed;
27073d8817e4Smiod }
27083d8817e4Smiod
27093d8817e4Smiod /* Determine and set the size of the stub section for a final link.
27103d8817e4Smiod
27113d8817e4Smiod The basic idea here is to examine all the relocations looking for
27123d8817e4Smiod PC-relative calls to a target that is unreachable with a "bl"
27133d8817e4Smiod instruction. */
27143d8817e4Smiod
27153d8817e4Smiod bfd_boolean
elf32_hppa_size_stubs(bfd * output_bfd,bfd * stub_bfd,struct bfd_link_info * info,bfd_boolean multi_subspace,bfd_signed_vma group_size,asection * (* add_stub_section)(const char *,asection *),void (* layout_sections_again)(void))27163d8817e4Smiod elf32_hppa_size_stubs
27173d8817e4Smiod (bfd *output_bfd, bfd *stub_bfd, struct bfd_link_info *info,
27183d8817e4Smiod bfd_boolean multi_subspace, bfd_signed_vma group_size,
27193d8817e4Smiod asection * (*add_stub_section) (const char *, asection *),
27203d8817e4Smiod void (*layout_sections_again) (void))
27213d8817e4Smiod {
27223d8817e4Smiod bfd_size_type stub_group_size;
27233d8817e4Smiod bfd_boolean stubs_always_before_branch;
27243d8817e4Smiod bfd_boolean stub_changed;
27253d8817e4Smiod struct elf32_hppa_link_hash_table *htab = hppa_link_hash_table (info);
27263d8817e4Smiod
27273d8817e4Smiod /* Stash our params away. */
27283d8817e4Smiod htab->stub_bfd = stub_bfd;
27293d8817e4Smiod htab->multi_subspace = multi_subspace;
27303d8817e4Smiod htab->add_stub_section = add_stub_section;
27313d8817e4Smiod htab->layout_sections_again = layout_sections_again;
27323d8817e4Smiod stubs_always_before_branch = group_size < 0;
27333d8817e4Smiod if (group_size < 0)
27343d8817e4Smiod stub_group_size = -group_size;
27353d8817e4Smiod else
27363d8817e4Smiod stub_group_size = group_size;
27373d8817e4Smiod if (stub_group_size == 1)
27383d8817e4Smiod {
27393d8817e4Smiod /* Default values. */
27403d8817e4Smiod if (stubs_always_before_branch)
27413d8817e4Smiod {
27423d8817e4Smiod stub_group_size = 7680000;
27433d8817e4Smiod if (htab->has_17bit_branch || htab->multi_subspace)
27443d8817e4Smiod stub_group_size = 240000;
27453d8817e4Smiod if (htab->has_12bit_branch)
27463d8817e4Smiod stub_group_size = 7500;
27473d8817e4Smiod }
27483d8817e4Smiod else
27493d8817e4Smiod {
27503d8817e4Smiod stub_group_size = 6971392;
27513d8817e4Smiod if (htab->has_17bit_branch || htab->multi_subspace)
27523d8817e4Smiod stub_group_size = 217856;
27533d8817e4Smiod if (htab->has_12bit_branch)
27543d8817e4Smiod stub_group_size = 6808;
27553d8817e4Smiod }
27563d8817e4Smiod }
27573d8817e4Smiod
27583d8817e4Smiod group_sections (htab, stub_group_size, stubs_always_before_branch);
27593d8817e4Smiod
27603d8817e4Smiod switch (get_local_syms (output_bfd, info->input_bfds, info))
27613d8817e4Smiod {
27623d8817e4Smiod default:
27633d8817e4Smiod if (htab->all_local_syms)
27643d8817e4Smiod goto error_ret_free_local;
27653d8817e4Smiod return FALSE;
27663d8817e4Smiod
27673d8817e4Smiod case 0:
27683d8817e4Smiod stub_changed = FALSE;
27693d8817e4Smiod break;
27703d8817e4Smiod
27713d8817e4Smiod case 1:
27723d8817e4Smiod stub_changed = TRUE;
27733d8817e4Smiod break;
27743d8817e4Smiod }
27753d8817e4Smiod
27763d8817e4Smiod while (1)
27773d8817e4Smiod {
27783d8817e4Smiod bfd *input_bfd;
27793d8817e4Smiod unsigned int bfd_indx;
27803d8817e4Smiod asection *stub_sec;
27813d8817e4Smiod
27823d8817e4Smiod for (input_bfd = info->input_bfds, bfd_indx = 0;
27833d8817e4Smiod input_bfd != NULL;
27843d8817e4Smiod input_bfd = input_bfd->link_next, bfd_indx++)
27853d8817e4Smiod {
27863d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
27873d8817e4Smiod asection *section;
27883d8817e4Smiod Elf_Internal_Sym *local_syms;
27893d8817e4Smiod
27903d8817e4Smiod /* We'll need the symbol table in a second. */
27913d8817e4Smiod symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
27923d8817e4Smiod if (symtab_hdr->sh_info == 0)
27933d8817e4Smiod continue;
27943d8817e4Smiod
27953d8817e4Smiod local_syms = htab->all_local_syms[bfd_indx];
27963d8817e4Smiod
27973d8817e4Smiod /* Walk over each section attached to the input bfd. */
27983d8817e4Smiod for (section = input_bfd->sections;
27993d8817e4Smiod section != NULL;
28003d8817e4Smiod section = section->next)
28013d8817e4Smiod {
28023d8817e4Smiod Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
28033d8817e4Smiod
28043d8817e4Smiod /* If there aren't any relocs, then there's nothing more
28053d8817e4Smiod to do. */
28063d8817e4Smiod if ((section->flags & SEC_RELOC) == 0
28073d8817e4Smiod || section->reloc_count == 0)
28083d8817e4Smiod continue;
28093d8817e4Smiod
28103d8817e4Smiod /* If this section is a link-once section that will be
28113d8817e4Smiod discarded, then don't create any stubs. */
28123d8817e4Smiod if (section->output_section == NULL
28133d8817e4Smiod || section->output_section->owner != output_bfd)
28143d8817e4Smiod continue;
28153d8817e4Smiod
28163d8817e4Smiod /* Get the relocs. */
28173d8817e4Smiod internal_relocs
28183d8817e4Smiod = _bfd_elf_link_read_relocs (input_bfd, section, NULL, NULL,
28193d8817e4Smiod info->keep_memory);
28203d8817e4Smiod if (internal_relocs == NULL)
28213d8817e4Smiod goto error_ret_free_local;
28223d8817e4Smiod
28233d8817e4Smiod /* Now examine each relocation. */
28243d8817e4Smiod irela = internal_relocs;
28253d8817e4Smiod irelaend = irela + section->reloc_count;
28263d8817e4Smiod for (; irela < irelaend; irela++)
28273d8817e4Smiod {
28283d8817e4Smiod unsigned int r_type, r_indx;
28293d8817e4Smiod enum elf32_hppa_stub_type stub_type;
28303d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh;
28313d8817e4Smiod asection *sym_sec;
28323d8817e4Smiod bfd_vma sym_value;
28333d8817e4Smiod bfd_vma destination;
28343d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
28353d8817e4Smiod char *stub_name;
28363d8817e4Smiod const asection *id_sec;
28373d8817e4Smiod
28383d8817e4Smiod r_type = ELF32_R_TYPE (irela->r_info);
28393d8817e4Smiod r_indx = ELF32_R_SYM (irela->r_info);
28403d8817e4Smiod
28413d8817e4Smiod if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
28423d8817e4Smiod {
28433d8817e4Smiod bfd_set_error (bfd_error_bad_value);
28443d8817e4Smiod error_ret_free_internal:
28453d8817e4Smiod if (elf_section_data (section)->relocs == NULL)
28463d8817e4Smiod free (internal_relocs);
28473d8817e4Smiod goto error_ret_free_local;
28483d8817e4Smiod }
28493d8817e4Smiod
28503d8817e4Smiod /* Only look for stubs on call instructions. */
28513d8817e4Smiod if (r_type != (unsigned int) R_PARISC_PCREL12F
28523d8817e4Smiod && r_type != (unsigned int) R_PARISC_PCREL17F
28533d8817e4Smiod && r_type != (unsigned int) R_PARISC_PCREL22F)
28543d8817e4Smiod continue;
28553d8817e4Smiod
28563d8817e4Smiod /* Now determine the call target, its name, value,
28573d8817e4Smiod section. */
28583d8817e4Smiod sym_sec = NULL;
28593d8817e4Smiod sym_value = 0;
28603d8817e4Smiod destination = 0;
28613d8817e4Smiod hh = NULL;
28623d8817e4Smiod if (r_indx < symtab_hdr->sh_info)
28633d8817e4Smiod {
28643d8817e4Smiod /* It's a local symbol. */
28653d8817e4Smiod Elf_Internal_Sym *sym;
28663d8817e4Smiod Elf_Internal_Shdr *hdr;
28673d8817e4Smiod
28683d8817e4Smiod sym = local_syms + r_indx;
28693d8817e4Smiod hdr = elf_elfsections (input_bfd)[sym->st_shndx];
28703d8817e4Smiod sym_sec = hdr->bfd_section;
28713d8817e4Smiod if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
28723d8817e4Smiod sym_value = sym->st_value;
28733d8817e4Smiod destination = (sym_value + irela->r_addend
28743d8817e4Smiod + sym_sec->output_offset
28753d8817e4Smiod + sym_sec->output_section->vma);
28763d8817e4Smiod }
28773d8817e4Smiod else
28783d8817e4Smiod {
28793d8817e4Smiod /* It's an external symbol. */
28803d8817e4Smiod int e_indx;
28813d8817e4Smiod
28823d8817e4Smiod e_indx = r_indx - symtab_hdr->sh_info;
28833d8817e4Smiod hh = hppa_elf_hash_entry (elf_sym_hashes (input_bfd)[e_indx]);
28843d8817e4Smiod
28853d8817e4Smiod while (hh->eh.root.type == bfd_link_hash_indirect
28863d8817e4Smiod || hh->eh.root.type == bfd_link_hash_warning)
28873d8817e4Smiod hh = hppa_elf_hash_entry (hh->eh.root.u.i.link);
28883d8817e4Smiod
28893d8817e4Smiod if (hh->eh.root.type == bfd_link_hash_defined
28903d8817e4Smiod || hh->eh.root.type == bfd_link_hash_defweak)
28913d8817e4Smiod {
28923d8817e4Smiod sym_sec = hh->eh.root.u.def.section;
28933d8817e4Smiod sym_value = hh->eh.root.u.def.value;
28943d8817e4Smiod if (sym_sec->output_section != NULL)
28953d8817e4Smiod destination = (sym_value + irela->r_addend
28963d8817e4Smiod + sym_sec->output_offset
28973d8817e4Smiod + sym_sec->output_section->vma);
28983d8817e4Smiod }
28993d8817e4Smiod else if (hh->eh.root.type == bfd_link_hash_undefweak)
29003d8817e4Smiod {
29013d8817e4Smiod if (! info->shared)
29023d8817e4Smiod continue;
29033d8817e4Smiod }
29043d8817e4Smiod else if (hh->eh.root.type == bfd_link_hash_undefined)
29053d8817e4Smiod {
29063d8817e4Smiod if (! (info->unresolved_syms_in_objects == RM_IGNORE
29073d8817e4Smiod && (ELF_ST_VISIBILITY (hh->eh.other)
29083d8817e4Smiod == STV_DEFAULT)
29093d8817e4Smiod && hh->eh.type != STT_PARISC_MILLI))
29103d8817e4Smiod continue;
29113d8817e4Smiod }
29123d8817e4Smiod else
29133d8817e4Smiod {
29143d8817e4Smiod bfd_set_error (bfd_error_bad_value);
29153d8817e4Smiod goto error_ret_free_internal;
29163d8817e4Smiod }
29173d8817e4Smiod }
29183d8817e4Smiod
29193d8817e4Smiod /* Determine what (if any) linker stub is needed. */
29203d8817e4Smiod stub_type = hppa_type_of_stub (section, irela, hh,
29213d8817e4Smiod destination, info);
29223d8817e4Smiod if (stub_type == hppa_stub_none)
29233d8817e4Smiod continue;
29243d8817e4Smiod
29253d8817e4Smiod /* Support for grouping stub sections. */
29263d8817e4Smiod id_sec = htab->stub_group[section->id].link_sec;
29273d8817e4Smiod
29283d8817e4Smiod /* Get the name of this stub. */
29293d8817e4Smiod stub_name = hppa_stub_name (id_sec, sym_sec, hh, irela);
29303d8817e4Smiod if (!stub_name)
29313d8817e4Smiod goto error_ret_free_internal;
29323d8817e4Smiod
29333d8817e4Smiod hsh = hppa_stub_hash_lookup (&htab->bstab,
29343d8817e4Smiod stub_name,
29353d8817e4Smiod FALSE, FALSE);
29363d8817e4Smiod if (hsh != NULL)
29373d8817e4Smiod {
29383d8817e4Smiod /* The proper stub has already been created. */
29393d8817e4Smiod free (stub_name);
29403d8817e4Smiod continue;
29413d8817e4Smiod }
29423d8817e4Smiod
29433d8817e4Smiod hsh = hppa_add_stub (stub_name, section, htab);
29443d8817e4Smiod if (hsh == NULL)
29453d8817e4Smiod {
29463d8817e4Smiod free (stub_name);
29473d8817e4Smiod goto error_ret_free_internal;
29483d8817e4Smiod }
29493d8817e4Smiod
29503d8817e4Smiod hsh->target_value = sym_value;
29513d8817e4Smiod hsh->target_section = sym_sec;
29523d8817e4Smiod hsh->stub_type = stub_type;
29533d8817e4Smiod if (info->shared)
29543d8817e4Smiod {
29553d8817e4Smiod if (stub_type == hppa_stub_import)
29563d8817e4Smiod hsh->stub_type = hppa_stub_import_shared;
29573d8817e4Smiod else if (stub_type == hppa_stub_long_branch)
29583d8817e4Smiod hsh->stub_type = hppa_stub_long_branch_shared;
29593d8817e4Smiod }
29603d8817e4Smiod hsh->hh = hh;
29613d8817e4Smiod stub_changed = TRUE;
29623d8817e4Smiod }
29633d8817e4Smiod
29643d8817e4Smiod /* We're done with the internal relocs, free them. */
29653d8817e4Smiod if (elf_section_data (section)->relocs == NULL)
29663d8817e4Smiod free (internal_relocs);
29673d8817e4Smiod }
29683d8817e4Smiod }
29693d8817e4Smiod
29703d8817e4Smiod if (!stub_changed)
29713d8817e4Smiod break;
29723d8817e4Smiod
29733d8817e4Smiod /* OK, we've added some stubs. Find out the new size of the
29743d8817e4Smiod stub sections. */
29753d8817e4Smiod for (stub_sec = htab->stub_bfd->sections;
29763d8817e4Smiod stub_sec != NULL;
29773d8817e4Smiod stub_sec = stub_sec->next)
29783d8817e4Smiod stub_sec->size = 0;
29793d8817e4Smiod
29803d8817e4Smiod bfd_hash_traverse (&htab->bstab, hppa_size_one_stub, htab);
29813d8817e4Smiod
29823d8817e4Smiod /* Ask the linker to do its stuff. */
29833d8817e4Smiod (*htab->layout_sections_again) ();
29843d8817e4Smiod stub_changed = FALSE;
29853d8817e4Smiod }
29863d8817e4Smiod
29873d8817e4Smiod free (htab->all_local_syms);
29883d8817e4Smiod return TRUE;
29893d8817e4Smiod
29903d8817e4Smiod error_ret_free_local:
29913d8817e4Smiod free (htab->all_local_syms);
29923d8817e4Smiod return FALSE;
29933d8817e4Smiod }
29943d8817e4Smiod
29953d8817e4Smiod /* For a final link, this function is called after we have sized the
29963d8817e4Smiod stubs to provide a value for __gp. */
29973d8817e4Smiod
29983d8817e4Smiod bfd_boolean
elf32_hppa_set_gp(bfd * abfd,struct bfd_link_info * info)29993d8817e4Smiod elf32_hppa_set_gp (bfd *abfd, struct bfd_link_info *info)
30003d8817e4Smiod {
30013d8817e4Smiod struct bfd_link_hash_entry *h;
30023d8817e4Smiod asection *sec = NULL;
30033d8817e4Smiod bfd_vma gp_val = 0;
30043d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
30053d8817e4Smiod
30063d8817e4Smiod htab = hppa_link_hash_table (info);
30073d8817e4Smiod h = bfd_link_hash_lookup (&htab->etab.root, "$global$", FALSE, FALSE, FALSE);
30083d8817e4Smiod
30093d8817e4Smiod if (h != NULL
30103d8817e4Smiod && (h->type == bfd_link_hash_defined
30113d8817e4Smiod || h->type == bfd_link_hash_defweak))
30123d8817e4Smiod {
30133d8817e4Smiod gp_val = h->u.def.value;
30143d8817e4Smiod sec = h->u.def.section;
30153d8817e4Smiod }
30163d8817e4Smiod else
30173d8817e4Smiod {
30183d8817e4Smiod asection *splt = bfd_get_section_by_name (abfd, ".plt");
30193d8817e4Smiod asection *sgot = bfd_get_section_by_name (abfd, ".got");
30203d8817e4Smiod
30213d8817e4Smiod /* Choose to point our LTP at, in this order, one of .plt, .got,
30223d8817e4Smiod or .data, if these sections exist. In the case of choosing
30233d8817e4Smiod .plt try to make the LTP ideal for addressing anywhere in the
30243d8817e4Smiod .plt or .got with a 14 bit signed offset. Typically, the end
30253d8817e4Smiod of the .plt is the start of the .got, so choose .plt + 0x2000
30263d8817e4Smiod if either the .plt or .got is larger than 0x2000. If both
30273d8817e4Smiod the .plt and .got are smaller than 0x2000, choose the end of
30283d8817e4Smiod the .plt section. */
30293d8817e4Smiod sec = strcmp (bfd_get_target (abfd), "elf32-hppa-netbsd") == 0
30303d8817e4Smiod ? NULL : splt;
30313d8817e4Smiod if (sec != NULL)
30323d8817e4Smiod {
30333d8817e4Smiod gp_val = sec->size;
30343d8817e4Smiod if (gp_val > 0x2000 || (sgot && sgot->size > 0x2000))
30353d8817e4Smiod {
30363d8817e4Smiod gp_val = 0x2000;
30373d8817e4Smiod }
30383d8817e4Smiod }
30393d8817e4Smiod else
30403d8817e4Smiod {
30413d8817e4Smiod sec = sgot;
30423d8817e4Smiod if (sec != NULL)
30433d8817e4Smiod {
30443d8817e4Smiod if (strcmp (bfd_get_target (abfd), "elf32-hppa-netbsd") != 0)
30453d8817e4Smiod {
30463d8817e4Smiod /* We know we don't have a .plt. If .got is large,
30473d8817e4Smiod offset our LTP. */
30483d8817e4Smiod if (sec->size > 0x2000)
30493d8817e4Smiod gp_val = 0x2000;
30503d8817e4Smiod }
30513d8817e4Smiod }
30523d8817e4Smiod else
30533d8817e4Smiod {
30543d8817e4Smiod /* No .plt or .got. Who cares what the LTP is? */
30553d8817e4Smiod sec = bfd_get_section_by_name (abfd, ".data");
30563d8817e4Smiod }
30573d8817e4Smiod }
30583d8817e4Smiod
30593d8817e4Smiod if (h != NULL)
30603d8817e4Smiod {
30613d8817e4Smiod h->type = bfd_link_hash_defined;
30623d8817e4Smiod h->u.def.value = gp_val;
30633d8817e4Smiod if (sec != NULL)
30643d8817e4Smiod h->u.def.section = sec;
30653d8817e4Smiod else
30663d8817e4Smiod h->u.def.section = bfd_abs_section_ptr;
30673d8817e4Smiod }
30683d8817e4Smiod }
30693d8817e4Smiod
30703d8817e4Smiod if (sec != NULL && sec->output_section != NULL)
30713d8817e4Smiod gp_val += sec->output_section->vma + sec->output_offset;
30723d8817e4Smiod
30733d8817e4Smiod elf_gp (abfd) = gp_val;
30743d8817e4Smiod return TRUE;
30753d8817e4Smiod }
30763d8817e4Smiod
30773d8817e4Smiod /* Build all the stubs associated with the current output file. The
30783d8817e4Smiod stubs are kept in a hash table attached to the main linker hash
30793d8817e4Smiod table. We also set up the .plt entries for statically linked PIC
30803d8817e4Smiod functions here. This function is called via hppaelf_finish in the
30813d8817e4Smiod linker. */
30823d8817e4Smiod
30833d8817e4Smiod bfd_boolean
elf32_hppa_build_stubs(struct bfd_link_info * info)30843d8817e4Smiod elf32_hppa_build_stubs (struct bfd_link_info *info)
30853d8817e4Smiod {
30863d8817e4Smiod asection *stub_sec;
30873d8817e4Smiod struct bfd_hash_table *table;
30883d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
30893d8817e4Smiod
30903d8817e4Smiod htab = hppa_link_hash_table (info);
30913d8817e4Smiod
30923d8817e4Smiod for (stub_sec = htab->stub_bfd->sections;
30933d8817e4Smiod stub_sec != NULL;
30943d8817e4Smiod stub_sec = stub_sec->next)
30953d8817e4Smiod {
30963d8817e4Smiod bfd_size_type size;
30973d8817e4Smiod
30983d8817e4Smiod /* Allocate memory to hold the linker stubs. */
30993d8817e4Smiod size = stub_sec->size;
31003d8817e4Smiod stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
31013d8817e4Smiod if (stub_sec->contents == NULL && size != 0)
31023d8817e4Smiod return FALSE;
31033d8817e4Smiod stub_sec->size = 0;
31043d8817e4Smiod }
31053d8817e4Smiod
31063d8817e4Smiod /* Build the stubs as directed by the stub hash table. */
31073d8817e4Smiod table = &htab->bstab;
31083d8817e4Smiod bfd_hash_traverse (table, hppa_build_one_stub, info);
31093d8817e4Smiod
31103d8817e4Smiod return TRUE;
31113d8817e4Smiod }
31123d8817e4Smiod
31133d8817e4Smiod /* Perform a final link. */
31143d8817e4Smiod
31153d8817e4Smiod static bfd_boolean
elf32_hppa_final_link(bfd * abfd,struct bfd_link_info * info)31163d8817e4Smiod elf32_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
31173d8817e4Smiod {
31183d8817e4Smiod /* Invoke the regular ELF linker to do all the work. */
31193d8817e4Smiod if (!bfd_elf_final_link (abfd, info))
31203d8817e4Smiod return FALSE;
31213d8817e4Smiod
31223d8817e4Smiod /* If we're producing a final executable, sort the contents of the
31233d8817e4Smiod unwind section. */
31243d8817e4Smiod return elf_hppa_sort_unwind (abfd);
31253d8817e4Smiod }
31263d8817e4Smiod
31273d8817e4Smiod /* Record the lowest address for the data and text segments. */
31283d8817e4Smiod
31293d8817e4Smiod static void
hppa_record_segment_addr(bfd * abfd ATTRIBUTE_UNUSED,asection * section,void * data)31303d8817e4Smiod hppa_record_segment_addr (bfd *abfd ATTRIBUTE_UNUSED,
31313d8817e4Smiod asection *section,
31323d8817e4Smiod void *data)
31333d8817e4Smiod {
31343d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
31353d8817e4Smiod
31363d8817e4Smiod htab = (struct elf32_hppa_link_hash_table*) data;
31373d8817e4Smiod
31383d8817e4Smiod if ((section->flags & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
31393d8817e4Smiod {
31403d8817e4Smiod bfd_vma value = section->vma - section->filepos;
31413d8817e4Smiod
31423d8817e4Smiod if ((section->flags & SEC_READONLY) != 0)
31433d8817e4Smiod {
31443d8817e4Smiod if (value < htab->text_segment_base)
31453d8817e4Smiod htab->text_segment_base = value;
31463d8817e4Smiod }
31473d8817e4Smiod else
31483d8817e4Smiod {
31493d8817e4Smiod if (value < htab->data_segment_base)
31503d8817e4Smiod htab->data_segment_base = value;
31513d8817e4Smiod }
31523d8817e4Smiod }
31533d8817e4Smiod }
31543d8817e4Smiod
31553d8817e4Smiod /* Perform a relocation as part of a final link. */
31563d8817e4Smiod
31573d8817e4Smiod static bfd_reloc_status_type
final_link_relocate(asection * input_section,bfd_byte * contents,const Elf_Internal_Rela * rela,bfd_vma value,struct elf32_hppa_link_hash_table * htab,asection * sym_sec,struct elf32_hppa_link_hash_entry * hh,struct bfd_link_info * info)31583d8817e4Smiod final_link_relocate (asection *input_section,
31593d8817e4Smiod bfd_byte *contents,
31603d8817e4Smiod const Elf_Internal_Rela *rela,
31613d8817e4Smiod bfd_vma value,
31623d8817e4Smiod struct elf32_hppa_link_hash_table *htab,
31633d8817e4Smiod asection *sym_sec,
31643d8817e4Smiod struct elf32_hppa_link_hash_entry *hh,
31653d8817e4Smiod struct bfd_link_info *info)
31663d8817e4Smiod {
31673d8817e4Smiod int insn;
31683d8817e4Smiod unsigned int r_type = ELF32_R_TYPE (rela->r_info);
31693d8817e4Smiod unsigned int orig_r_type = r_type;
31703d8817e4Smiod reloc_howto_type *howto = elf_hppa_howto_table + r_type;
31713d8817e4Smiod int r_format = howto->bitsize;
31723d8817e4Smiod enum hppa_reloc_field_selector_type_alt r_field;
31733d8817e4Smiod bfd *input_bfd = input_section->owner;
31743d8817e4Smiod bfd_vma offset = rela->r_offset;
31753d8817e4Smiod bfd_vma max_branch_offset = 0;
31763d8817e4Smiod bfd_byte *hit_data = contents + offset;
31773d8817e4Smiod bfd_signed_vma addend = rela->r_addend;
31783d8817e4Smiod bfd_vma location;
31793d8817e4Smiod struct elf32_hppa_stub_hash_entry *hsh = NULL;
31803d8817e4Smiod int val;
31813d8817e4Smiod
31823d8817e4Smiod if (r_type == R_PARISC_NONE)
31833d8817e4Smiod return bfd_reloc_ok;
31843d8817e4Smiod
31853d8817e4Smiod insn = bfd_get_32 (input_bfd, hit_data);
31863d8817e4Smiod
31873d8817e4Smiod /* Find out where we are and where we're going. */
31883d8817e4Smiod location = (offset +
31893d8817e4Smiod input_section->output_offset +
31903d8817e4Smiod input_section->output_section->vma);
31913d8817e4Smiod
31923d8817e4Smiod /* If we are not building a shared library, convert DLTIND relocs to
31933d8817e4Smiod DPREL relocs. */
31943d8817e4Smiod if (!info->shared)
31953d8817e4Smiod {
31963d8817e4Smiod switch (r_type)
31973d8817e4Smiod {
31983d8817e4Smiod case R_PARISC_DLTIND21L:
31993d8817e4Smiod r_type = R_PARISC_DPREL21L;
32003d8817e4Smiod break;
32013d8817e4Smiod
32023d8817e4Smiod case R_PARISC_DLTIND14R:
32033d8817e4Smiod r_type = R_PARISC_DPREL14R;
32043d8817e4Smiod break;
32053d8817e4Smiod
32063d8817e4Smiod case R_PARISC_DLTIND14F:
32073d8817e4Smiod r_type = R_PARISC_DPREL14F;
32083d8817e4Smiod break;
32093d8817e4Smiod }
32103d8817e4Smiod }
32113d8817e4Smiod
32123d8817e4Smiod switch (r_type)
32133d8817e4Smiod {
32143d8817e4Smiod case R_PARISC_PCREL12F:
32153d8817e4Smiod case R_PARISC_PCREL17F:
32163d8817e4Smiod case R_PARISC_PCREL22F:
32173d8817e4Smiod /* If this call should go via the plt, find the import stub in
32183d8817e4Smiod the stub hash. */
32193d8817e4Smiod if (sym_sec == NULL
32203d8817e4Smiod || sym_sec->output_section == NULL
32213d8817e4Smiod || (hh != NULL
32223d8817e4Smiod && hh->eh.plt.offset != (bfd_vma) -1
32233d8817e4Smiod && hh->eh.dynindx != -1
32243d8817e4Smiod && !hh->plabel
32253d8817e4Smiod && (info->shared
32263d8817e4Smiod || !hh->eh.def_regular
32273d8817e4Smiod || hh->eh.root.type == bfd_link_hash_defweak)))
32283d8817e4Smiod {
32293d8817e4Smiod hsh = hppa_get_stub_entry (input_section, sym_sec,
32303d8817e4Smiod hh, rela, htab);
32313d8817e4Smiod if (hsh != NULL)
32323d8817e4Smiod {
32333d8817e4Smiod value = (hsh->stub_offset
32343d8817e4Smiod + hsh->stub_sec->output_offset
32353d8817e4Smiod + hsh->stub_sec->output_section->vma);
32363d8817e4Smiod addend = 0;
32373d8817e4Smiod }
32383d8817e4Smiod else if (sym_sec == NULL && hh != NULL
32393d8817e4Smiod && hh->eh.root.type == bfd_link_hash_undefweak)
32403d8817e4Smiod {
32413d8817e4Smiod /* It's OK if undefined weak. Calls to undefined weak
32423d8817e4Smiod symbols behave as if the "called" function
32433d8817e4Smiod immediately returns. We can thus call to a weak
32443d8817e4Smiod function without first checking whether the function
32453d8817e4Smiod is defined. */
32463d8817e4Smiod value = location;
32473d8817e4Smiod addend = 8;
32483d8817e4Smiod }
32493d8817e4Smiod else
32503d8817e4Smiod return bfd_reloc_undefined;
32513d8817e4Smiod }
32523d8817e4Smiod /* Fall thru. */
32533d8817e4Smiod
32543d8817e4Smiod case R_PARISC_PCREL21L:
32553d8817e4Smiod case R_PARISC_PCREL17C:
32563d8817e4Smiod case R_PARISC_PCREL17R:
32573d8817e4Smiod case R_PARISC_PCREL14R:
32583d8817e4Smiod case R_PARISC_PCREL14F:
32593d8817e4Smiod case R_PARISC_PCREL32:
32603d8817e4Smiod /* Make it a pc relative offset. */
32613d8817e4Smiod value -= location;
32623d8817e4Smiod addend -= 8;
32633d8817e4Smiod break;
32643d8817e4Smiod
32653d8817e4Smiod case R_PARISC_DPREL21L:
32663d8817e4Smiod case R_PARISC_DPREL14R:
32673d8817e4Smiod case R_PARISC_DPREL14F:
32683d8817e4Smiod /* Convert instructions that use the linkage table pointer (r19) to
32693d8817e4Smiod instructions that use the global data pointer (dp). This is the
32703d8817e4Smiod most efficient way of using PIC code in an incomplete executable,
32713d8817e4Smiod but the user must follow the standard runtime conventions for
32723d8817e4Smiod accessing data for this to work. */
32733d8817e4Smiod if (orig_r_type == R_PARISC_DLTIND21L)
32743d8817e4Smiod {
32753d8817e4Smiod /* Convert addil instructions if the original reloc was a
32763d8817e4Smiod DLTIND21L. GCC sometimes uses a register other than r19 for
32773d8817e4Smiod the operation, so we must convert any addil instruction
32783d8817e4Smiod that uses this relocation. */
32793d8817e4Smiod if ((insn & 0xfc000000) == ((int) OP_ADDIL << 26))
32803d8817e4Smiod insn = ADDIL_DP;
32813d8817e4Smiod else
32823d8817e4Smiod /* We must have a ldil instruction. It's too hard to find
32833d8817e4Smiod and convert the associated add instruction, so issue an
32843d8817e4Smiod error. */
32853d8817e4Smiod (*_bfd_error_handler)
32863d8817e4Smiod (_("%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"),
32873d8817e4Smiod input_bfd,
32883d8817e4Smiod input_section,
32893d8817e4Smiod offset,
32903d8817e4Smiod howto->name,
32913d8817e4Smiod insn);
32923d8817e4Smiod }
32933d8817e4Smiod else if (orig_r_type == R_PARISC_DLTIND14F)
32943d8817e4Smiod {
32953d8817e4Smiod /* This must be a format 1 load/store. Change the base
32963d8817e4Smiod register to dp. */
32973d8817e4Smiod insn = (insn & 0xfc1ffff) | (27 << 21);
32983d8817e4Smiod }
32993d8817e4Smiod
33003d8817e4Smiod /* For all the DP relative relocations, we need to examine the symbol's
33013d8817e4Smiod section. If it has no section or if it's a code section, then
33023d8817e4Smiod "data pointer relative" makes no sense. In that case we don't
33033d8817e4Smiod adjust the "value", and for 21 bit addil instructions, we change the
33043d8817e4Smiod source addend register from %dp to %r0. This situation commonly
33053d8817e4Smiod arises for undefined weak symbols and when a variable's "constness"
33063d8817e4Smiod is declared differently from the way the variable is defined. For
33073d8817e4Smiod instance: "extern int foo" with foo defined as "const int foo". */
33083d8817e4Smiod if (sym_sec == NULL || (sym_sec->flags & SEC_CODE) != 0)
33093d8817e4Smiod {
33103d8817e4Smiod if ((insn & ((0x3f << 26) | (0x1f << 21)))
33113d8817e4Smiod == (((int) OP_ADDIL << 26) | (27 << 21)))
33123d8817e4Smiod {
33133d8817e4Smiod insn &= ~ (0x1f << 21);
33143d8817e4Smiod }
33153d8817e4Smiod /* Now try to make things easy for the dynamic linker. */
33163d8817e4Smiod
33173d8817e4Smiod break;
33183d8817e4Smiod }
33193d8817e4Smiod /* Fall thru. */
33203d8817e4Smiod
33213d8817e4Smiod case R_PARISC_DLTIND21L:
33223d8817e4Smiod case R_PARISC_DLTIND14R:
33233d8817e4Smiod case R_PARISC_DLTIND14F:
33243d8817e4Smiod value -= elf_gp (input_section->output_section->owner);
33253d8817e4Smiod break;
33263d8817e4Smiod
33273d8817e4Smiod case R_PARISC_SEGREL32:
33283d8817e4Smiod if ((sym_sec->flags & SEC_CODE) != 0)
33293d8817e4Smiod value -= htab->text_segment_base;
33303d8817e4Smiod else
33313d8817e4Smiod value -= htab->data_segment_base;
33323d8817e4Smiod break;
33333d8817e4Smiod
33343d8817e4Smiod default:
33353d8817e4Smiod break;
33363d8817e4Smiod }
33373d8817e4Smiod
33383d8817e4Smiod switch (r_type)
33393d8817e4Smiod {
33403d8817e4Smiod case R_PARISC_DIR32:
33413d8817e4Smiod case R_PARISC_DIR14F:
33423d8817e4Smiod case R_PARISC_DIR17F:
33433d8817e4Smiod case R_PARISC_PCREL17C:
33443d8817e4Smiod case R_PARISC_PCREL14F:
33453d8817e4Smiod case R_PARISC_PCREL32:
33463d8817e4Smiod case R_PARISC_DPREL14F:
33473d8817e4Smiod case R_PARISC_PLABEL32:
33483d8817e4Smiod case R_PARISC_DLTIND14F:
33493d8817e4Smiod case R_PARISC_SEGBASE:
33503d8817e4Smiod case R_PARISC_SEGREL32:
33513d8817e4Smiod r_field = e_fsel;
33523d8817e4Smiod break;
33533d8817e4Smiod
33543d8817e4Smiod case R_PARISC_DLTIND21L:
33553d8817e4Smiod case R_PARISC_PCREL21L:
33563d8817e4Smiod case R_PARISC_PLABEL21L:
33573d8817e4Smiod r_field = e_lsel;
33583d8817e4Smiod break;
33593d8817e4Smiod
33603d8817e4Smiod case R_PARISC_DIR21L:
33613d8817e4Smiod case R_PARISC_DPREL21L:
33623d8817e4Smiod r_field = e_lrsel;
33633d8817e4Smiod break;
33643d8817e4Smiod
33653d8817e4Smiod case R_PARISC_PCREL17R:
33663d8817e4Smiod case R_PARISC_PCREL14R:
33673d8817e4Smiod case R_PARISC_PLABEL14R:
33683d8817e4Smiod case R_PARISC_DLTIND14R:
33693d8817e4Smiod r_field = e_rsel;
33703d8817e4Smiod break;
33713d8817e4Smiod
33723d8817e4Smiod case R_PARISC_DIR17R:
33733d8817e4Smiod case R_PARISC_DIR14R:
33743d8817e4Smiod case R_PARISC_DPREL14R:
33753d8817e4Smiod r_field = e_rrsel;
33763d8817e4Smiod break;
33773d8817e4Smiod
33783d8817e4Smiod case R_PARISC_PCREL12F:
33793d8817e4Smiod case R_PARISC_PCREL17F:
33803d8817e4Smiod case R_PARISC_PCREL22F:
33813d8817e4Smiod r_field = e_fsel;
33823d8817e4Smiod
33833d8817e4Smiod if (r_type == (unsigned int) R_PARISC_PCREL17F)
33843d8817e4Smiod {
33853d8817e4Smiod max_branch_offset = (1 << (17-1)) << 2;
33863d8817e4Smiod }
33873d8817e4Smiod else if (r_type == (unsigned int) R_PARISC_PCREL12F)
33883d8817e4Smiod {
33893d8817e4Smiod max_branch_offset = (1 << (12-1)) << 2;
33903d8817e4Smiod }
33913d8817e4Smiod else
33923d8817e4Smiod {
33933d8817e4Smiod max_branch_offset = (1 << (22-1)) << 2;
33943d8817e4Smiod }
33953d8817e4Smiod
33963d8817e4Smiod /* sym_sec is NULL on undefined weak syms or when shared on
33973d8817e4Smiod undefined syms. We've already checked for a stub for the
33983d8817e4Smiod shared undefined case. */
33993d8817e4Smiod if (sym_sec == NULL)
34003d8817e4Smiod break;
34013d8817e4Smiod
34023d8817e4Smiod /* If the branch is out of reach, then redirect the
34033d8817e4Smiod call to the local stub for this function. */
34043d8817e4Smiod if (value + addend + max_branch_offset >= 2*max_branch_offset)
34053d8817e4Smiod {
34063d8817e4Smiod hsh = hppa_get_stub_entry (input_section, sym_sec,
34073d8817e4Smiod hh, rela, htab);
34083d8817e4Smiod if (hsh == NULL)
34093d8817e4Smiod return bfd_reloc_undefined;
34103d8817e4Smiod
34113d8817e4Smiod /* Munge up the value and addend so that we call the stub
34123d8817e4Smiod rather than the procedure directly. */
34133d8817e4Smiod value = (hsh->stub_offset
34143d8817e4Smiod + hsh->stub_sec->output_offset
34153d8817e4Smiod + hsh->stub_sec->output_section->vma
34163d8817e4Smiod - location);
34173d8817e4Smiod addend = -8;
34183d8817e4Smiod }
34193d8817e4Smiod break;
34203d8817e4Smiod
34213d8817e4Smiod /* Something we don't know how to handle. */
34223d8817e4Smiod default:
34233d8817e4Smiod return bfd_reloc_notsupported;
34243d8817e4Smiod }
34253d8817e4Smiod
34263d8817e4Smiod /* Make sure we can reach the stub. */
34273d8817e4Smiod if (max_branch_offset != 0
34283d8817e4Smiod && value + addend + max_branch_offset >= 2*max_branch_offset)
34293d8817e4Smiod {
34303d8817e4Smiod (*_bfd_error_handler)
34313d8817e4Smiod (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
34323d8817e4Smiod input_bfd,
34333d8817e4Smiod input_section,
34343d8817e4Smiod offset,
34353d8817e4Smiod hsh->bh_root.string);
34363d8817e4Smiod bfd_set_error (bfd_error_bad_value);
34373d8817e4Smiod return bfd_reloc_notsupported;
34383d8817e4Smiod }
34393d8817e4Smiod
34403d8817e4Smiod val = hppa_field_adjust (value, addend, r_field);
34413d8817e4Smiod
34423d8817e4Smiod switch (r_type)
34433d8817e4Smiod {
34443d8817e4Smiod case R_PARISC_PCREL12F:
34453d8817e4Smiod case R_PARISC_PCREL17C:
34463d8817e4Smiod case R_PARISC_PCREL17F:
34473d8817e4Smiod case R_PARISC_PCREL17R:
34483d8817e4Smiod case R_PARISC_PCREL22F:
34493d8817e4Smiod case R_PARISC_DIR17F:
34503d8817e4Smiod case R_PARISC_DIR17R:
34513d8817e4Smiod /* This is a branch. Divide the offset by four.
34523d8817e4Smiod Note that we need to decide whether it's a branch or
34533d8817e4Smiod otherwise by inspecting the reloc. Inspecting insn won't
34543d8817e4Smiod work as insn might be from a .word directive. */
34553d8817e4Smiod val >>= 2;
34563d8817e4Smiod break;
34573d8817e4Smiod
34583d8817e4Smiod default:
34593d8817e4Smiod break;
34603d8817e4Smiod }
34613d8817e4Smiod
34623d8817e4Smiod insn = hppa_rebuild_insn (insn, val, r_format);
34633d8817e4Smiod
34643d8817e4Smiod /* Update the instruction word. */
34653d8817e4Smiod bfd_put_32 (input_bfd, (bfd_vma) insn, hit_data);
34663d8817e4Smiod return bfd_reloc_ok;
34673d8817e4Smiod }
34683d8817e4Smiod
34693d8817e4Smiod /* Relocate an HPPA ELF section. */
34703d8817e4Smiod
34713d8817e4Smiod static bfd_boolean
elf32_hppa_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * relocs,Elf_Internal_Sym * local_syms,asection ** local_sections)34723d8817e4Smiod elf32_hppa_relocate_section (bfd *output_bfd,
34733d8817e4Smiod struct bfd_link_info *info,
34743d8817e4Smiod bfd *input_bfd,
34753d8817e4Smiod asection *input_section,
34763d8817e4Smiod bfd_byte *contents,
34773d8817e4Smiod Elf_Internal_Rela *relocs,
34783d8817e4Smiod Elf_Internal_Sym *local_syms,
34793d8817e4Smiod asection **local_sections)
34803d8817e4Smiod {
34813d8817e4Smiod bfd_vma *local_got_offsets;
34823d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
34833d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
34843d8817e4Smiod Elf_Internal_Rela *rela;
34853d8817e4Smiod Elf_Internal_Rela *relend;
34863d8817e4Smiod
34873d8817e4Smiod if (info->relocatable)
34883d8817e4Smiod return TRUE;
34893d8817e4Smiod
34903d8817e4Smiod symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
34913d8817e4Smiod
34923d8817e4Smiod htab = hppa_link_hash_table (info);
34933d8817e4Smiod local_got_offsets = elf_local_got_offsets (input_bfd);
34943d8817e4Smiod
34953d8817e4Smiod rela = relocs;
34963d8817e4Smiod relend = relocs + input_section->reloc_count;
34973d8817e4Smiod for (; rela < relend; rela++)
34983d8817e4Smiod {
34993d8817e4Smiod unsigned int r_type;
35003d8817e4Smiod reloc_howto_type *howto;
35013d8817e4Smiod unsigned int r_symndx;
35023d8817e4Smiod struct elf32_hppa_link_hash_entry *hh;
35033d8817e4Smiod Elf_Internal_Sym *sym;
35043d8817e4Smiod asection *sym_sec;
35053d8817e4Smiod bfd_vma relocation;
35063d8817e4Smiod bfd_reloc_status_type rstatus;
35073d8817e4Smiod const char *sym_name;
35083d8817e4Smiod bfd_boolean plabel;
35093d8817e4Smiod bfd_boolean warned_undef;
35103d8817e4Smiod
35113d8817e4Smiod r_type = ELF32_R_TYPE (rela->r_info);
35123d8817e4Smiod if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
35133d8817e4Smiod {
35143d8817e4Smiod bfd_set_error (bfd_error_bad_value);
35153d8817e4Smiod return FALSE;
35163d8817e4Smiod }
35173d8817e4Smiod if (r_type == (unsigned int) R_PARISC_GNU_VTENTRY
35183d8817e4Smiod || r_type == (unsigned int) R_PARISC_GNU_VTINHERIT)
35193d8817e4Smiod continue;
35203d8817e4Smiod
35213d8817e4Smiod /* This is a final link. */
35223d8817e4Smiod r_symndx = ELF32_R_SYM (rela->r_info);
35233d8817e4Smiod hh = NULL;
35243d8817e4Smiod sym = NULL;
35253d8817e4Smiod sym_sec = NULL;
35263d8817e4Smiod warned_undef = FALSE;
35273d8817e4Smiod if (r_symndx < symtab_hdr->sh_info)
35283d8817e4Smiod {
35293d8817e4Smiod /* This is a local symbol, h defaults to NULL. */
35303d8817e4Smiod sym = local_syms + r_symndx;
35313d8817e4Smiod sym_sec = local_sections[r_symndx];
35323d8817e4Smiod relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sym_sec, rela);
35333d8817e4Smiod }
35343d8817e4Smiod else
35353d8817e4Smiod {
35363d8817e4Smiod struct elf_link_hash_entry *eh;
35373d8817e4Smiod bfd_boolean unresolved_reloc;
35383d8817e4Smiod struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
35393d8817e4Smiod
35403d8817e4Smiod RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rela,
35413d8817e4Smiod r_symndx, symtab_hdr, sym_hashes,
35423d8817e4Smiod eh, sym_sec, relocation,
35433d8817e4Smiod unresolved_reloc, warned_undef);
35443d8817e4Smiod
35453d8817e4Smiod if (relocation == 0
35463d8817e4Smiod && eh->root.type != bfd_link_hash_defined
35473d8817e4Smiod && eh->root.type != bfd_link_hash_defweak
35483d8817e4Smiod && eh->root.type != bfd_link_hash_undefweak)
35493d8817e4Smiod {
35503d8817e4Smiod if (info->unresolved_syms_in_objects == RM_IGNORE
35513d8817e4Smiod && ELF_ST_VISIBILITY (eh->other) == STV_DEFAULT
35523d8817e4Smiod && eh->type == STT_PARISC_MILLI)
35533d8817e4Smiod {
35543d8817e4Smiod if (! info->callbacks->undefined_symbol
35553d8817e4Smiod (info, eh->root.root.string, input_bfd,
35563d8817e4Smiod input_section, rela->r_offset, FALSE))
35573d8817e4Smiod return FALSE;
35583d8817e4Smiod warned_undef = TRUE;
35593d8817e4Smiod }
35603d8817e4Smiod }
35613d8817e4Smiod hh = hppa_elf_hash_entry (eh);
35623d8817e4Smiod }
35633d8817e4Smiod
35643d8817e4Smiod /* Do any required modifications to the relocation value, and
35653d8817e4Smiod determine what types of dynamic info we need to output, if
35663d8817e4Smiod any. */
35673d8817e4Smiod plabel = 0;
35683d8817e4Smiod switch (r_type)
35693d8817e4Smiod {
35703d8817e4Smiod case R_PARISC_DLTIND14F:
35713d8817e4Smiod case R_PARISC_DLTIND14R:
35723d8817e4Smiod case R_PARISC_DLTIND21L:
35733d8817e4Smiod {
35743d8817e4Smiod bfd_vma off;
35753d8817e4Smiod bfd_boolean do_got = 0;
35763d8817e4Smiod
35773d8817e4Smiod /* Relocation is to the entry for this symbol in the
35783d8817e4Smiod global offset table. */
35793d8817e4Smiod if (hh != NULL)
35803d8817e4Smiod {
35813d8817e4Smiod bfd_boolean dyn;
35823d8817e4Smiod
35833d8817e4Smiod off = hh->eh.got.offset;
35843d8817e4Smiod dyn = htab->etab.dynamic_sections_created;
35853d8817e4Smiod if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared,
35863d8817e4Smiod &hh->eh))
35873d8817e4Smiod {
35883d8817e4Smiod /* If we aren't going to call finish_dynamic_symbol,
35893d8817e4Smiod then we need to handle initialisation of the .got
35903d8817e4Smiod entry and create needed relocs here. Since the
35913d8817e4Smiod offset must always be a multiple of 4, we use the
35923d8817e4Smiod least significant bit to record whether we have
35933d8817e4Smiod initialised it already. */
35943d8817e4Smiod if ((off & 1) != 0)
35953d8817e4Smiod off &= ~1;
35963d8817e4Smiod else
35973d8817e4Smiod {
35983d8817e4Smiod hh->eh.got.offset |= 1;
35993d8817e4Smiod do_got = 1;
36003d8817e4Smiod }
36013d8817e4Smiod }
36023d8817e4Smiod }
36033d8817e4Smiod else
36043d8817e4Smiod {
36053d8817e4Smiod /* Local symbol case. */
36063d8817e4Smiod if (local_got_offsets == NULL)
36073d8817e4Smiod abort ();
36083d8817e4Smiod
36093d8817e4Smiod off = local_got_offsets[r_symndx];
36103d8817e4Smiod
36113d8817e4Smiod /* The offset must always be a multiple of 4. We use
36123d8817e4Smiod the least significant bit to record whether we have
36133d8817e4Smiod already generated the necessary reloc. */
36143d8817e4Smiod if ((off & 1) != 0)
36153d8817e4Smiod off &= ~1;
36163d8817e4Smiod else
36173d8817e4Smiod {
36183d8817e4Smiod local_got_offsets[r_symndx] |= 1;
36193d8817e4Smiod do_got = 1;
36203d8817e4Smiod }
36213d8817e4Smiod }
36223d8817e4Smiod
36233d8817e4Smiod if (do_got)
36243d8817e4Smiod {
36253d8817e4Smiod if (info->shared)
36263d8817e4Smiod {
36273d8817e4Smiod /* Output a dynamic relocation for this GOT entry.
36283d8817e4Smiod In this case it is relative to the base of the
36293d8817e4Smiod object because the symbol index is zero. */
36303d8817e4Smiod Elf_Internal_Rela outrel;
36313d8817e4Smiod bfd_byte *loc;
36323d8817e4Smiod asection *sec = htab->srelgot;
36333d8817e4Smiod
36343d8817e4Smiod outrel.r_offset = (off
36353d8817e4Smiod + htab->sgot->output_offset
36363d8817e4Smiod + htab->sgot->output_section->vma);
36373d8817e4Smiod outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
36383d8817e4Smiod outrel.r_addend = relocation;
36393d8817e4Smiod loc = sec->contents;
36403d8817e4Smiod loc += sec->reloc_count++ * sizeof (Elf32_External_Rela);
36413d8817e4Smiod bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
36423d8817e4Smiod }
36433d8817e4Smiod else
36443d8817e4Smiod bfd_put_32 (output_bfd, relocation,
36453d8817e4Smiod htab->sgot->contents + off);
36463d8817e4Smiod }
36473d8817e4Smiod
36483d8817e4Smiod if (off >= (bfd_vma) -2)
36493d8817e4Smiod abort ();
36503d8817e4Smiod
36513d8817e4Smiod /* Add the base of the GOT to the relocation value. */
36523d8817e4Smiod relocation = (off
36533d8817e4Smiod + htab->sgot->output_offset
36543d8817e4Smiod + htab->sgot->output_section->vma);
36553d8817e4Smiod }
36563d8817e4Smiod break;
36573d8817e4Smiod
36583d8817e4Smiod case R_PARISC_SEGREL32:
36593d8817e4Smiod /* If this is the first SEGREL relocation, then initialize
36603d8817e4Smiod the segment base values. */
36613d8817e4Smiod if (htab->text_segment_base == (bfd_vma) -1)
36623d8817e4Smiod bfd_map_over_sections (output_bfd, hppa_record_segment_addr, htab);
36633d8817e4Smiod break;
36643d8817e4Smiod
36653d8817e4Smiod case R_PARISC_PLABEL14R:
36663d8817e4Smiod case R_PARISC_PLABEL21L:
36673d8817e4Smiod case R_PARISC_PLABEL32:
36683d8817e4Smiod if (htab->etab.dynamic_sections_created)
36693d8817e4Smiod {
36703d8817e4Smiod bfd_vma off;
36713d8817e4Smiod bfd_boolean do_plt = 0;
36723d8817e4Smiod /* If we have a global symbol with a PLT slot, then
36733d8817e4Smiod redirect this relocation to it. */
36743d8817e4Smiod if (hh != NULL)
36753d8817e4Smiod {
36763d8817e4Smiod off = hh->eh.plt.offset;
36773d8817e4Smiod if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared,
36783d8817e4Smiod &hh->eh))
36793d8817e4Smiod {
36803d8817e4Smiod /* In a non-shared link, adjust_dynamic_symbols
36813d8817e4Smiod isn't called for symbols forced local. We
36823d8817e4Smiod need to write out the plt entry here. */
36833d8817e4Smiod if ((off & 1) != 0)
36843d8817e4Smiod off &= ~1;
36853d8817e4Smiod else
36863d8817e4Smiod {
36873d8817e4Smiod hh->eh.plt.offset |= 1;
36883d8817e4Smiod do_plt = 1;
36893d8817e4Smiod }
36903d8817e4Smiod }
36913d8817e4Smiod }
36923d8817e4Smiod else
36933d8817e4Smiod {
36943d8817e4Smiod bfd_vma *local_plt_offsets;
36953d8817e4Smiod
36963d8817e4Smiod if (local_got_offsets == NULL)
36973d8817e4Smiod abort ();
36983d8817e4Smiod
36993d8817e4Smiod local_plt_offsets = local_got_offsets + symtab_hdr->sh_info;
37003d8817e4Smiod off = local_plt_offsets[r_symndx];
37013d8817e4Smiod
37023d8817e4Smiod /* As for the local .got entry case, we use the last
37033d8817e4Smiod bit to record whether we've already initialised
37043d8817e4Smiod this local .plt entry. */
37053d8817e4Smiod if ((off & 1) != 0)
37063d8817e4Smiod off &= ~1;
37073d8817e4Smiod else
37083d8817e4Smiod {
37093d8817e4Smiod local_plt_offsets[r_symndx] |= 1;
37103d8817e4Smiod do_plt = 1;
37113d8817e4Smiod }
37123d8817e4Smiod }
37133d8817e4Smiod
37143d8817e4Smiod if (do_plt)
37153d8817e4Smiod {
37163d8817e4Smiod if (info->shared)
37173d8817e4Smiod {
37183d8817e4Smiod /* Output a dynamic IPLT relocation for this
37193d8817e4Smiod PLT entry. */
37203d8817e4Smiod Elf_Internal_Rela outrel;
37213d8817e4Smiod bfd_byte *loc;
37223d8817e4Smiod asection *s = htab->srelplt;
37233d8817e4Smiod
37243d8817e4Smiod outrel.r_offset = (off
37253d8817e4Smiod + htab->splt->output_offset
37263d8817e4Smiod + htab->splt->output_section->vma);
37273d8817e4Smiod outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
37283d8817e4Smiod outrel.r_addend = relocation;
37293d8817e4Smiod loc = s->contents;
37303d8817e4Smiod loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
37313d8817e4Smiod bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
37323d8817e4Smiod }
37333d8817e4Smiod else
37343d8817e4Smiod {
37353d8817e4Smiod bfd_put_32 (output_bfd,
37363d8817e4Smiod relocation,
37373d8817e4Smiod htab->splt->contents + off);
37383d8817e4Smiod bfd_put_32 (output_bfd,
37393d8817e4Smiod elf_gp (htab->splt->output_section->owner),
37403d8817e4Smiod htab->splt->contents + off + 4);
37413d8817e4Smiod }
37423d8817e4Smiod }
37433d8817e4Smiod
37443d8817e4Smiod if (off >= (bfd_vma) -2)
37453d8817e4Smiod abort ();
37463d8817e4Smiod
37473d8817e4Smiod /* PLABELs contain function pointers. Relocation is to
37483d8817e4Smiod the entry for the function in the .plt. The magic +2
37493d8817e4Smiod offset signals to $$dyncall that the function pointer
37503d8817e4Smiod is in the .plt and thus has a gp pointer too.
37513d8817e4Smiod Exception: Undefined PLABELs should have a value of
37523d8817e4Smiod zero. */
37533d8817e4Smiod if (hh == NULL
37543d8817e4Smiod || (hh->eh.root.type != bfd_link_hash_undefweak
37553d8817e4Smiod && hh->eh.root.type != bfd_link_hash_undefined))
37563d8817e4Smiod {
37573d8817e4Smiod relocation = (off
37583d8817e4Smiod + htab->splt->output_offset
37593d8817e4Smiod + htab->splt->output_section->vma
37603d8817e4Smiod + 2);
37613d8817e4Smiod }
37623d8817e4Smiod plabel = 1;
37633d8817e4Smiod }
37643d8817e4Smiod /* Fall through and possibly emit a dynamic relocation. */
37653d8817e4Smiod
37663d8817e4Smiod case R_PARISC_DIR17F:
37673d8817e4Smiod case R_PARISC_DIR17R:
37683d8817e4Smiod case R_PARISC_DIR14F:
37693d8817e4Smiod case R_PARISC_DIR14R:
37703d8817e4Smiod case R_PARISC_DIR21L:
37713d8817e4Smiod case R_PARISC_DPREL14F:
37723d8817e4Smiod case R_PARISC_DPREL14R:
37733d8817e4Smiod case R_PARISC_DPREL21L:
37743d8817e4Smiod case R_PARISC_DIR32:
37753d8817e4Smiod /* r_symndx will be zero only for relocs against symbols
37763d8817e4Smiod from removed linkonce sections, or sections discarded by
37773d8817e4Smiod a linker script. */
37783d8817e4Smiod if (r_symndx == 0
37793d8817e4Smiod || (input_section->flags & SEC_ALLOC) == 0)
37803d8817e4Smiod break;
37813d8817e4Smiod
37823d8817e4Smiod /* The reloc types handled here and this conditional
37833d8817e4Smiod expression must match the code in ..check_relocs and
37843d8817e4Smiod allocate_dynrelocs. ie. We need exactly the same condition
37853d8817e4Smiod as in ..check_relocs, with some extra conditions (dynindx
37863d8817e4Smiod test in this case) to cater for relocs removed by
37873d8817e4Smiod allocate_dynrelocs. If you squint, the non-shared test
37883d8817e4Smiod here does indeed match the one in ..check_relocs, the
37893d8817e4Smiod difference being that here we test DEF_DYNAMIC as well as
37903d8817e4Smiod !DEF_REGULAR. All common syms end up with !DEF_REGULAR,
37913d8817e4Smiod which is why we can't use just that test here.
37923d8817e4Smiod Conversely, DEF_DYNAMIC can't be used in check_relocs as
37933d8817e4Smiod there all files have not been loaded. */
37943d8817e4Smiod if ((info->shared
37953d8817e4Smiod && (hh == NULL
37963d8817e4Smiod || ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT
37973d8817e4Smiod || hh->eh.root.type != bfd_link_hash_undefweak)
37983d8817e4Smiod && (IS_ABSOLUTE_RELOC (r_type)
37993d8817e4Smiod || !SYMBOL_CALLS_LOCAL (info, &hh->eh)))
38003d8817e4Smiod || (!info->shared
38013d8817e4Smiod && hh != NULL
38023d8817e4Smiod && hh->eh.dynindx != -1
38033d8817e4Smiod && !hh->eh.non_got_ref
38043d8817e4Smiod && ((ELIMINATE_COPY_RELOCS
38053d8817e4Smiod && hh->eh.def_dynamic
38063d8817e4Smiod && !hh->eh.def_regular)
38073d8817e4Smiod || hh->eh.root.type == bfd_link_hash_undefweak
38083d8817e4Smiod || hh->eh.root.type == bfd_link_hash_undefined)))
38093d8817e4Smiod {
38103d8817e4Smiod Elf_Internal_Rela outrel;
38113d8817e4Smiod bfd_boolean skip;
38123d8817e4Smiod asection *sreloc;
38133d8817e4Smiod bfd_byte *loc;
38143d8817e4Smiod
38153d8817e4Smiod /* When generating a shared object, these relocations
38163d8817e4Smiod are copied into the output file to be resolved at run
38173d8817e4Smiod time. */
38183d8817e4Smiod
38193d8817e4Smiod outrel.r_addend = rela->r_addend;
38203d8817e4Smiod outrel.r_offset =
38213d8817e4Smiod _bfd_elf_section_offset (output_bfd, info, input_section,
38223d8817e4Smiod rela->r_offset);
38233d8817e4Smiod skip = (outrel.r_offset == (bfd_vma) -1
38243d8817e4Smiod || outrel.r_offset == (bfd_vma) -2);
38253d8817e4Smiod outrel.r_offset += (input_section->output_offset
38263d8817e4Smiod + input_section->output_section->vma);
38273d8817e4Smiod
38283d8817e4Smiod if (skip)
38293d8817e4Smiod {
38303d8817e4Smiod memset (&outrel, 0, sizeof (outrel));
38313d8817e4Smiod }
38323d8817e4Smiod else if (hh != NULL
38333d8817e4Smiod && hh->eh.dynindx != -1
38343d8817e4Smiod && (plabel
38353d8817e4Smiod || !IS_ABSOLUTE_RELOC (r_type)
38363d8817e4Smiod || !info->shared
38373d8817e4Smiod || !info->symbolic
38383d8817e4Smiod || !hh->eh.def_regular))
38393d8817e4Smiod {
38403d8817e4Smiod outrel.r_info = ELF32_R_INFO (hh->eh.dynindx, r_type);
38413d8817e4Smiod }
38423d8817e4Smiod else /* It's a local symbol, or one marked to become local. */
38433d8817e4Smiod {
38443d8817e4Smiod int indx = 0;
38453d8817e4Smiod
38463d8817e4Smiod /* Add the absolute offset of the symbol. */
38473d8817e4Smiod outrel.r_addend += relocation;
38483d8817e4Smiod
38493d8817e4Smiod /* Global plabels need to be processed by the
38503d8817e4Smiod dynamic linker so that functions have at most one
38513d8817e4Smiod fptr. For this reason, we need to differentiate
38523d8817e4Smiod between global and local plabels, which we do by
38533d8817e4Smiod providing the function symbol for a global plabel
38543d8817e4Smiod reloc, and no symbol for local plabels. */
38553d8817e4Smiod if (! plabel
38563d8817e4Smiod && sym_sec != NULL
38573d8817e4Smiod && sym_sec->output_section != NULL
38583d8817e4Smiod && ! bfd_is_abs_section (sym_sec))
38593d8817e4Smiod {
38603d8817e4Smiod /* Skip this relocation if the output section has
38613d8817e4Smiod been discarded. */
38623d8817e4Smiod if (bfd_is_abs_section (sym_sec->output_section))
38633d8817e4Smiod break;
38643d8817e4Smiod
38653d8817e4Smiod indx = elf_section_data (sym_sec->output_section)->dynindx;
38663d8817e4Smiod /* We are turning this relocation into one
38673d8817e4Smiod against a section symbol, so subtract out the
38683d8817e4Smiod output section's address but not the offset
38693d8817e4Smiod of the input section in the output section. */
38703d8817e4Smiod outrel.r_addend -= sym_sec->output_section->vma;
38713d8817e4Smiod }
38723d8817e4Smiod
38733d8817e4Smiod outrel.r_info = ELF32_R_INFO (indx, r_type);
38743d8817e4Smiod }
38753d8817e4Smiod sreloc = elf_section_data (input_section)->sreloc;
38763d8817e4Smiod if (sreloc == NULL)
38773d8817e4Smiod abort ();
38783d8817e4Smiod
38793d8817e4Smiod loc = sreloc->contents;
38803d8817e4Smiod loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
38813d8817e4Smiod bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
38823d8817e4Smiod }
38833d8817e4Smiod break;
38843d8817e4Smiod
38853d8817e4Smiod default:
38863d8817e4Smiod break;
38873d8817e4Smiod }
38883d8817e4Smiod
38893d8817e4Smiod rstatus = final_link_relocate (input_section, contents, rela, relocation,
38903d8817e4Smiod htab, sym_sec, hh, info);
38913d8817e4Smiod
38923d8817e4Smiod if (rstatus == bfd_reloc_ok)
38933d8817e4Smiod continue;
38943d8817e4Smiod
38953d8817e4Smiod if (hh != NULL)
38963d8817e4Smiod sym_name = hh->eh.root.root.string;
38973d8817e4Smiod else
38983d8817e4Smiod {
38993d8817e4Smiod sym_name = bfd_elf_string_from_elf_section (input_bfd,
39003d8817e4Smiod symtab_hdr->sh_link,
39013d8817e4Smiod sym->st_name);
39023d8817e4Smiod if (sym_name == NULL)
39033d8817e4Smiod return FALSE;
39043d8817e4Smiod if (*sym_name == '\0')
39053d8817e4Smiod sym_name = bfd_section_name (input_bfd, sym_sec);
39063d8817e4Smiod }
39073d8817e4Smiod
39083d8817e4Smiod howto = elf_hppa_howto_table + r_type;
39093d8817e4Smiod
39103d8817e4Smiod if (rstatus == bfd_reloc_undefined || rstatus == bfd_reloc_notsupported)
39113d8817e4Smiod {
39123d8817e4Smiod if (rstatus == bfd_reloc_notsupported || !warned_undef)
39133d8817e4Smiod {
39143d8817e4Smiod (*_bfd_error_handler)
39153d8817e4Smiod (_("%B(%A+0x%lx): cannot handle %s for %s"),
39163d8817e4Smiod input_bfd,
39173d8817e4Smiod input_section,
39183d8817e4Smiod (long) rela->r_offset,
39193d8817e4Smiod howto->name,
39203d8817e4Smiod sym_name);
39213d8817e4Smiod bfd_set_error (bfd_error_bad_value);
39223d8817e4Smiod return FALSE;
39233d8817e4Smiod }
39243d8817e4Smiod }
39253d8817e4Smiod else
39263d8817e4Smiod {
39273d8817e4Smiod if (!((*info->callbacks->reloc_overflow)
39283d8817e4Smiod (info, (hh ? &hh->eh.root : NULL), sym_name, howto->name,
39293d8817e4Smiod (bfd_vma) 0, input_bfd, input_section, rela->r_offset)))
39303d8817e4Smiod return FALSE;
39313d8817e4Smiod }
39323d8817e4Smiod }
39333d8817e4Smiod
39343d8817e4Smiod return TRUE;
39353d8817e4Smiod }
39363d8817e4Smiod
39373d8817e4Smiod /* Finish up dynamic symbol handling. We set the contents of various
39383d8817e4Smiod dynamic sections here. */
39393d8817e4Smiod
39403d8817e4Smiod static bfd_boolean
elf32_hppa_finish_dynamic_symbol(bfd * output_bfd,struct bfd_link_info * info,struct elf_link_hash_entry * eh,Elf_Internal_Sym * sym)39413d8817e4Smiod elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
39423d8817e4Smiod struct bfd_link_info *info,
39433d8817e4Smiod struct elf_link_hash_entry *eh,
39443d8817e4Smiod Elf_Internal_Sym *sym)
39453d8817e4Smiod {
39463d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
39473d8817e4Smiod Elf_Internal_Rela rela;
39483d8817e4Smiod bfd_byte *loc;
39493d8817e4Smiod
39503d8817e4Smiod htab = hppa_link_hash_table (info);
39513d8817e4Smiod
39523d8817e4Smiod if (eh->plt.offset != (bfd_vma) -1)
39533d8817e4Smiod {
39543d8817e4Smiod bfd_vma value;
39553d8817e4Smiod
39563d8817e4Smiod if (eh->plt.offset & 1)
39573d8817e4Smiod abort ();
39583d8817e4Smiod
39593d8817e4Smiod /* This symbol has an entry in the procedure linkage table. Set
39603d8817e4Smiod it up.
39613d8817e4Smiod
39623d8817e4Smiod The format of a plt entry is
39633d8817e4Smiod <funcaddr>
39643d8817e4Smiod <__gp>
39653d8817e4Smiod */
39663d8817e4Smiod value = 0;
39673d8817e4Smiod if (eh->root.type == bfd_link_hash_defined
39683d8817e4Smiod || eh->root.type == bfd_link_hash_defweak)
39693d8817e4Smiod {
39703d8817e4Smiod value = eh->root.u.def.value;
39713d8817e4Smiod if (eh->root.u.def.section->output_section != NULL)
39723d8817e4Smiod value += (eh->root.u.def.section->output_offset
39733d8817e4Smiod + eh->root.u.def.section->output_section->vma);
39743d8817e4Smiod }
39753d8817e4Smiod
39763d8817e4Smiod /* Create a dynamic IPLT relocation for this entry. */
39773d8817e4Smiod rela.r_offset = (eh->plt.offset
39783d8817e4Smiod + htab->splt->output_offset
39793d8817e4Smiod + htab->splt->output_section->vma);
39803d8817e4Smiod if (eh->dynindx != -1)
39813d8817e4Smiod {
39823d8817e4Smiod rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_IPLT);
39833d8817e4Smiod rela.r_addend = 0;
39843d8817e4Smiod }
39853d8817e4Smiod else
39863d8817e4Smiod {
39873d8817e4Smiod /* This symbol has been marked to become local, and is
39883d8817e4Smiod used by a plabel so must be kept in the .plt. */
39893d8817e4Smiod rela.r_info = ELF32_R_INFO (0, R_PARISC_IPLT);
39903d8817e4Smiod rela.r_addend = value;
39913d8817e4Smiod }
39923d8817e4Smiod
39933d8817e4Smiod loc = htab->srelplt->contents;
39943d8817e4Smiod loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
39953d8817e4Smiod bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, &rela, loc);
39963d8817e4Smiod
39973d8817e4Smiod if (!eh->def_regular)
39983d8817e4Smiod {
39993d8817e4Smiod /* Mark the symbol as undefined, rather than as defined in
40003d8817e4Smiod the .plt section. Leave the value alone. */
40013d8817e4Smiod sym->st_shndx = SHN_UNDEF;
40023d8817e4Smiod }
40033d8817e4Smiod }
40043d8817e4Smiod
40053d8817e4Smiod if (eh->got.offset != (bfd_vma) -1)
40063d8817e4Smiod {
40073d8817e4Smiod /* This symbol has an entry in the global offset table. Set it
40083d8817e4Smiod up. */
40093d8817e4Smiod
40103d8817e4Smiod rela.r_offset = ((eh->got.offset &~ (bfd_vma) 1)
40113d8817e4Smiod + htab->sgot->output_offset
40123d8817e4Smiod + htab->sgot->output_section->vma);
40133d8817e4Smiod
40143d8817e4Smiod /* If this is a -Bsymbolic link and the symbol is defined
40153d8817e4Smiod locally or was forced to be local because of a version file,
40163d8817e4Smiod we just want to emit a RELATIVE reloc. The entry in the
40173d8817e4Smiod global offset table will already have been initialized in the
40183d8817e4Smiod relocate_section function. */
40193d8817e4Smiod if (info->shared
40203d8817e4Smiod && (info->symbolic || eh->dynindx == -1)
40213d8817e4Smiod && eh->def_regular)
40223d8817e4Smiod {
40233d8817e4Smiod rela.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
40243d8817e4Smiod rela.r_addend = (eh->root.u.def.value
40253d8817e4Smiod + eh->root.u.def.section->output_offset
40263d8817e4Smiod + eh->root.u.def.section->output_section->vma);
40273d8817e4Smiod }
40283d8817e4Smiod else
40293d8817e4Smiod {
40303d8817e4Smiod if ((eh->got.offset & 1) != 0)
40313d8817e4Smiod abort ();
40323d8817e4Smiod
40333d8817e4Smiod bfd_put_32 (output_bfd, 0, htab->sgot->contents + (eh->got.offset & ~1));
40343d8817e4Smiod rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_DIR32);
40353d8817e4Smiod rela.r_addend = 0;
40363d8817e4Smiod }
40373d8817e4Smiod
40383d8817e4Smiod loc = htab->srelgot->contents;
40393d8817e4Smiod loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
40403d8817e4Smiod bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
40413d8817e4Smiod }
40423d8817e4Smiod
40433d8817e4Smiod if (eh->needs_copy)
40443d8817e4Smiod {
40453d8817e4Smiod asection *sec;
40463d8817e4Smiod
40473d8817e4Smiod /* This symbol needs a copy reloc. Set it up. */
40483d8817e4Smiod
40493d8817e4Smiod if (! (eh->dynindx != -1
40503d8817e4Smiod && (eh->root.type == bfd_link_hash_defined
40513d8817e4Smiod || eh->root.type == bfd_link_hash_defweak)))
40523d8817e4Smiod abort ();
40533d8817e4Smiod
40543d8817e4Smiod sec = htab->srelbss;
40553d8817e4Smiod
40563d8817e4Smiod rela.r_offset = (eh->root.u.def.value
40573d8817e4Smiod + eh->root.u.def.section->output_offset
40583d8817e4Smiod + eh->root.u.def.section->output_section->vma);
40593d8817e4Smiod rela.r_addend = 0;
40603d8817e4Smiod rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_COPY);
40613d8817e4Smiod loc = sec->contents + sec->reloc_count++ * sizeof (Elf32_External_Rela);
40623d8817e4Smiod bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
40633d8817e4Smiod }
40643d8817e4Smiod
40653d8817e4Smiod /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
40663d8817e4Smiod if (eh->root.root.string[0] == '_'
40673d8817e4Smiod && (strcmp (eh->root.root.string, "_DYNAMIC") == 0
40683d8817e4Smiod || eh == htab->etab.hgot))
40693d8817e4Smiod {
40703d8817e4Smiod sym->st_shndx = SHN_ABS;
40713d8817e4Smiod }
40723d8817e4Smiod
40733d8817e4Smiod return TRUE;
40743d8817e4Smiod }
40753d8817e4Smiod
40763d8817e4Smiod /* Used to decide how to sort relocs in an optimal manner for the
40773d8817e4Smiod dynamic linker, before writing them out. */
40783d8817e4Smiod
40793d8817e4Smiod static enum elf_reloc_type_class
elf32_hppa_reloc_type_class(const Elf_Internal_Rela * rela)40803d8817e4Smiod elf32_hppa_reloc_type_class (const Elf_Internal_Rela *rela)
40813d8817e4Smiod {
40823d8817e4Smiod if (ELF32_R_SYM (rela->r_info) == 0)
40833d8817e4Smiod return reloc_class_relative;
40843d8817e4Smiod
40853d8817e4Smiod switch ((int) ELF32_R_TYPE (rela->r_info))
40863d8817e4Smiod {
40873d8817e4Smiod case R_PARISC_IPLT:
40883d8817e4Smiod return reloc_class_plt;
40893d8817e4Smiod case R_PARISC_COPY:
40903d8817e4Smiod return reloc_class_copy;
40913d8817e4Smiod default:
40923d8817e4Smiod return reloc_class_normal;
40933d8817e4Smiod }
40943d8817e4Smiod }
40953d8817e4Smiod
40963d8817e4Smiod /* Finish up the dynamic sections. */
40973d8817e4Smiod
40983d8817e4Smiod static bfd_boolean
elf32_hppa_finish_dynamic_sections(bfd * output_bfd,struct bfd_link_info * info)40993d8817e4Smiod elf32_hppa_finish_dynamic_sections (bfd *output_bfd,
41003d8817e4Smiod struct bfd_link_info *info)
41013d8817e4Smiod {
41023d8817e4Smiod bfd *dynobj;
41033d8817e4Smiod struct elf32_hppa_link_hash_table *htab;
41043d8817e4Smiod asection *sdyn;
41053d8817e4Smiod
41063d8817e4Smiod htab = hppa_link_hash_table (info);
41073d8817e4Smiod dynobj = htab->etab.dynobj;
41083d8817e4Smiod
41093d8817e4Smiod sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
41103d8817e4Smiod
41113d8817e4Smiod if (htab->etab.dynamic_sections_created)
41123d8817e4Smiod {
41133d8817e4Smiod Elf32_External_Dyn *dyncon, *dynconend;
41143d8817e4Smiod
41153d8817e4Smiod if (sdyn == NULL)
41163d8817e4Smiod abort ();
41173d8817e4Smiod
41183d8817e4Smiod dyncon = (Elf32_External_Dyn *) sdyn->contents;
41193d8817e4Smiod dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
41203d8817e4Smiod for (; dyncon < dynconend; dyncon++)
41213d8817e4Smiod {
41223d8817e4Smiod Elf_Internal_Dyn dyn;
41233d8817e4Smiod asection *s;
41243d8817e4Smiod
41253d8817e4Smiod bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
41263d8817e4Smiod
41273d8817e4Smiod switch (dyn.d_tag)
41283d8817e4Smiod {
41293d8817e4Smiod default:
41303d8817e4Smiod continue;
41313d8817e4Smiod
41323d8817e4Smiod case DT_PLTGOT:
41333d8817e4Smiod /* Use PLTGOT to set the GOT register. */
41343d8817e4Smiod dyn.d_un.d_ptr = elf_gp (output_bfd);
41353d8817e4Smiod break;
41363d8817e4Smiod
41373d8817e4Smiod case DT_JMPREL:
41383d8817e4Smiod s = htab->srelplt;
41393d8817e4Smiod dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
41403d8817e4Smiod break;
41413d8817e4Smiod
41423d8817e4Smiod case DT_PLTRELSZ:
41433d8817e4Smiod s = htab->srelplt;
41443d8817e4Smiod dyn.d_un.d_val = s->size;
41453d8817e4Smiod break;
41463d8817e4Smiod
41473d8817e4Smiod case DT_RELASZ:
41483d8817e4Smiod /* Don't count procedure linkage table relocs in the
41493d8817e4Smiod overall reloc count. */
41503d8817e4Smiod s = htab->srelplt;
41513d8817e4Smiod if (s == NULL)
41523d8817e4Smiod continue;
41533d8817e4Smiod dyn.d_un.d_val -= s->size;
41543d8817e4Smiod break;
41553d8817e4Smiod
41563d8817e4Smiod case DT_RELA:
41573d8817e4Smiod /* We may not be using the standard ELF linker script.
41583d8817e4Smiod If .rela.plt is the first .rela section, we adjust
41593d8817e4Smiod DT_RELA to not include it. */
41603d8817e4Smiod s = htab->srelplt;
41613d8817e4Smiod if (s == NULL)
41623d8817e4Smiod continue;
41633d8817e4Smiod if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
41643d8817e4Smiod continue;
41653d8817e4Smiod dyn.d_un.d_ptr += s->size;
41663d8817e4Smiod break;
41673d8817e4Smiod }
41683d8817e4Smiod
41693d8817e4Smiod bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
41703d8817e4Smiod }
41713d8817e4Smiod }
41723d8817e4Smiod
41733d8817e4Smiod if (htab->sgot != NULL && htab->sgot->size != 0)
41743d8817e4Smiod {
41753d8817e4Smiod /* Fill in the first entry in the global offset table.
41763d8817e4Smiod We use it to point to our dynamic section, if we have one. */
41773d8817e4Smiod bfd_put_32 (output_bfd,
41783d8817e4Smiod sdyn ? sdyn->output_section->vma + sdyn->output_offset : 0,
41793d8817e4Smiod htab->sgot->contents);
41803d8817e4Smiod
41813d8817e4Smiod /* The second entry is reserved for use by the dynamic linker. */
41823d8817e4Smiod memset (htab->sgot->contents + GOT_ENTRY_SIZE, 0, GOT_ENTRY_SIZE);
41833d8817e4Smiod
41843d8817e4Smiod /* Set .got entry size. */
41853d8817e4Smiod elf_section_data (htab->sgot->output_section)
41863d8817e4Smiod ->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
41873d8817e4Smiod }
41883d8817e4Smiod
41893d8817e4Smiod if (htab->splt != NULL && htab->splt->size != 0)
41903d8817e4Smiod {
41913d8817e4Smiod /* Set plt entry size. */
41923d8817e4Smiod elf_section_data (htab->splt->output_section)
41933d8817e4Smiod ->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
41943d8817e4Smiod
41953d8817e4Smiod if (htab->need_plt_stub)
41963d8817e4Smiod {
41973d8817e4Smiod /* Set up the .plt stub. */
41983d8817e4Smiod memcpy (htab->splt->contents
41993d8817e4Smiod + htab->splt->size - sizeof (plt_stub),
42003d8817e4Smiod plt_stub, sizeof (plt_stub));
42013d8817e4Smiod
42023d8817e4Smiod if ((htab->splt->output_offset
42033d8817e4Smiod + htab->splt->output_section->vma
42043d8817e4Smiod + htab->splt->size)
42053d8817e4Smiod != (htab->sgot->output_offset
42063d8817e4Smiod + htab->sgot->output_section->vma))
42073d8817e4Smiod {
42083d8817e4Smiod (*_bfd_error_handler)
42093d8817e4Smiod (_(".got section not immediately after .plt section"));
42103d8817e4Smiod return FALSE;
42113d8817e4Smiod }
42123d8817e4Smiod }
42133d8817e4Smiod }
42143d8817e4Smiod
42153d8817e4Smiod return TRUE;
42163d8817e4Smiod }
42173d8817e4Smiod
42183d8817e4Smiod /* Tweak the OSABI field of the elf header. */
42193d8817e4Smiod
42203d8817e4Smiod static void
elf32_hppa_post_process_headers(bfd * abfd,struct bfd_link_info * info ATTRIBUTE_UNUSED)42213d8817e4Smiod elf32_hppa_post_process_headers (bfd *abfd,
42223d8817e4Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED)
42233d8817e4Smiod {
42243d8817e4Smiod Elf_Internal_Ehdr * i_ehdrp;
42253d8817e4Smiod
42263d8817e4Smiod i_ehdrp = elf_elfheader (abfd);
42273d8817e4Smiod
42283d8817e4Smiod if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)
42293d8817e4Smiod {
42303d8817e4Smiod i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
42313d8817e4Smiod }
42323d8817e4Smiod else if (strcmp (bfd_get_target (abfd), "elf32-hppa-netbsd") == 0)
42333d8817e4Smiod {
42343d8817e4Smiod i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_NETBSD;
42353d8817e4Smiod }
42363d8817e4Smiod else
42373d8817e4Smiod {
42383d8817e4Smiod i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
42393d8817e4Smiod }
42403d8817e4Smiod }
42413d8817e4Smiod
42423d8817e4Smiod /* Called when writing out an object file to decide the type of a
42433d8817e4Smiod symbol. */
42443d8817e4Smiod static int
elf32_hppa_elf_get_symbol_type(Elf_Internal_Sym * elf_sym,int type)42453d8817e4Smiod elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
42463d8817e4Smiod {
42473d8817e4Smiod if (ELF_ST_TYPE (elf_sym->st_info) == STT_PARISC_MILLI)
42483d8817e4Smiod return STT_PARISC_MILLI;
42493d8817e4Smiod else
42503d8817e4Smiod return type;
42513d8817e4Smiod }
42523d8817e4Smiod
42533d8817e4Smiod /* Misc BFD support code. */
42543d8817e4Smiod #define bfd_elf32_bfd_is_local_label_name elf_hppa_is_local_label_name
42553d8817e4Smiod #define bfd_elf32_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup
42563d8817e4Smiod #define elf_info_to_howto elf_hppa_info_to_howto
42573d8817e4Smiod #define elf_info_to_howto_rel elf_hppa_info_to_howto_rel
42583d8817e4Smiod
42593d8817e4Smiod /* Stuff for the BFD linker. */
42603d8817e4Smiod #define bfd_elf32_bfd_final_link elf32_hppa_final_link
42613d8817e4Smiod #define bfd_elf32_bfd_link_hash_table_create elf32_hppa_link_hash_table_create
42623d8817e4Smiod #define bfd_elf32_bfd_link_hash_table_free elf32_hppa_link_hash_table_free
42633d8817e4Smiod #define elf_backend_adjust_dynamic_symbol elf32_hppa_adjust_dynamic_symbol
42643d8817e4Smiod #define elf_backend_copy_indirect_symbol elf32_hppa_copy_indirect_symbol
42653d8817e4Smiod #define elf_backend_check_relocs elf32_hppa_check_relocs
42663d8817e4Smiod #define elf_backend_create_dynamic_sections elf32_hppa_create_dynamic_sections
42673d8817e4Smiod #define elf_backend_fake_sections elf_hppa_fake_sections
42683d8817e4Smiod #define elf_backend_relocate_section elf32_hppa_relocate_section
42693d8817e4Smiod #define elf_backend_hide_symbol elf32_hppa_hide_symbol
42703d8817e4Smiod #define elf_backend_finish_dynamic_symbol elf32_hppa_finish_dynamic_symbol
42713d8817e4Smiod #define elf_backend_finish_dynamic_sections elf32_hppa_finish_dynamic_sections
42723d8817e4Smiod #define elf_backend_size_dynamic_sections elf32_hppa_size_dynamic_sections
42733d8817e4Smiod #define elf_backend_gc_mark_hook elf32_hppa_gc_mark_hook
42743d8817e4Smiod #define elf_backend_gc_sweep_hook elf32_hppa_gc_sweep_hook
42753d8817e4Smiod #define elf_backend_grok_prstatus elf32_hppa_grok_prstatus
42763d8817e4Smiod #define elf_backend_grok_psinfo elf32_hppa_grok_psinfo
42773d8817e4Smiod #define elf_backend_object_p elf32_hppa_object_p
42783d8817e4Smiod #define elf_backend_final_write_processing elf_hppa_final_write_processing
42793d8817e4Smiod #define elf_backend_post_process_headers elf32_hppa_post_process_headers
42803d8817e4Smiod #define elf_backend_get_symbol_type elf32_hppa_elf_get_symbol_type
42813d8817e4Smiod #define elf_backend_reloc_type_class elf32_hppa_reloc_type_class
42823d8817e4Smiod #define elf_backend_action_discarded elf_hppa_action_discarded
42833d8817e4Smiod
42843d8817e4Smiod #define elf_backend_can_gc_sections 1
42853d8817e4Smiod #define elf_backend_can_refcount 1
42863d8817e4Smiod #define elf_backend_plt_alignment 2
42873d8817e4Smiod #define elf_backend_want_got_plt 0
42883d8817e4Smiod #define elf_backend_plt_readonly 0
42893d8817e4Smiod #define elf_backend_want_plt_sym 0
42903d8817e4Smiod #define elf_backend_got_header_size 8
42913d8817e4Smiod #define elf_backend_rela_normal 1
42923d8817e4Smiod
42933d8817e4Smiod #define TARGET_BIG_SYM bfd_elf32_hppa_vec
42943d8817e4Smiod #define TARGET_BIG_NAME "elf32-hppa"
42953d8817e4Smiod #define ELF_ARCH bfd_arch_hppa
42963d8817e4Smiod #define ELF_MACHINE_CODE EM_PARISC
42973d8817e4Smiod #define ELF_MAXPAGESIZE 0x1000
42983d8817e4Smiod
42993d8817e4Smiod #include "elf32-target.h"
43003d8817e4Smiod
43013d8817e4Smiod #undef TARGET_BIG_SYM
43023d8817e4Smiod #define TARGET_BIG_SYM bfd_elf32_hppa_linux_vec
43033d8817e4Smiod #undef TARGET_BIG_NAME
43043d8817e4Smiod #define TARGET_BIG_NAME "elf32-hppa-linux"
43053d8817e4Smiod
43063d8817e4Smiod #define INCLUDED_TARGET_FILE 1
43073d8817e4Smiod #include "elf32-target.h"
43083d8817e4Smiod
43093d8817e4Smiod #undef TARGET_BIG_SYM
43103d8817e4Smiod #define TARGET_BIG_SYM bfd_elf32_hppa_nbsd_vec
43113d8817e4Smiod #undef TARGET_BIG_NAME
43123d8817e4Smiod #define TARGET_BIG_NAME "elf32-hppa-netbsd"
43133d8817e4Smiod
43143d8817e4Smiod #include "elf32-target.h"
4315