xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/elf32-hppa.c (revision 39e16c998637bb26aefdefcd2c660c5929081b00)
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