xref: /openbsd-src/gnu/usr.bin/binutils/bfd/elf64-hppa.c (revision 2d6de53b6832b1a63b46fdbe0f539ec82f5350ac)
15f210c2aSfgsch /* Support for HPPA 64-bit ELF
2cf2f2c56Smiod    Copyright 1999, 2000, 2001, 2002, 2003, 2004
3cf2f2c56Smiod    Free Software Foundation, Inc.
45f210c2aSfgsch 
55f210c2aSfgsch    This file is part of BFD, the Binary File Descriptor library.
65f210c2aSfgsch 
75f210c2aSfgsch    This program is free software; you can redistribute it and/or modify
85f210c2aSfgsch    it under the terms of the GNU General Public License as published by
95f210c2aSfgsch    the Free Software Foundation; either version 2 of the License, or
105f210c2aSfgsch    (at your option) any later version.
115f210c2aSfgsch 
125f210c2aSfgsch    This program is distributed in the hope that it will be useful,
135f210c2aSfgsch    but WITHOUT ANY WARRANTY; without even the implied warranty of
145f210c2aSfgsch    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155f210c2aSfgsch    GNU General Public License for more details.
165f210c2aSfgsch 
175f210c2aSfgsch    You should have received a copy of the GNU General Public License
185f210c2aSfgsch    along with this program; if not, write to the Free Software
195f210c2aSfgsch    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
205f210c2aSfgsch 
215f210c2aSfgsch #include "alloca-conf.h"
225f210c2aSfgsch #include "bfd.h"
235f210c2aSfgsch #include "sysdep.h"
245f210c2aSfgsch #include "libbfd.h"
255f210c2aSfgsch #include "elf-bfd.h"
265f210c2aSfgsch #include "elf/hppa.h"
275f210c2aSfgsch #include "libhppa.h"
285f210c2aSfgsch #include "elf64-hppa.h"
295f210c2aSfgsch #define ARCH_SIZE	       64
305f210c2aSfgsch 
315f210c2aSfgsch #define PLT_ENTRY_SIZE 0x10
325f210c2aSfgsch #define DLT_ENTRY_SIZE 0x8
335f210c2aSfgsch #define OPD_ENTRY_SIZE 0x20
345f210c2aSfgsch 
355f210c2aSfgsch #define ELF_DYNAMIC_INTERPRETER "/usr/lib/pa20_64/dld.sl"
365f210c2aSfgsch 
375f210c2aSfgsch /* The stub is supposed to load the target address and target's DP
385f210c2aSfgsch    value out of the PLT, then do an external branch to the target
395f210c2aSfgsch    address.
405f210c2aSfgsch 
415f210c2aSfgsch    LDD PLTOFF(%r27),%r1
425f210c2aSfgsch    BVE (%r1)
435f210c2aSfgsch    LDD PLTOFF+8(%r27),%r27
445f210c2aSfgsch 
455f210c2aSfgsch    Note that we must use the LDD with a 14 bit displacement, not the one
465f210c2aSfgsch    with a 5 bit displacement.  */
475f210c2aSfgsch static char plt_stub[] = {0x53, 0x61, 0x00, 0x00, 0xe8, 0x20, 0xd0, 0x00,
485f210c2aSfgsch 			  0x53, 0x7b, 0x00, 0x00 };
495f210c2aSfgsch 
505f210c2aSfgsch struct elf64_hppa_dyn_hash_entry
515f210c2aSfgsch {
525f210c2aSfgsch   struct bfd_hash_entry root;
535f210c2aSfgsch 
545f210c2aSfgsch   /* Offsets for this symbol in various linker sections.  */
555f210c2aSfgsch   bfd_vma dlt_offset;
565f210c2aSfgsch   bfd_vma plt_offset;
575f210c2aSfgsch   bfd_vma opd_offset;
585f210c2aSfgsch   bfd_vma stub_offset;
595f210c2aSfgsch 
605f210c2aSfgsch   /* The symbol table entry, if any, that this was derived from.  */
615f210c2aSfgsch   struct elf_link_hash_entry *h;
625f210c2aSfgsch 
635f210c2aSfgsch   /* The index of the (possibly local) symbol in the input bfd and its
645f210c2aSfgsch      associated BFD.  Needed so that we can have relocs against local
655f210c2aSfgsch      symbols in shared libraries.  */
66d2201f2fSdrahn   long sym_indx;
675f210c2aSfgsch   bfd *owner;
685f210c2aSfgsch 
695f210c2aSfgsch   /* Dynamic symbols may need to have two different values.  One for
705f210c2aSfgsch      the dynamic symbol table, one for the normal symbol table.
715f210c2aSfgsch 
725f210c2aSfgsch      In such cases we store the symbol's real value and section
735f210c2aSfgsch      index here so we can restore the real value before we write
745f210c2aSfgsch      the normal symbol table.  */
755f210c2aSfgsch   bfd_vma st_value;
765f210c2aSfgsch   int st_shndx;
775f210c2aSfgsch 
785f210c2aSfgsch   /* Used to count non-got, non-plt relocations for delayed sizing
795f210c2aSfgsch      of relocation sections.  */
805f210c2aSfgsch   struct elf64_hppa_dyn_reloc_entry
815f210c2aSfgsch   {
825f210c2aSfgsch     /* Next relocation in the chain.  */
835f210c2aSfgsch     struct elf64_hppa_dyn_reloc_entry *next;
845f210c2aSfgsch 
855f210c2aSfgsch     /* The type of the relocation.  */
865f210c2aSfgsch     int type;
875f210c2aSfgsch 
885f210c2aSfgsch     /* The input section of the relocation.  */
895f210c2aSfgsch     asection *sec;
905f210c2aSfgsch 
915f210c2aSfgsch     /* The index of the section symbol for the input section of
925f210c2aSfgsch        the relocation.  Only needed when building shared libraries.  */
935f210c2aSfgsch     int sec_symndx;
945f210c2aSfgsch 
955f210c2aSfgsch     /* The offset within the input section of the relocation.  */
965f210c2aSfgsch     bfd_vma offset;
975f210c2aSfgsch 
985f210c2aSfgsch     /* The addend for the relocation.  */
995f210c2aSfgsch     bfd_vma addend;
1005f210c2aSfgsch 
1015f210c2aSfgsch   } *reloc_entries;
1025f210c2aSfgsch 
1035f210c2aSfgsch   /* Nonzero if this symbol needs an entry in one of the linker
1045f210c2aSfgsch      sections.  */
1055f210c2aSfgsch   unsigned want_dlt;
1065f210c2aSfgsch   unsigned want_plt;
1075f210c2aSfgsch   unsigned want_opd;
1085f210c2aSfgsch   unsigned want_stub;
1095f210c2aSfgsch };
1105f210c2aSfgsch 
1115f210c2aSfgsch struct elf64_hppa_dyn_hash_table
1125f210c2aSfgsch {
1135f210c2aSfgsch   struct bfd_hash_table root;
1145f210c2aSfgsch };
1155f210c2aSfgsch 
1165f210c2aSfgsch struct elf64_hppa_link_hash_table
1175f210c2aSfgsch {
1185f210c2aSfgsch   struct elf_link_hash_table root;
1195f210c2aSfgsch 
1205f210c2aSfgsch   /* Shortcuts to get to the various linker defined sections.  */
1215f210c2aSfgsch   asection *dlt_sec;
1225f210c2aSfgsch   asection *dlt_rel_sec;
1235f210c2aSfgsch   asection *plt_sec;
1245f210c2aSfgsch   asection *plt_rel_sec;
1255f210c2aSfgsch   asection *opd_sec;
1265f210c2aSfgsch   asection *opd_rel_sec;
1275f210c2aSfgsch   asection *other_rel_sec;
1285f210c2aSfgsch 
1295f210c2aSfgsch   /* Offset of __gp within .plt section.  When the PLT gets large we want
1305f210c2aSfgsch      to slide __gp into the PLT section so that we can continue to use
1315f210c2aSfgsch      single DP relative instructions to load values out of the PLT.  */
1325f210c2aSfgsch   bfd_vma gp_offset;
1335f210c2aSfgsch 
1345f210c2aSfgsch   /* Note this is not strictly correct.  We should create a stub section for
1355f210c2aSfgsch      each input section with calls.  The stub section should be placed before
1365f210c2aSfgsch      the section with the call.  */
1375f210c2aSfgsch   asection *stub_sec;
1385f210c2aSfgsch 
1395f210c2aSfgsch   bfd_vma text_segment_base;
1405f210c2aSfgsch   bfd_vma data_segment_base;
1415f210c2aSfgsch 
1425f210c2aSfgsch   struct elf64_hppa_dyn_hash_table dyn_hash_table;
1435f210c2aSfgsch 
1445f210c2aSfgsch   /* We build tables to map from an input section back to its
1455f210c2aSfgsch      symbol index.  This is the BFD for which we currently have
1465f210c2aSfgsch      a map.  */
1475f210c2aSfgsch   bfd *section_syms_bfd;
1485f210c2aSfgsch 
1495f210c2aSfgsch   /* Array of symbol numbers for each input section attached to the
1505f210c2aSfgsch      current BFD.  */
1515f210c2aSfgsch   int *section_syms;
1525f210c2aSfgsch };
1535f210c2aSfgsch 
1545f210c2aSfgsch #define elf64_hppa_hash_table(p) \
1555f210c2aSfgsch   ((struct elf64_hppa_link_hash_table *) ((p)->hash))
1565f210c2aSfgsch 
1575f210c2aSfgsch typedef struct bfd_hash_entry *(*new_hash_entry_func)
1585f210c2aSfgsch   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
1595f210c2aSfgsch 
160d2201f2fSdrahn static bfd_boolean elf64_hppa_dyn_hash_table_init
1615f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_table *ht, bfd *abfd,
1625f210c2aSfgsch 	   new_hash_entry_func new));
1635f210c2aSfgsch static struct bfd_hash_entry *elf64_hppa_new_dyn_hash_entry
1645f210c2aSfgsch   PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
1655f210c2aSfgsch 	   const char *string));
1665f210c2aSfgsch static struct bfd_link_hash_table *elf64_hppa_hash_table_create
1675f210c2aSfgsch   PARAMS ((bfd *abfd));
1685f210c2aSfgsch static struct elf64_hppa_dyn_hash_entry *elf64_hppa_dyn_hash_lookup
1695f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_table *table, const char *string,
170d2201f2fSdrahn 	   bfd_boolean create, bfd_boolean copy));
1715f210c2aSfgsch static void elf64_hppa_dyn_hash_traverse
1725f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_table *table,
173d2201f2fSdrahn 	   bfd_boolean (*func) (struct elf64_hppa_dyn_hash_entry *, PTR),
1745f210c2aSfgsch 	   PTR info));
1755f210c2aSfgsch 
1765f210c2aSfgsch static const char *get_dyn_name
177cf2f2c56Smiod   PARAMS ((bfd *, struct elf_link_hash_entry *,
1785f210c2aSfgsch 	   const Elf_Internal_Rela *, char **, size_t *));
1795f210c2aSfgsch 
1805f210c2aSfgsch /* This must follow the definitions of the various derived linker
1815f210c2aSfgsch    hash tables and shared functions.  */
1825f210c2aSfgsch #include "elf-hppa.h"
1835f210c2aSfgsch 
184d2201f2fSdrahn static bfd_boolean elf64_hppa_object_p
1855f210c2aSfgsch   PARAMS ((bfd *));
1865f210c2aSfgsch 
187d2201f2fSdrahn static bfd_boolean elf64_hppa_section_from_shdr
188d2201f2fSdrahn   PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
1895f210c2aSfgsch 
1905f210c2aSfgsch static void elf64_hppa_post_process_headers
1915f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *));
1925f210c2aSfgsch 
193d2201f2fSdrahn static bfd_boolean elf64_hppa_create_dynamic_sections
1945f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *));
1955f210c2aSfgsch 
196d2201f2fSdrahn static bfd_boolean elf64_hppa_adjust_dynamic_symbol
1975f210c2aSfgsch   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
1985f210c2aSfgsch 
199d2201f2fSdrahn static bfd_boolean elf64_hppa_mark_milli_and_exported_functions
200d2201f2fSdrahn   PARAMS ((struct elf_link_hash_entry *, PTR));
201d2201f2fSdrahn 
202d2201f2fSdrahn static bfd_boolean elf64_hppa_size_dynamic_sections
2035f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *));
2045f210c2aSfgsch 
205d2201f2fSdrahn static bfd_boolean elf64_hppa_link_output_symbol_hook
206cf2f2c56Smiod   PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
207cf2f2c56Smiod 	   asection *, struct elf_link_hash_entry *));
208d2201f2fSdrahn 
209d2201f2fSdrahn static bfd_boolean elf64_hppa_finish_dynamic_symbol
2105f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *,
2115f210c2aSfgsch 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
2125f210c2aSfgsch 
213d2201f2fSdrahn static int elf64_hppa_additional_program_headers
214d2201f2fSdrahn   PARAMS ((bfd *));
215d2201f2fSdrahn 
216d2201f2fSdrahn static bfd_boolean elf64_hppa_modify_segment_map
217cf2f2c56Smiod   PARAMS ((bfd *, struct bfd_link_info *));
218d2201f2fSdrahn 
219d2201f2fSdrahn static enum elf_reloc_type_class elf64_hppa_reloc_type_class
220d2201f2fSdrahn   PARAMS ((const Elf_Internal_Rela *));
221d2201f2fSdrahn 
222d2201f2fSdrahn static bfd_boolean elf64_hppa_finish_dynamic_sections
2235f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *));
2245f210c2aSfgsch 
225d2201f2fSdrahn static bfd_boolean elf64_hppa_check_relocs
2265f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *,
2275f210c2aSfgsch 	   asection *, const Elf_Internal_Rela *));
2285f210c2aSfgsch 
229d2201f2fSdrahn static bfd_boolean elf64_hppa_dynamic_symbol_p
2305f210c2aSfgsch   PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
2315f210c2aSfgsch 
232d2201f2fSdrahn static bfd_boolean elf64_hppa_mark_exported_functions
2335f210c2aSfgsch   PARAMS ((struct elf_link_hash_entry *, PTR));
2345f210c2aSfgsch 
235d2201f2fSdrahn static bfd_boolean elf64_hppa_finalize_opd
2365f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2375f210c2aSfgsch 
238d2201f2fSdrahn static bfd_boolean elf64_hppa_finalize_dlt
2395f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2405f210c2aSfgsch 
241d2201f2fSdrahn static bfd_boolean allocate_global_data_dlt
2425f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2435f210c2aSfgsch 
244d2201f2fSdrahn static bfd_boolean allocate_global_data_plt
2455f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2465f210c2aSfgsch 
247d2201f2fSdrahn static bfd_boolean allocate_global_data_stub
2485f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2495f210c2aSfgsch 
250d2201f2fSdrahn static bfd_boolean allocate_global_data_opd
2515f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2525f210c2aSfgsch 
253d2201f2fSdrahn static bfd_boolean get_reloc_section
2545f210c2aSfgsch   PARAMS ((bfd *, struct elf64_hppa_link_hash_table *, asection *));
2555f210c2aSfgsch 
256d2201f2fSdrahn static bfd_boolean count_dyn_reloc
2575f210c2aSfgsch   PARAMS ((bfd *, struct elf64_hppa_dyn_hash_entry *,
2585f210c2aSfgsch 	   int, asection *, int, bfd_vma, bfd_vma));
2595f210c2aSfgsch 
260d2201f2fSdrahn static bfd_boolean allocate_dynrel_entries
2615f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2625f210c2aSfgsch 
263d2201f2fSdrahn static bfd_boolean elf64_hppa_finalize_dynreloc
2645f210c2aSfgsch   PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
2655f210c2aSfgsch 
266d2201f2fSdrahn static bfd_boolean get_opd
2675f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
2685f210c2aSfgsch 
269d2201f2fSdrahn static bfd_boolean get_plt
2705f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
2715f210c2aSfgsch 
272d2201f2fSdrahn static bfd_boolean get_dlt
2735f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
2745f210c2aSfgsch 
275d2201f2fSdrahn static bfd_boolean get_stub
2765f210c2aSfgsch   PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));
2775f210c2aSfgsch 
2785f210c2aSfgsch static int elf64_hppa_elf_get_symbol_type
2795f210c2aSfgsch   PARAMS ((Elf_Internal_Sym *, int));
2805f210c2aSfgsch 
281d2201f2fSdrahn static bfd_boolean
elf64_hppa_dyn_hash_table_init(ht,abfd,new)2825f210c2aSfgsch elf64_hppa_dyn_hash_table_init (ht, abfd, new)
2835f210c2aSfgsch      struct elf64_hppa_dyn_hash_table *ht;
2845f210c2aSfgsch      bfd *abfd ATTRIBUTE_UNUSED;
2855f210c2aSfgsch      new_hash_entry_func new;
2865f210c2aSfgsch {
2875f210c2aSfgsch   memset (ht, 0, sizeof (*ht));
2885f210c2aSfgsch   return bfd_hash_table_init (&ht->root, new);
2895f210c2aSfgsch }
2905f210c2aSfgsch 
2915f210c2aSfgsch static struct bfd_hash_entry*
elf64_hppa_new_dyn_hash_entry(entry,table,string)2925f210c2aSfgsch elf64_hppa_new_dyn_hash_entry (entry, table, string)
2935f210c2aSfgsch      struct bfd_hash_entry *entry;
2945f210c2aSfgsch      struct bfd_hash_table *table;
2955f210c2aSfgsch      const char *string;
2965f210c2aSfgsch {
2975f210c2aSfgsch   struct elf64_hppa_dyn_hash_entry *ret;
2985f210c2aSfgsch   ret = (struct elf64_hppa_dyn_hash_entry *) entry;
2995f210c2aSfgsch 
3005f210c2aSfgsch   /* Allocate the structure if it has not already been allocated by a
3015f210c2aSfgsch      subclass.  */
3025f210c2aSfgsch   if (!ret)
3035f210c2aSfgsch     ret = bfd_hash_allocate (table, sizeof (*ret));
3045f210c2aSfgsch 
3055f210c2aSfgsch   if (!ret)
3065f210c2aSfgsch     return 0;
3075f210c2aSfgsch 
3085f210c2aSfgsch   /* Initialize our local data.  All zeros, and definitely easier
3095f210c2aSfgsch      than setting 8 bit fields.  */
3105f210c2aSfgsch   memset (ret, 0, sizeof (*ret));
3115f210c2aSfgsch 
3125f210c2aSfgsch   /* Call the allocation method of the superclass.  */
3135f210c2aSfgsch   ret = ((struct elf64_hppa_dyn_hash_entry *)
3145f210c2aSfgsch 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
3155f210c2aSfgsch 
3165f210c2aSfgsch   return &ret->root;
3175f210c2aSfgsch }
3185f210c2aSfgsch 
3195f210c2aSfgsch /* Create the derived linker hash table.  The PA64 ELF port uses this
3205f210c2aSfgsch    derived hash table to keep information specific to the PA ElF
3215f210c2aSfgsch    linker (without using static variables).  */
3225f210c2aSfgsch 
3235f210c2aSfgsch static struct bfd_link_hash_table*
elf64_hppa_hash_table_create(abfd)3245f210c2aSfgsch elf64_hppa_hash_table_create (abfd)
3255f210c2aSfgsch      bfd *abfd;
3265f210c2aSfgsch {
3275f210c2aSfgsch   struct elf64_hppa_link_hash_table *ret;
3285f210c2aSfgsch 
329d2201f2fSdrahn   ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret));
3305f210c2aSfgsch   if (!ret)
3315f210c2aSfgsch     return 0;
3325f210c2aSfgsch   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
3335f210c2aSfgsch 				      _bfd_elf_link_hash_newfunc))
3345f210c2aSfgsch     {
3355f210c2aSfgsch       bfd_release (abfd, ret);
3365f210c2aSfgsch       return 0;
3375f210c2aSfgsch     }
3385f210c2aSfgsch 
3395f210c2aSfgsch   if (!elf64_hppa_dyn_hash_table_init (&ret->dyn_hash_table, abfd,
3405f210c2aSfgsch 				       elf64_hppa_new_dyn_hash_entry))
3415f210c2aSfgsch     return 0;
3425f210c2aSfgsch   return &ret->root.root;
3435f210c2aSfgsch }
3445f210c2aSfgsch 
3455f210c2aSfgsch /* Look up an entry in a PA64 ELF linker hash table.  */
3465f210c2aSfgsch 
3475f210c2aSfgsch static struct elf64_hppa_dyn_hash_entry *
elf64_hppa_dyn_hash_lookup(table,string,create,copy)3485f210c2aSfgsch elf64_hppa_dyn_hash_lookup(table, string, create, copy)
3495f210c2aSfgsch      struct elf64_hppa_dyn_hash_table *table;
3505f210c2aSfgsch      const char *string;
351d2201f2fSdrahn      bfd_boolean create, copy;
3525f210c2aSfgsch {
3535f210c2aSfgsch   return ((struct elf64_hppa_dyn_hash_entry *)
3545f210c2aSfgsch 	  bfd_hash_lookup (&table->root, string, create, copy));
3555f210c2aSfgsch }
3565f210c2aSfgsch 
3575f210c2aSfgsch /* Traverse a PA64 ELF linker hash table.  */
3585f210c2aSfgsch 
3595f210c2aSfgsch static void
elf64_hppa_dyn_hash_traverse(table,func,info)3605f210c2aSfgsch elf64_hppa_dyn_hash_traverse (table, func, info)
3615f210c2aSfgsch      struct elf64_hppa_dyn_hash_table *table;
362d2201f2fSdrahn      bfd_boolean (*func) PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));
3635f210c2aSfgsch      PTR info;
3645f210c2aSfgsch {
3655f210c2aSfgsch   (bfd_hash_traverse
3665f210c2aSfgsch    (&table->root,
367d2201f2fSdrahn     (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) func,
3685f210c2aSfgsch     info));
3695f210c2aSfgsch }
3705f210c2aSfgsch 
3715f210c2aSfgsch /* Return nonzero if ABFD represents a PA2.0 ELF64 file.
3725f210c2aSfgsch 
3735f210c2aSfgsch    Additionally we set the default architecture and machine.  */
374d2201f2fSdrahn static bfd_boolean
elf64_hppa_object_p(abfd)3755f210c2aSfgsch elf64_hppa_object_p (abfd)
3765f210c2aSfgsch      bfd *abfd;
3775f210c2aSfgsch {
3785f210c2aSfgsch   Elf_Internal_Ehdr * i_ehdrp;
3795f210c2aSfgsch   unsigned int flags;
3805f210c2aSfgsch 
3815f210c2aSfgsch   i_ehdrp = elf_elfheader (abfd);
3825f210c2aSfgsch   if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)
3835f210c2aSfgsch     {
384cf2f2c56Smiod       /* GCC on hppa-linux produces binaries with OSABI=Linux,
385cf2f2c56Smiod 	 but the kernel produces corefiles with OSABI=SysV.  */
386cf2f2c56Smiod       if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX &&
387cf2f2c56Smiod 	  i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
388d2201f2fSdrahn 	return FALSE;
3895f210c2aSfgsch     }
3905f210c2aSfgsch   else
3915f210c2aSfgsch     {
3925f210c2aSfgsch       if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
393d2201f2fSdrahn 	return FALSE;
3945f210c2aSfgsch     }
3955f210c2aSfgsch 
3965f210c2aSfgsch   flags = i_ehdrp->e_flags;
3975f210c2aSfgsch   switch (flags & (EF_PARISC_ARCH | EF_PARISC_WIDE))
3985f210c2aSfgsch     {
3995f210c2aSfgsch     case EFA_PARISC_1_0:
4005f210c2aSfgsch       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 10);
4015f210c2aSfgsch     case EFA_PARISC_1_1:
4025f210c2aSfgsch       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 11);
4035f210c2aSfgsch     case EFA_PARISC_2_0:
4045f210c2aSfgsch       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);
4055f210c2aSfgsch     case EFA_PARISC_2_0 | EF_PARISC_WIDE:
4065f210c2aSfgsch       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
4075f210c2aSfgsch     }
4085f210c2aSfgsch   /* Don't be fussy.  */
409d2201f2fSdrahn   return TRUE;
4105f210c2aSfgsch }
4115f210c2aSfgsch 
4125f210c2aSfgsch /* Given section type (hdr->sh_type), return a boolean indicating
4135f210c2aSfgsch    whether or not the section is an elf64-hppa specific section.  */
414d2201f2fSdrahn static bfd_boolean
elf64_hppa_section_from_shdr(abfd,hdr,name)4155f210c2aSfgsch elf64_hppa_section_from_shdr (abfd, hdr, name)
4165f210c2aSfgsch      bfd *abfd;
417d2201f2fSdrahn      Elf_Internal_Shdr *hdr;
418d2201f2fSdrahn      const char *name;
4195f210c2aSfgsch {
4205f210c2aSfgsch   asection *newsect;
4215f210c2aSfgsch 
4225f210c2aSfgsch   switch (hdr->sh_type)
4235f210c2aSfgsch     {
4245f210c2aSfgsch     case SHT_PARISC_EXT:
4255f210c2aSfgsch       if (strcmp (name, ".PARISC.archext") != 0)
426d2201f2fSdrahn 	return FALSE;
4275f210c2aSfgsch       break;
4285f210c2aSfgsch     case SHT_PARISC_UNWIND:
4295f210c2aSfgsch       if (strcmp (name, ".PARISC.unwind") != 0)
430d2201f2fSdrahn 	return FALSE;
4315f210c2aSfgsch       break;
4325f210c2aSfgsch     case SHT_PARISC_DOC:
4335f210c2aSfgsch     case SHT_PARISC_ANNOT:
4345f210c2aSfgsch     default:
435d2201f2fSdrahn       return FALSE;
4365f210c2aSfgsch     }
4375f210c2aSfgsch 
4385f210c2aSfgsch   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
439d2201f2fSdrahn     return FALSE;
4405f210c2aSfgsch   newsect = hdr->bfd_section;
4415f210c2aSfgsch 
442d2201f2fSdrahn   return TRUE;
4435f210c2aSfgsch }
4445f210c2aSfgsch 
4455f210c2aSfgsch /* Construct a string for use in the elf64_hppa_dyn_hash_table.  The
4465f210c2aSfgsch    name describes what was once potentially anonymous memory.  We
4475f210c2aSfgsch    allocate memory as necessary, possibly reusing PBUF/PLEN.  */
4485f210c2aSfgsch 
4495f210c2aSfgsch static const char *
get_dyn_name(abfd,h,rel,pbuf,plen)450cf2f2c56Smiod get_dyn_name (abfd, h, rel, pbuf, plen)
451cf2f2c56Smiod      bfd *abfd;
4525f210c2aSfgsch      struct elf_link_hash_entry *h;
4535f210c2aSfgsch      const Elf_Internal_Rela *rel;
4545f210c2aSfgsch      char **pbuf;
4555f210c2aSfgsch      size_t *plen;
4565f210c2aSfgsch {
457cf2f2c56Smiod   asection *sec = abfd->sections;
4585f210c2aSfgsch   size_t nlen, tlen;
4595f210c2aSfgsch   char *buf;
4605f210c2aSfgsch   size_t len;
4615f210c2aSfgsch 
4625f210c2aSfgsch   if (h && rel->r_addend == 0)
4635f210c2aSfgsch     return h->root.root.string;
4645f210c2aSfgsch 
4655f210c2aSfgsch   if (h)
4665f210c2aSfgsch     nlen = strlen (h->root.root.string);
4675f210c2aSfgsch   else
4685f210c2aSfgsch     nlen = 8 + 1 + sizeof (rel->r_info) * 2 - 8;
4695f210c2aSfgsch   tlen = nlen + 1 + sizeof (rel->r_addend) * 2 + 1;
4705f210c2aSfgsch 
4715f210c2aSfgsch   len = *plen;
4725f210c2aSfgsch   buf = *pbuf;
4735f210c2aSfgsch   if (len < tlen)
4745f210c2aSfgsch     {
4755f210c2aSfgsch       if (buf)
4765f210c2aSfgsch 	free (buf);
4775f210c2aSfgsch       *pbuf = buf = malloc (tlen);
4785f210c2aSfgsch       *plen = len = tlen;
4795f210c2aSfgsch       if (!buf)
4805f210c2aSfgsch 	return NULL;
4815f210c2aSfgsch     }
4825f210c2aSfgsch 
4835f210c2aSfgsch   if (h)
4845f210c2aSfgsch     {
4855f210c2aSfgsch       memcpy (buf, h->root.root.string, nlen);
4865f210c2aSfgsch       buf[nlen++] = '+';
4875f210c2aSfgsch       sprintf_vma (buf + nlen, rel->r_addend);
4885f210c2aSfgsch     }
4895f210c2aSfgsch   else
4905f210c2aSfgsch     {
4915f210c2aSfgsch       nlen = sprintf (buf, "%x:%lx",
4925f210c2aSfgsch 		      sec->id & 0xffffffff,
4935f210c2aSfgsch 		      (long) ELF64_R_SYM (rel->r_info));
4945f210c2aSfgsch       if (rel->r_addend)
4955f210c2aSfgsch 	{
4965f210c2aSfgsch 	  buf[nlen++] = '+';
4975f210c2aSfgsch 	  sprintf_vma (buf + nlen, rel->r_addend);
4985f210c2aSfgsch 	}
4995f210c2aSfgsch     }
5005f210c2aSfgsch 
5015f210c2aSfgsch   return buf;
5025f210c2aSfgsch }
5035f210c2aSfgsch 
5045f210c2aSfgsch /* SEC is a section containing relocs for an input BFD when linking; return
5055f210c2aSfgsch    a suitable section for holding relocs in the output BFD for a link.  */
5065f210c2aSfgsch 
507d2201f2fSdrahn static bfd_boolean
get_reloc_section(abfd,hppa_info,sec)5085f210c2aSfgsch get_reloc_section (abfd, hppa_info, sec)
5095f210c2aSfgsch      bfd *abfd;
5105f210c2aSfgsch      struct elf64_hppa_link_hash_table *hppa_info;
5115f210c2aSfgsch      asection *sec;
5125f210c2aSfgsch {
5135f210c2aSfgsch   const char *srel_name;
5145f210c2aSfgsch   asection *srel;
5155f210c2aSfgsch   bfd *dynobj;
5165f210c2aSfgsch 
5175f210c2aSfgsch   srel_name = (bfd_elf_string_from_elf_section
5185f210c2aSfgsch 	       (abfd, elf_elfheader(abfd)->e_shstrndx,
5195f210c2aSfgsch 		elf_section_data(sec)->rel_hdr.sh_name));
5205f210c2aSfgsch   if (srel_name == NULL)
521d2201f2fSdrahn     return FALSE;
5225f210c2aSfgsch 
5235f210c2aSfgsch   BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
5245f210c2aSfgsch 	       && strcmp (bfd_get_section_name (abfd, sec),
5255f210c2aSfgsch 			  srel_name+5) == 0)
5265f210c2aSfgsch 	      || (strncmp (srel_name, ".rel", 4) == 0
5275f210c2aSfgsch 		  && strcmp (bfd_get_section_name (abfd, sec),
5285f210c2aSfgsch 			     srel_name+4) == 0));
5295f210c2aSfgsch 
5305f210c2aSfgsch   dynobj = hppa_info->root.dynobj;
5315f210c2aSfgsch   if (!dynobj)
5325f210c2aSfgsch     hppa_info->root.dynobj = dynobj = abfd;
5335f210c2aSfgsch 
5345f210c2aSfgsch   srel = bfd_get_section_by_name (dynobj, srel_name);
5355f210c2aSfgsch   if (srel == NULL)
5365f210c2aSfgsch     {
5375f210c2aSfgsch       srel = bfd_make_section (dynobj, srel_name);
5385f210c2aSfgsch       if (srel == NULL
5395f210c2aSfgsch 	  || !bfd_set_section_flags (dynobj, srel,
5405f210c2aSfgsch 				     (SEC_ALLOC
5415f210c2aSfgsch 				      | SEC_LOAD
5425f210c2aSfgsch 				      | SEC_HAS_CONTENTS
5435f210c2aSfgsch 				      | SEC_IN_MEMORY
5445f210c2aSfgsch 				      | SEC_LINKER_CREATED
5455f210c2aSfgsch 				      | SEC_READONLY))
5465f210c2aSfgsch 	  || !bfd_set_section_alignment (dynobj, srel, 3))
547d2201f2fSdrahn 	return FALSE;
5485f210c2aSfgsch     }
5495f210c2aSfgsch 
5505f210c2aSfgsch   hppa_info->other_rel_sec = srel;
551d2201f2fSdrahn   return TRUE;
5525f210c2aSfgsch }
5535f210c2aSfgsch 
5545f210c2aSfgsch /* Add a new entry to the list of dynamic relocations against DYN_H.
5555f210c2aSfgsch 
5565f210c2aSfgsch    We use this to keep a record of all the FPTR relocations against a
5575f210c2aSfgsch    particular symbol so that we can create FPTR relocations in the
5585f210c2aSfgsch    output file.  */
5595f210c2aSfgsch 
560d2201f2fSdrahn static bfd_boolean
count_dyn_reloc(abfd,dyn_h,type,sec,sec_symndx,offset,addend)5615f210c2aSfgsch count_dyn_reloc (abfd, dyn_h, type, sec, sec_symndx, offset, addend)
5625f210c2aSfgsch      bfd *abfd;
5635f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
5645f210c2aSfgsch      int type;
5655f210c2aSfgsch      asection *sec;
5665f210c2aSfgsch      int sec_symndx;
5675f210c2aSfgsch      bfd_vma offset;
5685f210c2aSfgsch      bfd_vma addend;
5695f210c2aSfgsch {
5705f210c2aSfgsch   struct elf64_hppa_dyn_reloc_entry *rent;
5715f210c2aSfgsch 
5725f210c2aSfgsch   rent = (struct elf64_hppa_dyn_reloc_entry *)
573d2201f2fSdrahn   bfd_alloc (abfd, (bfd_size_type) sizeof (*rent));
5745f210c2aSfgsch   if (!rent)
575d2201f2fSdrahn     return FALSE;
5765f210c2aSfgsch 
5775f210c2aSfgsch   rent->next = dyn_h->reloc_entries;
5785f210c2aSfgsch   rent->type = type;
5795f210c2aSfgsch   rent->sec = sec;
5805f210c2aSfgsch   rent->sec_symndx = sec_symndx;
5815f210c2aSfgsch   rent->offset = offset;
5825f210c2aSfgsch   rent->addend = addend;
5835f210c2aSfgsch   dyn_h->reloc_entries = rent;
5845f210c2aSfgsch 
585d2201f2fSdrahn   return TRUE;
5865f210c2aSfgsch }
5875f210c2aSfgsch 
5885f210c2aSfgsch /* Scan the RELOCS and record the type of dynamic entries that each
5895f210c2aSfgsch    referenced symbol needs.  */
5905f210c2aSfgsch 
591d2201f2fSdrahn static bfd_boolean
elf64_hppa_check_relocs(abfd,info,sec,relocs)5925f210c2aSfgsch elf64_hppa_check_relocs (abfd, info, sec, relocs)
5935f210c2aSfgsch      bfd *abfd;
5945f210c2aSfgsch      struct bfd_link_info *info;
5955f210c2aSfgsch      asection *sec;
5965f210c2aSfgsch      const Elf_Internal_Rela *relocs;
5975f210c2aSfgsch {
5985f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
5995f210c2aSfgsch   const Elf_Internal_Rela *relend;
6005f210c2aSfgsch   Elf_Internal_Shdr *symtab_hdr;
6015f210c2aSfgsch   const Elf_Internal_Rela *rel;
6025f210c2aSfgsch   asection *dlt, *plt, *stubs;
6035f210c2aSfgsch   char *buf;
6045f210c2aSfgsch   size_t buf_len;
6055f210c2aSfgsch   int sec_symndx;
6065f210c2aSfgsch 
607cf2f2c56Smiod   if (info->relocatable)
608d2201f2fSdrahn     return TRUE;
6095f210c2aSfgsch 
6105f210c2aSfgsch   /* If this is the first dynamic object found in the link, create
6115f210c2aSfgsch      the special sections required for dynamic linking.  */
6125f210c2aSfgsch   if (! elf_hash_table (info)->dynamic_sections_created)
6135f210c2aSfgsch     {
614cf2f2c56Smiod       if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
615d2201f2fSdrahn 	return FALSE;
6165f210c2aSfgsch     }
6175f210c2aSfgsch 
6185f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
6195f210c2aSfgsch   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
6205f210c2aSfgsch 
6215f210c2aSfgsch   /* If necessary, build a new table holding section symbols indices
622d2201f2fSdrahn      for this BFD.  */
6235f210c2aSfgsch 
6245f210c2aSfgsch   if (info->shared && hppa_info->section_syms_bfd != abfd)
6255f210c2aSfgsch     {
6265f210c2aSfgsch       unsigned long i;
627d2201f2fSdrahn       unsigned int highest_shndx;
628d2201f2fSdrahn       Elf_Internal_Sym *local_syms = NULL;
629d2201f2fSdrahn       Elf_Internal_Sym *isym, *isymend;
630d2201f2fSdrahn       bfd_size_type amt;
6315f210c2aSfgsch 
6325f210c2aSfgsch       /* We're done with the old cache of section index to section symbol
6335f210c2aSfgsch 	 index information.  Free it.
6345f210c2aSfgsch 
6355f210c2aSfgsch 	 ?!? Note we leak the last section_syms array.  Presumably we
6365f210c2aSfgsch 	 could free it in one of the later routines in this file.  */
6375f210c2aSfgsch       if (hppa_info->section_syms)
6385f210c2aSfgsch 	free (hppa_info->section_syms);
6395f210c2aSfgsch 
640d2201f2fSdrahn       /* Read this BFD's local symbols.  */
641d2201f2fSdrahn       if (symtab_hdr->sh_info != 0)
642d2201f2fSdrahn 	{
643d2201f2fSdrahn 	  local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
6445f210c2aSfgsch 	  if (local_syms == NULL)
645d2201f2fSdrahn 	    local_syms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
646d2201f2fSdrahn 					       symtab_hdr->sh_info, 0,
647d2201f2fSdrahn 					       NULL, NULL, NULL);
648d2201f2fSdrahn 	  if (local_syms == NULL)
649d2201f2fSdrahn 	    return FALSE;
6505f210c2aSfgsch 	}
6515f210c2aSfgsch 
652d2201f2fSdrahn       /* Record the highest section index referenced by the local symbols.  */
6535f210c2aSfgsch       highest_shndx = 0;
654d2201f2fSdrahn       isymend = local_syms + symtab_hdr->sh_info;
655d2201f2fSdrahn       for (isym = local_syms; isym < isymend; isym++)
6565f210c2aSfgsch 	{
6575f210c2aSfgsch 	  if (isym->st_shndx > highest_shndx)
6585f210c2aSfgsch 	    highest_shndx = isym->st_shndx;
6595f210c2aSfgsch 	}
6605f210c2aSfgsch 
6615f210c2aSfgsch       /* Allocate an array to hold the section index to section symbol index
6625f210c2aSfgsch 	 mapping.  Bump by one since we start counting at zero.  */
6635f210c2aSfgsch       highest_shndx++;
664d2201f2fSdrahn       amt = highest_shndx;
665d2201f2fSdrahn       amt *= sizeof (int);
666d2201f2fSdrahn       hppa_info->section_syms = (int *) bfd_malloc (amt);
6675f210c2aSfgsch 
6685f210c2aSfgsch       /* Now walk the local symbols again.  If we find a section symbol,
6695f210c2aSfgsch 	 record the index of the symbol into the section_syms array.  */
670d2201f2fSdrahn       for (i = 0, isym = local_syms; isym < isymend; i++, isym++)
6715f210c2aSfgsch 	{
6725f210c2aSfgsch 	  if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
6735f210c2aSfgsch 	    hppa_info->section_syms[isym->st_shndx] = i;
6745f210c2aSfgsch 	}
6755f210c2aSfgsch 
676d2201f2fSdrahn       /* We are finished with the local symbols.  */
677d2201f2fSdrahn       if (local_syms != NULL
678d2201f2fSdrahn 	  && symtab_hdr->contents != (unsigned char *) local_syms)
679d2201f2fSdrahn 	{
680d2201f2fSdrahn 	  if (! info->keep_memory)
6815f210c2aSfgsch 	    free (local_syms);
682d2201f2fSdrahn 	  else
683d2201f2fSdrahn 	    {
684d2201f2fSdrahn 	      /* Cache the symbols for elf_link_input_bfd.  */
685d2201f2fSdrahn 	      symtab_hdr->contents = (unsigned char *) local_syms;
686d2201f2fSdrahn 	    }
687d2201f2fSdrahn 	}
6885f210c2aSfgsch 
6895f210c2aSfgsch       /* Record which BFD we built the section_syms mapping for.  */
6905f210c2aSfgsch       hppa_info->section_syms_bfd = abfd;
6915f210c2aSfgsch     }
6925f210c2aSfgsch 
6935f210c2aSfgsch   /* Record the symbol index for this input section.  We may need it for
6945f210c2aSfgsch      relocations when building shared libraries.  When not building shared
6955f210c2aSfgsch      libraries this value is never really used, but assign it to zero to
6965f210c2aSfgsch      prevent out of bounds memory accesses in other routines.  */
6975f210c2aSfgsch   if (info->shared)
6985f210c2aSfgsch     {
6995f210c2aSfgsch       sec_symndx = _bfd_elf_section_from_bfd_section (abfd, sec);
7005f210c2aSfgsch 
7015f210c2aSfgsch       /* If we did not find a section symbol for this section, then
7025f210c2aSfgsch 	 something went terribly wrong above.  */
7035f210c2aSfgsch       if (sec_symndx == -1)
704d2201f2fSdrahn 	return FALSE;
7055f210c2aSfgsch 
7065f210c2aSfgsch       sec_symndx = hppa_info->section_syms[sec_symndx];
7075f210c2aSfgsch     }
7085f210c2aSfgsch   else
7095f210c2aSfgsch     sec_symndx = 0;
7105f210c2aSfgsch 
7115f210c2aSfgsch   dlt = plt = stubs = NULL;
7125f210c2aSfgsch   buf = NULL;
7135f210c2aSfgsch   buf_len = 0;
7145f210c2aSfgsch 
7155f210c2aSfgsch   relend = relocs + sec->reloc_count;
7165f210c2aSfgsch   for (rel = relocs; rel < relend; ++rel)
7175f210c2aSfgsch     {
718cf2f2c56Smiod       enum
719cf2f2c56Smiod 	{
7205f210c2aSfgsch 	  NEED_DLT = 1,
7215f210c2aSfgsch 	  NEED_PLT = 2,
7225f210c2aSfgsch 	  NEED_STUB = 4,
7235f210c2aSfgsch 	  NEED_OPD = 8,
7245f210c2aSfgsch 	  NEED_DYNREL = 16,
7255f210c2aSfgsch 	};
7265f210c2aSfgsch 
7275f210c2aSfgsch       struct elf_link_hash_entry *h = NULL;
7285f210c2aSfgsch       unsigned long r_symndx = ELF64_R_SYM (rel->r_info);
7295f210c2aSfgsch       struct elf64_hppa_dyn_hash_entry *dyn_h;
7305f210c2aSfgsch       int need_entry;
7315f210c2aSfgsch       const char *addr_name;
732d2201f2fSdrahn       bfd_boolean maybe_dynamic;
7335f210c2aSfgsch       int dynrel_type = R_PARISC_NONE;
7345f210c2aSfgsch       static reloc_howto_type *howto;
7355f210c2aSfgsch 
7365f210c2aSfgsch       if (r_symndx >= symtab_hdr->sh_info)
7375f210c2aSfgsch 	{
7385f210c2aSfgsch 	  /* We're dealing with a global symbol -- find its hash entry
7395f210c2aSfgsch 	     and mark it as being referenced.  */
7405f210c2aSfgsch 	  long indx = r_symndx - symtab_hdr->sh_info;
7415f210c2aSfgsch 	  h = elf_sym_hashes (abfd)[indx];
7425f210c2aSfgsch 	  while (h->root.type == bfd_link_hash_indirect
7435f210c2aSfgsch 		 || h->root.type == bfd_link_hash_warning)
7445f210c2aSfgsch 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
7455f210c2aSfgsch 
7465f210c2aSfgsch 	  h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
7475f210c2aSfgsch 	}
7485f210c2aSfgsch 
7495f210c2aSfgsch       /* We can only get preliminary data on whether a symbol is
7505f210c2aSfgsch 	 locally or externally defined, as not all of the input files
7515f210c2aSfgsch 	 have yet been processed.  Do something with what we know, as
7525f210c2aSfgsch 	 this may help reduce memory usage and processing time later.  */
753d2201f2fSdrahn       maybe_dynamic = FALSE;
754d2201f2fSdrahn       if (h && ((info->shared
755cf2f2c56Smiod 		 && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
7565f210c2aSfgsch 		|| ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
7575f210c2aSfgsch 		|| h->root.type == bfd_link_hash_defweak))
758d2201f2fSdrahn 	maybe_dynamic = TRUE;
7595f210c2aSfgsch 
7605f210c2aSfgsch       howto = elf_hppa_howto_table + ELF64_R_TYPE (rel->r_info);
7615f210c2aSfgsch       need_entry = 0;
7625f210c2aSfgsch       switch (howto->type)
7635f210c2aSfgsch 	{
7645f210c2aSfgsch 	/* These are simple indirect references to symbols through the
7655f210c2aSfgsch 	   DLT.  We need to create a DLT entry for any symbols which
7665f210c2aSfgsch 	   appears in a DLTIND relocation.  */
7675f210c2aSfgsch 	case R_PARISC_DLTIND21L:
7685f210c2aSfgsch 	case R_PARISC_DLTIND14R:
7695f210c2aSfgsch 	case R_PARISC_DLTIND14F:
7705f210c2aSfgsch 	case R_PARISC_DLTIND14WR:
7715f210c2aSfgsch 	case R_PARISC_DLTIND14DR:
7725f210c2aSfgsch 	  need_entry = NEED_DLT;
7735f210c2aSfgsch 	  break;
7745f210c2aSfgsch 
7755f210c2aSfgsch 	/* ?!?  These need a DLT entry.  But I have no idea what to do with
7765f210c2aSfgsch 	   the "link time TP value.  */
7775f210c2aSfgsch 	case R_PARISC_LTOFF_TP21L:
7785f210c2aSfgsch 	case R_PARISC_LTOFF_TP14R:
7795f210c2aSfgsch 	case R_PARISC_LTOFF_TP14F:
7805f210c2aSfgsch 	case R_PARISC_LTOFF_TP64:
7815f210c2aSfgsch 	case R_PARISC_LTOFF_TP14WR:
7825f210c2aSfgsch 	case R_PARISC_LTOFF_TP14DR:
7835f210c2aSfgsch 	case R_PARISC_LTOFF_TP16F:
7845f210c2aSfgsch 	case R_PARISC_LTOFF_TP16WF:
7855f210c2aSfgsch 	case R_PARISC_LTOFF_TP16DF:
7865f210c2aSfgsch 	  need_entry = NEED_DLT;
7875f210c2aSfgsch 	  break;
7885f210c2aSfgsch 
7895f210c2aSfgsch 	/* These are function calls.  Depending on their precise target we
7905f210c2aSfgsch 	   may need to make a stub for them.  The stub uses the PLT, so we
7915f210c2aSfgsch 	   need to create PLT entries for these symbols too.  */
7925f210c2aSfgsch 	case R_PARISC_PCREL12F:
7935f210c2aSfgsch 	case R_PARISC_PCREL17F:
7945f210c2aSfgsch 	case R_PARISC_PCREL22F:
7955f210c2aSfgsch 	case R_PARISC_PCREL32:
7965f210c2aSfgsch 	case R_PARISC_PCREL64:
7975f210c2aSfgsch 	case R_PARISC_PCREL21L:
7985f210c2aSfgsch 	case R_PARISC_PCREL17R:
7995f210c2aSfgsch 	case R_PARISC_PCREL17C:
8005f210c2aSfgsch 	case R_PARISC_PCREL14R:
8015f210c2aSfgsch 	case R_PARISC_PCREL14F:
8025f210c2aSfgsch 	case R_PARISC_PCREL22C:
8035f210c2aSfgsch 	case R_PARISC_PCREL14WR:
8045f210c2aSfgsch 	case R_PARISC_PCREL14DR:
8055f210c2aSfgsch 	case R_PARISC_PCREL16F:
8065f210c2aSfgsch 	case R_PARISC_PCREL16WF:
8075f210c2aSfgsch 	case R_PARISC_PCREL16DF:
8085f210c2aSfgsch 	  need_entry = (NEED_PLT | NEED_STUB);
8095f210c2aSfgsch 	  break;
8105f210c2aSfgsch 
8115f210c2aSfgsch 	case R_PARISC_PLTOFF21L:
8125f210c2aSfgsch 	case R_PARISC_PLTOFF14R:
8135f210c2aSfgsch 	case R_PARISC_PLTOFF14F:
8145f210c2aSfgsch 	case R_PARISC_PLTOFF14WR:
8155f210c2aSfgsch 	case R_PARISC_PLTOFF14DR:
8165f210c2aSfgsch 	case R_PARISC_PLTOFF16F:
8175f210c2aSfgsch 	case R_PARISC_PLTOFF16WF:
8185f210c2aSfgsch 	case R_PARISC_PLTOFF16DF:
8195f210c2aSfgsch 	  need_entry = (NEED_PLT);
8205f210c2aSfgsch 	  break;
8215f210c2aSfgsch 
8225f210c2aSfgsch 	case R_PARISC_DIR64:
8235f210c2aSfgsch 	  if (info->shared || maybe_dynamic)
8245f210c2aSfgsch 	    need_entry = (NEED_DYNREL);
8255f210c2aSfgsch 	  dynrel_type = R_PARISC_DIR64;
8265f210c2aSfgsch 	  break;
8275f210c2aSfgsch 
8285f210c2aSfgsch 	/* This is an indirect reference through the DLT to get the address
8295f210c2aSfgsch 	   of a OPD descriptor.  Thus we need to make a DLT entry that points
8305f210c2aSfgsch 	   to an OPD entry.  */
8315f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR21L:
8325f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR14R:
8335f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR14WR:
8345f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR14DR:
8355f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR32:
8365f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR64:
8375f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR16F:
8385f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR16WF:
8395f210c2aSfgsch 	case R_PARISC_LTOFF_FPTR16DF:
8405f210c2aSfgsch 	  if (info->shared || maybe_dynamic)
8415f210c2aSfgsch 	    need_entry = (NEED_DLT | NEED_OPD);
8425f210c2aSfgsch 	  else
8435f210c2aSfgsch 	    need_entry = (NEED_DLT | NEED_OPD);
8445f210c2aSfgsch 	  dynrel_type = R_PARISC_FPTR64;
8455f210c2aSfgsch 	  break;
8465f210c2aSfgsch 
8475f210c2aSfgsch 	/* This is a simple OPD entry.  */
8485f210c2aSfgsch 	case R_PARISC_FPTR64:
8495f210c2aSfgsch 	  if (info->shared || maybe_dynamic)
8505f210c2aSfgsch 	    need_entry = (NEED_OPD | NEED_DYNREL);
8515f210c2aSfgsch 	  else
8525f210c2aSfgsch 	    need_entry = (NEED_OPD);
8535f210c2aSfgsch 	  dynrel_type = R_PARISC_FPTR64;
8545f210c2aSfgsch 	  break;
8555f210c2aSfgsch 
8565f210c2aSfgsch 	/* Add more cases as needed.  */
8575f210c2aSfgsch 	}
8585f210c2aSfgsch 
8595f210c2aSfgsch       if (!need_entry)
8605f210c2aSfgsch 	continue;
8615f210c2aSfgsch 
8625f210c2aSfgsch       /* Collect a canonical name for this address.  */
863cf2f2c56Smiod       addr_name = get_dyn_name (abfd, h, rel, &buf, &buf_len);
8645f210c2aSfgsch 
8655f210c2aSfgsch       /* Collect the canonical entry data for this address.  */
8665f210c2aSfgsch       dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
867d2201f2fSdrahn 					  addr_name, TRUE, TRUE);
8685f210c2aSfgsch       BFD_ASSERT (dyn_h);
8695f210c2aSfgsch 
8705f210c2aSfgsch       /* Stash away enough information to be able to find this symbol
8715f210c2aSfgsch 	 regardless of whether or not it is local or global.  */
8725f210c2aSfgsch       dyn_h->h = h;
8735f210c2aSfgsch       dyn_h->owner = abfd;
8745f210c2aSfgsch       dyn_h->sym_indx = r_symndx;
8755f210c2aSfgsch 
8765f210c2aSfgsch       /* ?!? We may need to do some error checking in here.  */
8775f210c2aSfgsch       /* Create what's needed.  */
8785f210c2aSfgsch       if (need_entry & NEED_DLT)
8795f210c2aSfgsch 	{
8805f210c2aSfgsch 	  if (! hppa_info->dlt_sec
8815f210c2aSfgsch 	      && ! get_dlt (abfd, info, hppa_info))
8825f210c2aSfgsch 	    goto err_out;
8835f210c2aSfgsch 	  dyn_h->want_dlt = 1;
8845f210c2aSfgsch 	}
8855f210c2aSfgsch 
8865f210c2aSfgsch       if (need_entry & NEED_PLT)
8875f210c2aSfgsch 	{
8885f210c2aSfgsch 	  if (! hppa_info->plt_sec
8895f210c2aSfgsch 	      && ! get_plt (abfd, info, hppa_info))
8905f210c2aSfgsch 	    goto err_out;
8915f210c2aSfgsch 	  dyn_h->want_plt = 1;
8925f210c2aSfgsch 	}
8935f210c2aSfgsch 
8945f210c2aSfgsch       if (need_entry & NEED_STUB)
8955f210c2aSfgsch 	{
8965f210c2aSfgsch 	  if (! hppa_info->stub_sec
8975f210c2aSfgsch 	      && ! get_stub (abfd, info, hppa_info))
8985f210c2aSfgsch 	    goto err_out;
8995f210c2aSfgsch 	  dyn_h->want_stub = 1;
9005f210c2aSfgsch 	}
9015f210c2aSfgsch 
9025f210c2aSfgsch       if (need_entry & NEED_OPD)
9035f210c2aSfgsch 	{
9045f210c2aSfgsch 	  if (! hppa_info->opd_sec
9055f210c2aSfgsch 	      && ! get_opd (abfd, info, hppa_info))
9065f210c2aSfgsch 	    goto err_out;
9075f210c2aSfgsch 
9085f210c2aSfgsch 	  dyn_h->want_opd = 1;
9095f210c2aSfgsch 
9105f210c2aSfgsch 	  /* FPTRs are not allocated by the dynamic linker for PA64, though
9115f210c2aSfgsch 	     it is possible that will change in the future.  */
9125f210c2aSfgsch 
9135f210c2aSfgsch 	  /* This could be a local function that had its address taken, in
9145f210c2aSfgsch 	     which case H will be NULL.  */
9155f210c2aSfgsch 	  if (h)
9165f210c2aSfgsch 	    h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
9175f210c2aSfgsch 	}
9185f210c2aSfgsch 
9195f210c2aSfgsch       /* Add a new dynamic relocation to the chain of dynamic
9205f210c2aSfgsch 	 relocations for this symbol.  */
9215f210c2aSfgsch       if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
9225f210c2aSfgsch 	{
9235f210c2aSfgsch 	  if (! hppa_info->other_rel_sec
9245f210c2aSfgsch 	      && ! get_reloc_section (abfd, hppa_info, sec))
9255f210c2aSfgsch 	    goto err_out;
9265f210c2aSfgsch 
9275f210c2aSfgsch 	  if (!count_dyn_reloc (abfd, dyn_h, dynrel_type, sec,
9285f210c2aSfgsch 				sec_symndx, rel->r_offset, rel->r_addend))
9295f210c2aSfgsch 	    goto err_out;
9305f210c2aSfgsch 
9315f210c2aSfgsch 	  /* If we are building a shared library and we just recorded
9325f210c2aSfgsch 	     a dynamic R_PARISC_FPTR64 relocation, then make sure the
9335f210c2aSfgsch 	     section symbol for this section ends up in the dynamic
9345f210c2aSfgsch 	     symbol table.  */
9355f210c2aSfgsch 	  if (info->shared && dynrel_type == R_PARISC_FPTR64
936cf2f2c56Smiod 	      && ! (bfd_elf_link_record_local_dynamic_symbol
9375f210c2aSfgsch 		    (info, abfd, sec_symndx)))
938d2201f2fSdrahn 	    return FALSE;
9395f210c2aSfgsch 	}
9405f210c2aSfgsch     }
9415f210c2aSfgsch 
9425f210c2aSfgsch   if (buf)
9435f210c2aSfgsch     free (buf);
944d2201f2fSdrahn   return TRUE;
9455f210c2aSfgsch 
9465f210c2aSfgsch  err_out:
9475f210c2aSfgsch   if (buf)
9485f210c2aSfgsch     free (buf);
949d2201f2fSdrahn   return FALSE;
9505f210c2aSfgsch }
9515f210c2aSfgsch 
9525f210c2aSfgsch struct elf64_hppa_allocate_data
9535f210c2aSfgsch {
9545f210c2aSfgsch   struct bfd_link_info *info;
9555f210c2aSfgsch   bfd_size_type ofs;
9565f210c2aSfgsch };
9575f210c2aSfgsch 
9585f210c2aSfgsch /* Should we do dynamic things to this symbol?  */
9595f210c2aSfgsch 
960d2201f2fSdrahn static bfd_boolean
elf64_hppa_dynamic_symbol_p(h,info)9615f210c2aSfgsch elf64_hppa_dynamic_symbol_p (h, info)
9625f210c2aSfgsch      struct elf_link_hash_entry *h;
9635f210c2aSfgsch      struct bfd_link_info *info;
9645f210c2aSfgsch {
965cf2f2c56Smiod   /* ??? What, if anything, needs to happen wrt STV_PROTECTED symbols
966cf2f2c56Smiod      and relocations that retrieve a function descriptor?  Assume the
967cf2f2c56Smiod      worst for now.  */
968cf2f2c56Smiod   if (_bfd_elf_dynamic_symbol_p (h, info, 1))
969cf2f2c56Smiod     {
970cf2f2c56Smiod       /* ??? Why is this here and not elsewhere is_local_label_name.  */
9715f210c2aSfgsch       if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$')
972d2201f2fSdrahn 	return FALSE;
9735f210c2aSfgsch 
974d2201f2fSdrahn       return TRUE;
975cf2f2c56Smiod     }
976cf2f2c56Smiod   else
977d2201f2fSdrahn     return FALSE;
9785f210c2aSfgsch }
9795f210c2aSfgsch 
980cf2f2c56Smiod /* Mark all functions exported by this file so that we can later allocate
9815f210c2aSfgsch    entries in .opd for them.  */
9825f210c2aSfgsch 
983d2201f2fSdrahn static bfd_boolean
elf64_hppa_mark_exported_functions(h,data)9845f210c2aSfgsch elf64_hppa_mark_exported_functions (h, data)
9855f210c2aSfgsch      struct elf_link_hash_entry *h;
9865f210c2aSfgsch      PTR data;
9875f210c2aSfgsch {
9885f210c2aSfgsch   struct bfd_link_info *info = (struct bfd_link_info *)data;
9895f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
9905f210c2aSfgsch 
9915f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
9925f210c2aSfgsch 
993d2201f2fSdrahn   if (h->root.type == bfd_link_hash_warning)
994d2201f2fSdrahn     h = (struct elf_link_hash_entry *) h->root.u.i.link;
995d2201f2fSdrahn 
9965f210c2aSfgsch   if (h
9975f210c2aSfgsch       && (h->root.type == bfd_link_hash_defined
9985f210c2aSfgsch 	  || h->root.type == bfd_link_hash_defweak)
9995f210c2aSfgsch       && h->root.u.def.section->output_section != NULL
10005f210c2aSfgsch       && h->type == STT_FUNC)
10015f210c2aSfgsch     {
10025f210c2aSfgsch        struct elf64_hppa_dyn_hash_entry *dyn_h;
10035f210c2aSfgsch 
10045f210c2aSfgsch       /* Add this symbol to the PA64 linker hash table.  */
10055f210c2aSfgsch       dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
1006d2201f2fSdrahn 					  h->root.root.string, TRUE, TRUE);
10075f210c2aSfgsch       BFD_ASSERT (dyn_h);
10085f210c2aSfgsch       dyn_h->h = h;
10095f210c2aSfgsch 
10105f210c2aSfgsch       if (! hppa_info->opd_sec
10115f210c2aSfgsch 	  && ! get_opd (hppa_info->root.dynobj, info, hppa_info))
1012d2201f2fSdrahn 	return FALSE;
10135f210c2aSfgsch 
10145f210c2aSfgsch       dyn_h->want_opd = 1;
10155f210c2aSfgsch       /* Put a flag here for output_symbol_hook.  */
10165f210c2aSfgsch       dyn_h->st_shndx = -1;
10175f210c2aSfgsch       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
10185f210c2aSfgsch     }
10195f210c2aSfgsch 
1020d2201f2fSdrahn   return TRUE;
10215f210c2aSfgsch }
10225f210c2aSfgsch 
10235f210c2aSfgsch /* Allocate space for a DLT entry.  */
10245f210c2aSfgsch 
1025d2201f2fSdrahn static bfd_boolean
allocate_global_data_dlt(dyn_h,data)10265f210c2aSfgsch allocate_global_data_dlt (dyn_h, data)
10275f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
10285f210c2aSfgsch      PTR data;
10295f210c2aSfgsch {
10305f210c2aSfgsch   struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
10315f210c2aSfgsch 
10325f210c2aSfgsch   if (dyn_h->want_dlt)
10335f210c2aSfgsch     {
10345f210c2aSfgsch       struct elf_link_hash_entry *h = dyn_h->h;
10355f210c2aSfgsch 
10365f210c2aSfgsch       if (x->info->shared)
10375f210c2aSfgsch 	{
10385f210c2aSfgsch 	  /* Possibly add the symbol to the local dynamic symbol
10395f210c2aSfgsch 	     table since we might need to create a dynamic relocation
10405f210c2aSfgsch 	     against it.  */
10415f210c2aSfgsch 	  if (! h
1042d2201f2fSdrahn 	      || (h->dynindx == -1 && h->type != STT_PARISC_MILLI))
10435f210c2aSfgsch 	    {
10445f210c2aSfgsch 	      bfd *owner;
10455f210c2aSfgsch 	      owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
10465f210c2aSfgsch 
1047cf2f2c56Smiod 	      if (! (bfd_elf_link_record_local_dynamic_symbol
1048d2201f2fSdrahn 		     (x->info, owner, dyn_h->sym_indx)))
1049d2201f2fSdrahn 		return FALSE;
10505f210c2aSfgsch 	    }
10515f210c2aSfgsch 	}
10525f210c2aSfgsch 
10535f210c2aSfgsch       dyn_h->dlt_offset = x->ofs;
10545f210c2aSfgsch       x->ofs += DLT_ENTRY_SIZE;
10555f210c2aSfgsch     }
1056d2201f2fSdrahn   return TRUE;
10575f210c2aSfgsch }
10585f210c2aSfgsch 
10595f210c2aSfgsch /* Allocate space for a DLT.PLT entry.  */
10605f210c2aSfgsch 
1061d2201f2fSdrahn static bfd_boolean
allocate_global_data_plt(dyn_h,data)10625f210c2aSfgsch allocate_global_data_plt (dyn_h, data)
10635f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
10645f210c2aSfgsch      PTR data;
10655f210c2aSfgsch {
10665f210c2aSfgsch   struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
10675f210c2aSfgsch 
10685f210c2aSfgsch   if (dyn_h->want_plt
10695f210c2aSfgsch       && elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info)
10705f210c2aSfgsch       && !((dyn_h->h->root.type == bfd_link_hash_defined
10715f210c2aSfgsch 	    || dyn_h->h->root.type == bfd_link_hash_defweak)
10725f210c2aSfgsch 	   && dyn_h->h->root.u.def.section->output_section != NULL))
10735f210c2aSfgsch     {
10745f210c2aSfgsch       dyn_h->plt_offset = x->ofs;
10755f210c2aSfgsch       x->ofs += PLT_ENTRY_SIZE;
10765f210c2aSfgsch       if (dyn_h->plt_offset < 0x2000)
10775f210c2aSfgsch 	elf64_hppa_hash_table (x->info)->gp_offset = dyn_h->plt_offset;
10785f210c2aSfgsch     }
10795f210c2aSfgsch   else
10805f210c2aSfgsch     dyn_h->want_plt = 0;
10815f210c2aSfgsch 
1082d2201f2fSdrahn   return TRUE;
10835f210c2aSfgsch }
10845f210c2aSfgsch 
10855f210c2aSfgsch /* Allocate space for a STUB entry.  */
10865f210c2aSfgsch 
1087d2201f2fSdrahn static bfd_boolean
allocate_global_data_stub(dyn_h,data)10885f210c2aSfgsch allocate_global_data_stub (dyn_h, data)
10895f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
10905f210c2aSfgsch      PTR data;
10915f210c2aSfgsch {
10925f210c2aSfgsch   struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
10935f210c2aSfgsch 
10945f210c2aSfgsch   if (dyn_h->want_stub
10955f210c2aSfgsch       && elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info)
10965f210c2aSfgsch       && !((dyn_h->h->root.type == bfd_link_hash_defined
10975f210c2aSfgsch 	    || dyn_h->h->root.type == bfd_link_hash_defweak)
10985f210c2aSfgsch 	   && dyn_h->h->root.u.def.section->output_section != NULL))
10995f210c2aSfgsch     {
11005f210c2aSfgsch       dyn_h->stub_offset = x->ofs;
11015f210c2aSfgsch       x->ofs += sizeof (plt_stub);
11025f210c2aSfgsch     }
11035f210c2aSfgsch   else
11045f210c2aSfgsch     dyn_h->want_stub = 0;
1105d2201f2fSdrahn   return TRUE;
11065f210c2aSfgsch }
11075f210c2aSfgsch 
11085f210c2aSfgsch /* Allocate space for a FPTR entry.  */
11095f210c2aSfgsch 
1110d2201f2fSdrahn static bfd_boolean
allocate_global_data_opd(dyn_h,data)11115f210c2aSfgsch allocate_global_data_opd (dyn_h, data)
11125f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
11135f210c2aSfgsch      PTR data;
11145f210c2aSfgsch {
11155f210c2aSfgsch   struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
11165f210c2aSfgsch 
11175f210c2aSfgsch   if (dyn_h->want_opd)
11185f210c2aSfgsch     {
11195f210c2aSfgsch       struct elf_link_hash_entry *h = dyn_h->h;
11205f210c2aSfgsch 
11215f210c2aSfgsch       if (h)
11225f210c2aSfgsch 	while (h->root.type == bfd_link_hash_indirect
11235f210c2aSfgsch 	       || h->root.type == bfd_link_hash_warning)
11245f210c2aSfgsch 	  h = (struct elf_link_hash_entry *) h->root.u.i.link;
11255f210c2aSfgsch 
11265f210c2aSfgsch       /* We never need an opd entry for a symbol which is not
11275f210c2aSfgsch 	 defined by this output file.  */
1128d2201f2fSdrahn       if (h && (h->root.type == bfd_link_hash_undefined
1129d2201f2fSdrahn 		|| h->root.u.def.section->output_section == NULL))
11305f210c2aSfgsch 	dyn_h->want_opd = 0;
11315f210c2aSfgsch 
11325f210c2aSfgsch       /* If we are creating a shared library, took the address of a local
11335f210c2aSfgsch 	 function or might export this function from this object file, then
11345f210c2aSfgsch 	 we have to create an opd descriptor.  */
11355f210c2aSfgsch       else if (x->info->shared
11365f210c2aSfgsch 	       || h == NULL
1137d2201f2fSdrahn 	       || (h->dynindx == -1 && h->type != STT_PARISC_MILLI)
1138d2201f2fSdrahn 	       || (h->root.type == bfd_link_hash_defined
1139d2201f2fSdrahn 		   || h->root.type == bfd_link_hash_defweak))
11405f210c2aSfgsch 	{
11415f210c2aSfgsch 	  /* If we are creating a shared library, then we will have to
11425f210c2aSfgsch 	     create a runtime relocation for the symbol to properly
11435f210c2aSfgsch 	     initialize the .opd entry.  Make sure the symbol gets
11445f210c2aSfgsch 	     added to the dynamic symbol table.  */
11455f210c2aSfgsch 	  if (x->info->shared
11465f210c2aSfgsch 	      && (h == NULL || (h->dynindx == -1)))
11475f210c2aSfgsch 	    {
11485f210c2aSfgsch 	      bfd *owner;
11495f210c2aSfgsch 	      owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
11505f210c2aSfgsch 
1151cf2f2c56Smiod 	      if (!bfd_elf_link_record_local_dynamic_symbol
11525f210c2aSfgsch 		    (x->info, owner, dyn_h->sym_indx))
1153d2201f2fSdrahn 		return FALSE;
11545f210c2aSfgsch 	    }
11555f210c2aSfgsch 
11565f210c2aSfgsch 	  /* This may not be necessary or desirable anymore now that
11575f210c2aSfgsch 	     we have some support for dealing with section symbols
11585f210c2aSfgsch 	     in dynamic relocs.  But name munging does make the result
11595f210c2aSfgsch 	     much easier to debug.  ie, the EPLT reloc will reference
11605f210c2aSfgsch 	     a symbol like .foobar, instead of .text + offset.  */
11615f210c2aSfgsch 	  if (x->info->shared && h)
11625f210c2aSfgsch 	    {
11635f210c2aSfgsch 	      char *new_name;
11645f210c2aSfgsch 	      struct elf_link_hash_entry *nh;
11655f210c2aSfgsch 
11665f210c2aSfgsch 	      new_name = alloca (strlen (h->root.root.string) + 2);
11675f210c2aSfgsch 	      new_name[0] = '.';
11685f210c2aSfgsch 	      strcpy (new_name + 1, h->root.root.string);
11695f210c2aSfgsch 
11705f210c2aSfgsch 	      nh = elf_link_hash_lookup (elf_hash_table (x->info),
1171d2201f2fSdrahn 					 new_name, TRUE, TRUE, TRUE);
11725f210c2aSfgsch 
11735f210c2aSfgsch 	      nh->root.type = h->root.type;
11745f210c2aSfgsch 	      nh->root.u.def.value = h->root.u.def.value;
11755f210c2aSfgsch 	      nh->root.u.def.section = h->root.u.def.section;
11765f210c2aSfgsch 
1177cf2f2c56Smiod 	      if (! bfd_elf_link_record_dynamic_symbol (x->info, nh))
1178d2201f2fSdrahn 		return FALSE;
11795f210c2aSfgsch 
11805f210c2aSfgsch 	     }
11815f210c2aSfgsch 	  dyn_h->opd_offset = x->ofs;
11825f210c2aSfgsch 	  x->ofs += OPD_ENTRY_SIZE;
11835f210c2aSfgsch 	}
11845f210c2aSfgsch 
11855f210c2aSfgsch       /* Otherwise we do not need an opd entry.  */
11865f210c2aSfgsch       else
11875f210c2aSfgsch 	dyn_h->want_opd = 0;
11885f210c2aSfgsch     }
1189d2201f2fSdrahn   return TRUE;
11905f210c2aSfgsch }
11915f210c2aSfgsch 
11925f210c2aSfgsch /* HP requires the EI_OSABI field to be filled in.  The assignment to
11935f210c2aSfgsch    EI_ABIVERSION may not be strictly necessary.  */
11945f210c2aSfgsch 
11955f210c2aSfgsch static void
elf64_hppa_post_process_headers(abfd,link_info)11965f210c2aSfgsch elf64_hppa_post_process_headers (abfd, link_info)
11975f210c2aSfgsch      bfd * abfd;
11985f210c2aSfgsch      struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
11995f210c2aSfgsch {
12005f210c2aSfgsch   Elf_Internal_Ehdr * i_ehdrp;
12015f210c2aSfgsch 
12025f210c2aSfgsch   i_ehdrp = elf_elfheader (abfd);
12035f210c2aSfgsch 
12045f210c2aSfgsch   if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)
12055f210c2aSfgsch     {
12065f210c2aSfgsch       i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
12075f210c2aSfgsch     }
12085f210c2aSfgsch   else
12095f210c2aSfgsch     {
12105f210c2aSfgsch       i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
12115f210c2aSfgsch       i_ehdrp->e_ident[EI_ABIVERSION] = 1;
12125f210c2aSfgsch     }
12135f210c2aSfgsch }
12145f210c2aSfgsch 
12155f210c2aSfgsch /* Create function descriptor section (.opd).  This section is called .opd
1216cf2f2c56Smiod    because it contains "official procedure descriptors".  The "official"
12175f210c2aSfgsch    refers to the fact that these descriptors are used when taking the address
12185f210c2aSfgsch    of a procedure, thus ensuring a unique address for each procedure.  */
12195f210c2aSfgsch 
1220d2201f2fSdrahn static bfd_boolean
get_opd(abfd,info,hppa_info)12215f210c2aSfgsch get_opd (abfd, info, hppa_info)
12225f210c2aSfgsch      bfd *abfd;
12235f210c2aSfgsch      struct bfd_link_info *info ATTRIBUTE_UNUSED;
12245f210c2aSfgsch      struct elf64_hppa_link_hash_table *hppa_info;
12255f210c2aSfgsch {
12265f210c2aSfgsch   asection *opd;
12275f210c2aSfgsch   bfd *dynobj;
12285f210c2aSfgsch 
12295f210c2aSfgsch   opd = hppa_info->opd_sec;
12305f210c2aSfgsch   if (!opd)
12315f210c2aSfgsch     {
12325f210c2aSfgsch       dynobj = hppa_info->root.dynobj;
12335f210c2aSfgsch       if (!dynobj)
12345f210c2aSfgsch 	hppa_info->root.dynobj = dynobj = abfd;
12355f210c2aSfgsch 
12365f210c2aSfgsch       opd = bfd_make_section (dynobj, ".opd");
12375f210c2aSfgsch       if (!opd
12385f210c2aSfgsch 	  || !bfd_set_section_flags (dynobj, opd,
12395f210c2aSfgsch 				     (SEC_ALLOC
12405f210c2aSfgsch 				      | SEC_LOAD
12415f210c2aSfgsch 				      | SEC_HAS_CONTENTS
12425f210c2aSfgsch 				      | SEC_IN_MEMORY
12435f210c2aSfgsch 				      | SEC_LINKER_CREATED))
12445f210c2aSfgsch 	  || !bfd_set_section_alignment (abfd, opd, 3))
12455f210c2aSfgsch 	{
12465f210c2aSfgsch 	  BFD_ASSERT (0);
1247d2201f2fSdrahn 	  return FALSE;
12485f210c2aSfgsch 	}
12495f210c2aSfgsch 
12505f210c2aSfgsch       hppa_info->opd_sec = opd;
12515f210c2aSfgsch     }
12525f210c2aSfgsch 
1253d2201f2fSdrahn   return TRUE;
12545f210c2aSfgsch }
12555f210c2aSfgsch 
12565f210c2aSfgsch /* Create the PLT section.  */
12575f210c2aSfgsch 
1258d2201f2fSdrahn static bfd_boolean
get_plt(abfd,info,hppa_info)12595f210c2aSfgsch get_plt (abfd, info, hppa_info)
12605f210c2aSfgsch      bfd *abfd;
12615f210c2aSfgsch      struct bfd_link_info *info ATTRIBUTE_UNUSED;
12625f210c2aSfgsch      struct elf64_hppa_link_hash_table *hppa_info;
12635f210c2aSfgsch {
12645f210c2aSfgsch   asection *plt;
12655f210c2aSfgsch   bfd *dynobj;
12665f210c2aSfgsch 
12675f210c2aSfgsch   plt = hppa_info->plt_sec;
12685f210c2aSfgsch   if (!plt)
12695f210c2aSfgsch     {
12705f210c2aSfgsch       dynobj = hppa_info->root.dynobj;
12715f210c2aSfgsch       if (!dynobj)
12725f210c2aSfgsch 	hppa_info->root.dynobj = dynobj = abfd;
12735f210c2aSfgsch 
12745f210c2aSfgsch       plt = bfd_make_section (dynobj, ".plt");
12755f210c2aSfgsch       if (!plt
12765f210c2aSfgsch 	  || !bfd_set_section_flags (dynobj, plt,
12775f210c2aSfgsch 				     (SEC_ALLOC
12785f210c2aSfgsch 				      | SEC_LOAD
12795f210c2aSfgsch 				      | SEC_HAS_CONTENTS
12805f210c2aSfgsch 				      | SEC_IN_MEMORY
12815f210c2aSfgsch 				      | SEC_LINKER_CREATED))
12825f210c2aSfgsch 	  || !bfd_set_section_alignment (abfd, plt, 3))
12835f210c2aSfgsch 	{
12845f210c2aSfgsch 	  BFD_ASSERT (0);
1285d2201f2fSdrahn 	  return FALSE;
12865f210c2aSfgsch 	}
12875f210c2aSfgsch 
12885f210c2aSfgsch       hppa_info->plt_sec = plt;
12895f210c2aSfgsch     }
12905f210c2aSfgsch 
1291d2201f2fSdrahn   return TRUE;
12925f210c2aSfgsch }
12935f210c2aSfgsch 
12945f210c2aSfgsch /* Create the DLT section.  */
12955f210c2aSfgsch 
1296d2201f2fSdrahn static bfd_boolean
get_dlt(abfd,info,hppa_info)12975f210c2aSfgsch get_dlt (abfd, info, hppa_info)
12985f210c2aSfgsch      bfd *abfd;
12995f210c2aSfgsch      struct bfd_link_info *info ATTRIBUTE_UNUSED;
13005f210c2aSfgsch      struct elf64_hppa_link_hash_table *hppa_info;
13015f210c2aSfgsch {
13025f210c2aSfgsch   asection *dlt;
13035f210c2aSfgsch   bfd *dynobj;
13045f210c2aSfgsch 
13055f210c2aSfgsch   dlt = hppa_info->dlt_sec;
13065f210c2aSfgsch   if (!dlt)
13075f210c2aSfgsch     {
13085f210c2aSfgsch       dynobj = hppa_info->root.dynobj;
13095f210c2aSfgsch       if (!dynobj)
13105f210c2aSfgsch 	hppa_info->root.dynobj = dynobj = abfd;
13115f210c2aSfgsch 
13125f210c2aSfgsch       dlt = bfd_make_section (dynobj, ".dlt");
13135f210c2aSfgsch       if (!dlt
13145f210c2aSfgsch 	  || !bfd_set_section_flags (dynobj, dlt,
13155f210c2aSfgsch 				     (SEC_ALLOC
13165f210c2aSfgsch 				      | SEC_LOAD
13175f210c2aSfgsch 				      | SEC_HAS_CONTENTS
13185f210c2aSfgsch 				      | SEC_IN_MEMORY
13195f210c2aSfgsch 				      | SEC_LINKER_CREATED))
13205f210c2aSfgsch 	  || !bfd_set_section_alignment (abfd, dlt, 3))
13215f210c2aSfgsch 	{
13225f210c2aSfgsch 	  BFD_ASSERT (0);
1323d2201f2fSdrahn 	  return FALSE;
13245f210c2aSfgsch 	}
13255f210c2aSfgsch 
13265f210c2aSfgsch       hppa_info->dlt_sec = dlt;
13275f210c2aSfgsch     }
13285f210c2aSfgsch 
1329d2201f2fSdrahn   return TRUE;
13305f210c2aSfgsch }
13315f210c2aSfgsch 
13325f210c2aSfgsch /* Create the stubs section.  */
13335f210c2aSfgsch 
1334d2201f2fSdrahn static bfd_boolean
get_stub(abfd,info,hppa_info)13355f210c2aSfgsch get_stub (abfd, info, hppa_info)
13365f210c2aSfgsch      bfd *abfd;
13375f210c2aSfgsch      struct bfd_link_info *info ATTRIBUTE_UNUSED;
13385f210c2aSfgsch      struct elf64_hppa_link_hash_table *hppa_info;
13395f210c2aSfgsch {
13405f210c2aSfgsch   asection *stub;
13415f210c2aSfgsch   bfd *dynobj;
13425f210c2aSfgsch 
13435f210c2aSfgsch   stub = hppa_info->stub_sec;
13445f210c2aSfgsch   if (!stub)
13455f210c2aSfgsch     {
13465f210c2aSfgsch       dynobj = hppa_info->root.dynobj;
13475f210c2aSfgsch       if (!dynobj)
13485f210c2aSfgsch 	hppa_info->root.dynobj = dynobj = abfd;
13495f210c2aSfgsch 
13505f210c2aSfgsch       stub = bfd_make_section (dynobj, ".stub");
13515f210c2aSfgsch       if (!stub
13525f210c2aSfgsch 	  || !bfd_set_section_flags (dynobj, stub,
13535f210c2aSfgsch 				     (SEC_ALLOC
13545f210c2aSfgsch 				      | SEC_LOAD
13555f210c2aSfgsch 				      | SEC_HAS_CONTENTS
13565f210c2aSfgsch 				      | SEC_IN_MEMORY
13575f210c2aSfgsch 				      | SEC_READONLY
13585f210c2aSfgsch 				      | SEC_LINKER_CREATED))
13595f210c2aSfgsch 	  || !bfd_set_section_alignment (abfd, stub, 3))
13605f210c2aSfgsch 	{
13615f210c2aSfgsch 	  BFD_ASSERT (0);
1362d2201f2fSdrahn 	  return FALSE;
13635f210c2aSfgsch 	}
13645f210c2aSfgsch 
13655f210c2aSfgsch       hppa_info->stub_sec = stub;
13665f210c2aSfgsch     }
13675f210c2aSfgsch 
1368d2201f2fSdrahn   return TRUE;
13695f210c2aSfgsch }
13705f210c2aSfgsch 
13715f210c2aSfgsch /* Create sections necessary for dynamic linking.  This is only a rough
13725f210c2aSfgsch    cut and will likely change as we learn more about the somewhat
13735f210c2aSfgsch    unusual dynamic linking scheme HP uses.
13745f210c2aSfgsch 
13755f210c2aSfgsch    .stub:
13765f210c2aSfgsch 	Contains code to implement cross-space calls.  The first time one
13775f210c2aSfgsch 	of the stubs is used it will call into the dynamic linker, later
13785f210c2aSfgsch 	calls will go straight to the target.
13795f210c2aSfgsch 
13805f210c2aSfgsch 	The only stub we support right now looks like
13815f210c2aSfgsch 
13825f210c2aSfgsch 	ldd OFFSET(%dp),%r1
13835f210c2aSfgsch 	bve %r0(%r1)
13845f210c2aSfgsch 	ldd OFFSET+8(%dp),%dp
13855f210c2aSfgsch 
13865f210c2aSfgsch 	Other stubs may be needed in the future.  We may want the remove
13875f210c2aSfgsch 	the break/nop instruction.  It is only used right now to keep the
13885f210c2aSfgsch 	offset of a .plt entry and a .stub entry in sync.
13895f210c2aSfgsch 
13905f210c2aSfgsch    .dlt:
13915f210c2aSfgsch 	This is what most people call the .got.  HP used a different name.
13925f210c2aSfgsch 	Losers.
13935f210c2aSfgsch 
13945f210c2aSfgsch    .rela.dlt:
13955f210c2aSfgsch 	Relocations for the DLT.
13965f210c2aSfgsch 
13975f210c2aSfgsch    .plt:
13985f210c2aSfgsch 	Function pointers as address,gp pairs.
13995f210c2aSfgsch 
14005f210c2aSfgsch    .rela.plt:
14015f210c2aSfgsch 	Should contain dynamic IPLT (and EPLT?) relocations.
14025f210c2aSfgsch 
14035f210c2aSfgsch    .opd:
14045f210c2aSfgsch 	FPTRS
14055f210c2aSfgsch 
14065f210c2aSfgsch    .rela.opd:
14075f210c2aSfgsch 	EPLT relocations for symbols exported from shared libraries.  */
14085f210c2aSfgsch 
1409d2201f2fSdrahn static bfd_boolean
elf64_hppa_create_dynamic_sections(abfd,info)14105f210c2aSfgsch elf64_hppa_create_dynamic_sections (abfd, info)
14115f210c2aSfgsch      bfd *abfd;
14125f210c2aSfgsch      struct bfd_link_info *info;
14135f210c2aSfgsch {
14145f210c2aSfgsch   asection *s;
14155f210c2aSfgsch 
14165f210c2aSfgsch   if (! get_stub (abfd, info, elf64_hppa_hash_table (info)))
1417d2201f2fSdrahn     return FALSE;
14185f210c2aSfgsch 
14195f210c2aSfgsch   if (! get_dlt (abfd, info, elf64_hppa_hash_table (info)))
1420d2201f2fSdrahn     return FALSE;
14215f210c2aSfgsch 
14225f210c2aSfgsch   if (! get_plt (abfd, info, elf64_hppa_hash_table (info)))
1423d2201f2fSdrahn     return FALSE;
14245f210c2aSfgsch 
14255f210c2aSfgsch   if (! get_opd (abfd, info, elf64_hppa_hash_table (info)))
1426d2201f2fSdrahn     return FALSE;
14275f210c2aSfgsch 
14285f210c2aSfgsch   s = bfd_make_section(abfd, ".rela.dlt");
14295f210c2aSfgsch   if (s == NULL
14305f210c2aSfgsch       || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
14315f210c2aSfgsch 					   | SEC_HAS_CONTENTS
14325f210c2aSfgsch 					   | SEC_IN_MEMORY
14335f210c2aSfgsch 					   | SEC_READONLY
14345f210c2aSfgsch 					   | SEC_LINKER_CREATED))
14355f210c2aSfgsch       || !bfd_set_section_alignment (abfd, s, 3))
1436d2201f2fSdrahn     return FALSE;
14375f210c2aSfgsch   elf64_hppa_hash_table (info)->dlt_rel_sec = s;
14385f210c2aSfgsch 
14395f210c2aSfgsch   s = bfd_make_section(abfd, ".rela.plt");
14405f210c2aSfgsch   if (s == NULL
14415f210c2aSfgsch       || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
14425f210c2aSfgsch 					   | SEC_HAS_CONTENTS
14435f210c2aSfgsch 					   | SEC_IN_MEMORY
14445f210c2aSfgsch 					   | SEC_READONLY
14455f210c2aSfgsch 					   | SEC_LINKER_CREATED))
14465f210c2aSfgsch       || !bfd_set_section_alignment (abfd, s, 3))
1447d2201f2fSdrahn     return FALSE;
14485f210c2aSfgsch   elf64_hppa_hash_table (info)->plt_rel_sec = s;
14495f210c2aSfgsch 
14505f210c2aSfgsch   s = bfd_make_section(abfd, ".rela.data");
14515f210c2aSfgsch   if (s == NULL
14525f210c2aSfgsch       || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
14535f210c2aSfgsch 					   | SEC_HAS_CONTENTS
14545f210c2aSfgsch 					   | SEC_IN_MEMORY
14555f210c2aSfgsch 					   | SEC_READONLY
14565f210c2aSfgsch 					   | SEC_LINKER_CREATED))
14575f210c2aSfgsch       || !bfd_set_section_alignment (abfd, s, 3))
1458d2201f2fSdrahn     return FALSE;
14595f210c2aSfgsch   elf64_hppa_hash_table (info)->other_rel_sec = s;
14605f210c2aSfgsch 
14615f210c2aSfgsch   s = bfd_make_section(abfd, ".rela.opd");
14625f210c2aSfgsch   if (s == NULL
14635f210c2aSfgsch       || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
14645f210c2aSfgsch 					   | SEC_HAS_CONTENTS
14655f210c2aSfgsch 					   | SEC_IN_MEMORY
14665f210c2aSfgsch 					   | SEC_READONLY
14675f210c2aSfgsch 					   | SEC_LINKER_CREATED))
14685f210c2aSfgsch       || !bfd_set_section_alignment (abfd, s, 3))
1469d2201f2fSdrahn     return FALSE;
14705f210c2aSfgsch   elf64_hppa_hash_table (info)->opd_rel_sec = s;
14715f210c2aSfgsch 
1472d2201f2fSdrahn   return TRUE;
14735f210c2aSfgsch }
14745f210c2aSfgsch 
14755f210c2aSfgsch /* Allocate dynamic relocations for those symbols that turned out
14765f210c2aSfgsch    to be dynamic.  */
14775f210c2aSfgsch 
1478d2201f2fSdrahn static bfd_boolean
allocate_dynrel_entries(dyn_h,data)14795f210c2aSfgsch allocate_dynrel_entries (dyn_h, data)
14805f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
14815f210c2aSfgsch      PTR data;
14825f210c2aSfgsch {
14835f210c2aSfgsch   struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
14845f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
14855f210c2aSfgsch   struct elf64_hppa_dyn_reloc_entry *rent;
1486d2201f2fSdrahn   bfd_boolean dynamic_symbol, shared;
14875f210c2aSfgsch 
14885f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (x->info);
14895f210c2aSfgsch   dynamic_symbol = elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info);
14905f210c2aSfgsch   shared = x->info->shared;
14915f210c2aSfgsch 
14925f210c2aSfgsch   /* We may need to allocate relocations for a non-dynamic symbol
14935f210c2aSfgsch      when creating a shared library.  */
14945f210c2aSfgsch   if (!dynamic_symbol && !shared)
1495d2201f2fSdrahn     return TRUE;
14965f210c2aSfgsch 
14975f210c2aSfgsch   /* Take care of the normal data relocations.  */
14985f210c2aSfgsch 
14995f210c2aSfgsch   for (rent = dyn_h->reloc_entries; rent; rent = rent->next)
15005f210c2aSfgsch     {
1501d2201f2fSdrahn       /* Allocate one iff we are building a shared library, the relocation
1502d2201f2fSdrahn 	 isn't a R_PARISC_FPTR64, or we don't want an opd entry.  */
1503d2201f2fSdrahn       if (!shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
15045f210c2aSfgsch 	continue;
1505d2201f2fSdrahn 
15065f210c2aSfgsch       hppa_info->other_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
15075f210c2aSfgsch 
15085f210c2aSfgsch       /* Make sure this symbol gets into the dynamic symbol table if it is
15095f210c2aSfgsch 	 not already recorded.  ?!? This should not be in the loop since
15105f210c2aSfgsch 	 the symbol need only be added once.  */
1511d2201f2fSdrahn       if (dyn_h->h == 0
1512d2201f2fSdrahn 	  || (dyn_h->h->dynindx == -1 && dyn_h->h->type != STT_PARISC_MILLI))
1513cf2f2c56Smiod 	if (!bfd_elf_link_record_local_dynamic_symbol
15145f210c2aSfgsch 	    (x->info, rent->sec->owner, dyn_h->sym_indx))
1515d2201f2fSdrahn 	  return FALSE;
15165f210c2aSfgsch     }
15175f210c2aSfgsch 
15185f210c2aSfgsch   /* Take care of the GOT and PLT relocations.  */
15195f210c2aSfgsch 
15205f210c2aSfgsch   if ((dynamic_symbol || shared) && dyn_h->want_dlt)
15215f210c2aSfgsch     hppa_info->dlt_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
15225f210c2aSfgsch 
15235f210c2aSfgsch   /* If we are building a shared library, then every symbol that has an
15245f210c2aSfgsch      opd entry will need an EPLT relocation to relocate the symbol's address
15255f210c2aSfgsch      and __gp value based on the runtime load address.  */
15265f210c2aSfgsch   if (shared && dyn_h->want_opd)
15275f210c2aSfgsch     hppa_info->opd_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
15285f210c2aSfgsch 
15295f210c2aSfgsch   if (dyn_h->want_plt && dynamic_symbol)
15305f210c2aSfgsch     {
15315f210c2aSfgsch       bfd_size_type t = 0;
15325f210c2aSfgsch 
15335f210c2aSfgsch       /* Dynamic symbols get one IPLT relocation.  Local symbols in
15345f210c2aSfgsch 	 shared libraries get two REL relocations.  Local symbols in
15355f210c2aSfgsch 	 main applications get nothing.  */
15365f210c2aSfgsch       if (dynamic_symbol)
15375f210c2aSfgsch 	t = sizeof (Elf64_External_Rela);
15385f210c2aSfgsch       else if (shared)
15395f210c2aSfgsch 	t = 2 * sizeof (Elf64_External_Rela);
15405f210c2aSfgsch 
15415f210c2aSfgsch       hppa_info->plt_rel_sec->_raw_size += t;
15425f210c2aSfgsch     }
15435f210c2aSfgsch 
1544d2201f2fSdrahn   return TRUE;
15455f210c2aSfgsch }
15465f210c2aSfgsch 
15475f210c2aSfgsch /* Adjust a symbol defined by a dynamic object and referenced by a
15485f210c2aSfgsch    regular object.  */
15495f210c2aSfgsch 
1550d2201f2fSdrahn static bfd_boolean
elf64_hppa_adjust_dynamic_symbol(info,h)15515f210c2aSfgsch elf64_hppa_adjust_dynamic_symbol (info, h)
15525f210c2aSfgsch      struct bfd_link_info *info ATTRIBUTE_UNUSED;
15535f210c2aSfgsch      struct elf_link_hash_entry *h;
15545f210c2aSfgsch {
15555f210c2aSfgsch   /* ??? Undefined symbols with PLT entries should be re-defined
15565f210c2aSfgsch      to be the PLT entry.  */
15575f210c2aSfgsch 
15585f210c2aSfgsch   /* If this is a weak symbol, and there is a real definition, the
15595f210c2aSfgsch      processor independent code will have arranged for us to see the
15605f210c2aSfgsch      real definition first, and we can just use the same value.  */
15615f210c2aSfgsch   if (h->weakdef != NULL)
15625f210c2aSfgsch     {
15635f210c2aSfgsch       BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
15645f210c2aSfgsch 		  || h->weakdef->root.type == bfd_link_hash_defweak);
15655f210c2aSfgsch       h->root.u.def.section = h->weakdef->root.u.def.section;
15665f210c2aSfgsch       h->root.u.def.value = h->weakdef->root.u.def.value;
1567d2201f2fSdrahn       return TRUE;
15685f210c2aSfgsch     }
15695f210c2aSfgsch 
15705f210c2aSfgsch   /* If this is a reference to a symbol defined by a dynamic object which
15715f210c2aSfgsch      is not a function, we might allocate the symbol in our .dynbss section
15725f210c2aSfgsch      and allocate a COPY dynamic relocation.
15735f210c2aSfgsch 
15745f210c2aSfgsch      But PA64 code is canonically PIC, so as a rule we can avoid this sort
15755f210c2aSfgsch      of hackery.  */
15765f210c2aSfgsch 
1577d2201f2fSdrahn   return TRUE;
1578d2201f2fSdrahn }
1579d2201f2fSdrahn 
1580d2201f2fSdrahn /* This function is called via elf_link_hash_traverse to mark millicode
1581d2201f2fSdrahn    symbols with a dynindx of -1 and to remove the string table reference
1582d2201f2fSdrahn    from the dynamic symbol table.  If the symbol is not a millicode symbol,
1583d2201f2fSdrahn    elf64_hppa_mark_exported_functions is called.  */
1584d2201f2fSdrahn 
1585d2201f2fSdrahn static bfd_boolean
elf64_hppa_mark_milli_and_exported_functions(h,data)1586d2201f2fSdrahn elf64_hppa_mark_milli_and_exported_functions (h, data)
1587d2201f2fSdrahn      struct elf_link_hash_entry *h;
1588d2201f2fSdrahn      PTR data;
1589d2201f2fSdrahn {
1590d2201f2fSdrahn   struct bfd_link_info *info = (struct bfd_link_info *)data;
1591d2201f2fSdrahn   struct elf_link_hash_entry *elf = h;
1592d2201f2fSdrahn 
1593d2201f2fSdrahn   if (elf->root.type == bfd_link_hash_warning)
1594d2201f2fSdrahn     elf = (struct elf_link_hash_entry *) elf->root.u.i.link;
1595d2201f2fSdrahn 
1596d2201f2fSdrahn   if (elf->type == STT_PARISC_MILLI)
1597d2201f2fSdrahn     {
1598d2201f2fSdrahn       if (elf->dynindx != -1)
1599d2201f2fSdrahn 	{
1600d2201f2fSdrahn 	  elf->dynindx = -1;
1601d2201f2fSdrahn 	  _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
1602d2201f2fSdrahn 				  elf->dynstr_index);
1603d2201f2fSdrahn 	}
1604d2201f2fSdrahn       return TRUE;
1605d2201f2fSdrahn     }
1606d2201f2fSdrahn 
1607d2201f2fSdrahn   return elf64_hppa_mark_exported_functions (h, data);
16085f210c2aSfgsch }
16095f210c2aSfgsch 
16105f210c2aSfgsch /* Set the final sizes of the dynamic sections and allocate memory for
16115f210c2aSfgsch    the contents of our special sections.  */
16125f210c2aSfgsch 
1613d2201f2fSdrahn static bfd_boolean
elf64_hppa_size_dynamic_sections(output_bfd,info)16145f210c2aSfgsch elf64_hppa_size_dynamic_sections (output_bfd, info)
16155f210c2aSfgsch      bfd *output_bfd;
16165f210c2aSfgsch      struct bfd_link_info *info;
16175f210c2aSfgsch {
16185f210c2aSfgsch   bfd *dynobj;
16195f210c2aSfgsch   asection *s;
1620d2201f2fSdrahn   bfd_boolean plt;
1621d2201f2fSdrahn   bfd_boolean relocs;
1622d2201f2fSdrahn   bfd_boolean reltext;
16235f210c2aSfgsch   struct elf64_hppa_allocate_data data;
16245f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
16255f210c2aSfgsch 
16265f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
16275f210c2aSfgsch 
16285f210c2aSfgsch   dynobj = elf_hash_table (info)->dynobj;
16295f210c2aSfgsch   BFD_ASSERT (dynobj != NULL);
16305f210c2aSfgsch 
1631d2201f2fSdrahn   /* Mark each function this program exports so that we will allocate
1632d2201f2fSdrahn      space in the .opd section for each function's FPTR.  If we are
1633d2201f2fSdrahn      creating dynamic sections, change the dynamic index of millicode
1634d2201f2fSdrahn      symbols to -1 and remove them from the string table for .dynstr.
1635d2201f2fSdrahn 
1636d2201f2fSdrahn      We have to traverse the main linker hash table since we have to
1637d2201f2fSdrahn      find functions which may not have been mentioned in any relocs.  */
1638d2201f2fSdrahn   elf_link_hash_traverse (elf_hash_table (info),
1639d2201f2fSdrahn 			  (elf_hash_table (info)->dynamic_sections_created
1640d2201f2fSdrahn 			   ? elf64_hppa_mark_milli_and_exported_functions
1641d2201f2fSdrahn 			   : elf64_hppa_mark_exported_functions),
1642d2201f2fSdrahn 			  info);
1643d2201f2fSdrahn 
16445f210c2aSfgsch   if (elf_hash_table (info)->dynamic_sections_created)
16455f210c2aSfgsch     {
16465f210c2aSfgsch       /* Set the contents of the .interp section to the interpreter.  */
1647*2d6de53bSkettenis       if (info->executable && !info->static_link)
16485f210c2aSfgsch 	{
16495f210c2aSfgsch 	  s = bfd_get_section_by_name (dynobj, ".interp");
16505f210c2aSfgsch 	  BFD_ASSERT (s != NULL);
16515f210c2aSfgsch 	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
16525f210c2aSfgsch 	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
16535f210c2aSfgsch 	}
16545f210c2aSfgsch     }
16555f210c2aSfgsch   else
16565f210c2aSfgsch     {
16575f210c2aSfgsch       /* We may have created entries in the .rela.got section.
16585f210c2aSfgsch 	 However, if we are not creating the dynamic sections, we will
16595f210c2aSfgsch 	 not actually use these entries.  Reset the size of .rela.dlt,
16605f210c2aSfgsch 	 which will cause it to get stripped from the output file
16615f210c2aSfgsch 	 below.  */
16625f210c2aSfgsch       s = bfd_get_section_by_name (dynobj, ".rela.dlt");
16635f210c2aSfgsch       if (s != NULL)
16645f210c2aSfgsch 	s->_raw_size = 0;
16655f210c2aSfgsch     }
16665f210c2aSfgsch 
16675f210c2aSfgsch   /* Allocate the GOT entries.  */
16685f210c2aSfgsch 
16695f210c2aSfgsch   data.info = info;
16705f210c2aSfgsch   if (elf64_hppa_hash_table (info)->dlt_sec)
16715f210c2aSfgsch     {
16725f210c2aSfgsch       data.ofs = 0x0;
16735f210c2aSfgsch       elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
16745f210c2aSfgsch 				    allocate_global_data_dlt, &data);
16755f210c2aSfgsch       hppa_info->dlt_sec->_raw_size = data.ofs;
16765f210c2aSfgsch 
16775f210c2aSfgsch       data.ofs = 0x0;
16785f210c2aSfgsch       elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
16795f210c2aSfgsch 				    allocate_global_data_plt, &data);
16805f210c2aSfgsch       hppa_info->plt_sec->_raw_size = data.ofs;
16815f210c2aSfgsch 
16825f210c2aSfgsch       data.ofs = 0x0;
16835f210c2aSfgsch       elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
16845f210c2aSfgsch 				    allocate_global_data_stub, &data);
16855f210c2aSfgsch       hppa_info->stub_sec->_raw_size = data.ofs;
16865f210c2aSfgsch     }
16875f210c2aSfgsch 
16885f210c2aSfgsch   /* Allocate space for entries in the .opd section.  */
16895f210c2aSfgsch   if (elf64_hppa_hash_table (info)->opd_sec)
16905f210c2aSfgsch     {
16915f210c2aSfgsch       data.ofs = 0;
16925f210c2aSfgsch       elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
16935f210c2aSfgsch 				    allocate_global_data_opd, &data);
16945f210c2aSfgsch       hppa_info->opd_sec->_raw_size = data.ofs;
16955f210c2aSfgsch     }
16965f210c2aSfgsch 
16975f210c2aSfgsch   /* Now allocate space for dynamic relocations, if necessary.  */
16985f210c2aSfgsch   if (hppa_info->root.dynamic_sections_created)
16995f210c2aSfgsch     elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
17005f210c2aSfgsch 				  allocate_dynrel_entries, &data);
17015f210c2aSfgsch 
17025f210c2aSfgsch   /* The sizes of all the sections are set.  Allocate memory for them.  */
1703d2201f2fSdrahn   plt = FALSE;
1704d2201f2fSdrahn   relocs = FALSE;
1705d2201f2fSdrahn   reltext = FALSE;
17065f210c2aSfgsch   for (s = dynobj->sections; s != NULL; s = s->next)
17075f210c2aSfgsch     {
17085f210c2aSfgsch       const char *name;
1709d2201f2fSdrahn       bfd_boolean strip;
17105f210c2aSfgsch 
17115f210c2aSfgsch       if ((s->flags & SEC_LINKER_CREATED) == 0)
17125f210c2aSfgsch 	continue;
17135f210c2aSfgsch 
17145f210c2aSfgsch       /* It's OK to base decisions on the section name, because none
17155f210c2aSfgsch 	 of the dynobj section names depend upon the input files.  */
17165f210c2aSfgsch       name = bfd_get_section_name (dynobj, s);
17175f210c2aSfgsch 
17185f210c2aSfgsch       strip = 0;
17195f210c2aSfgsch 
17205f210c2aSfgsch       if (strcmp (name, ".plt") == 0)
17215f210c2aSfgsch 	{
1722d2201f2fSdrahn 	  /* Strip this section if we don't need it; see the comment below.  */
17235f210c2aSfgsch 	  if (s->_raw_size == 0)
17245f210c2aSfgsch 	    {
1725d2201f2fSdrahn 	      strip = TRUE;
17265f210c2aSfgsch 	    }
17275f210c2aSfgsch 	  else
17285f210c2aSfgsch 	    {
17295f210c2aSfgsch 	      /* Remember whether there is a PLT.  */
1730d2201f2fSdrahn 	      plt = TRUE;
17315f210c2aSfgsch 	    }
17325f210c2aSfgsch 	}
17335f210c2aSfgsch       else if (strcmp (name, ".dlt") == 0)
17345f210c2aSfgsch 	{
1735d2201f2fSdrahn 	  /* Strip this section if we don't need it; see the comment below.  */
17365f210c2aSfgsch 	  if (s->_raw_size == 0)
17375f210c2aSfgsch 	    {
1738d2201f2fSdrahn 	      strip = TRUE;
17395f210c2aSfgsch 	    }
17405f210c2aSfgsch 	}
17415f210c2aSfgsch       else if (strcmp (name, ".opd") == 0)
17425f210c2aSfgsch 	{
1743d2201f2fSdrahn 	  /* Strip this section if we don't need it; see the comment below.  */
17445f210c2aSfgsch 	  if (s->_raw_size == 0)
17455f210c2aSfgsch 	    {
1746d2201f2fSdrahn 	      strip = TRUE;
17475f210c2aSfgsch 	    }
17485f210c2aSfgsch 	}
1749d2201f2fSdrahn       else if (strncmp (name, ".rela", 5) == 0)
17505f210c2aSfgsch 	{
1751d2201f2fSdrahn 	  /* If we don't need this section, strip it from the output file.
1752d2201f2fSdrahn 	     This is mostly to handle .rela.bss and .rela.plt.  We must
1753d2201f2fSdrahn 	     create both sections in create_dynamic_sections, because they
1754d2201f2fSdrahn 	     must be created before the linker maps input sections to output
1755d2201f2fSdrahn 	     sections.  The linker does that before adjust_dynamic_symbol
1756d2201f2fSdrahn 	     is called, and it is that function which decides whether
1757d2201f2fSdrahn 	     anything needs to go into these sections.  */
17585f210c2aSfgsch 	  if (s->_raw_size == 0)
17595f210c2aSfgsch 	    {
17605f210c2aSfgsch 	      /* If we don't need this section, strip it from the
17615f210c2aSfgsch 		 output file.  This is mostly to handle .rela.bss and
17625f210c2aSfgsch 		 .rela.plt.  We must create both sections in
17635f210c2aSfgsch 		 create_dynamic_sections, because they must be created
17645f210c2aSfgsch 		 before the linker maps input sections to output
17655f210c2aSfgsch 		 sections.  The linker does that before
17665f210c2aSfgsch 		 adjust_dynamic_symbol is called, and it is that
17675f210c2aSfgsch 		 function which decides whether anything needs to go
17685f210c2aSfgsch 		 into these sections.  */
1769d2201f2fSdrahn 	      strip = TRUE;
17705f210c2aSfgsch 	    }
17715f210c2aSfgsch 	  else
17725f210c2aSfgsch 	    {
17735f210c2aSfgsch 	      asection *target;
17745f210c2aSfgsch 
17755f210c2aSfgsch 	      /* Remember whether there are any reloc sections other
17765f210c2aSfgsch 		 than .rela.plt.  */
17775f210c2aSfgsch 	      if (strcmp (name, ".rela.plt") != 0)
17785f210c2aSfgsch 		{
17795f210c2aSfgsch 		  const char *outname;
17805f210c2aSfgsch 
1781d2201f2fSdrahn 		  relocs = TRUE;
17825f210c2aSfgsch 
17835f210c2aSfgsch 		  /* If this relocation section applies to a read only
17845f210c2aSfgsch 		     section, then we probably need a DT_TEXTREL
17855f210c2aSfgsch 		     entry.  The entries in the .rela.plt section
17865f210c2aSfgsch 		     really apply to the .got section, which we
17875f210c2aSfgsch 		     created ourselves and so know is not readonly.  */
17885f210c2aSfgsch 		  outname = bfd_get_section_name (output_bfd,
17895f210c2aSfgsch 						  s->output_section);
17905f210c2aSfgsch 		  target = bfd_get_section_by_name (output_bfd, outname + 4);
17915f210c2aSfgsch 		  if (target != NULL
17925f210c2aSfgsch 		      && (target->flags & SEC_READONLY) != 0
17935f210c2aSfgsch 		      && (target->flags & SEC_ALLOC) != 0)
1794d2201f2fSdrahn 		    reltext = TRUE;
17955f210c2aSfgsch 		}
17965f210c2aSfgsch 
17975f210c2aSfgsch 	      /* We use the reloc_count field as a counter if we need
17985f210c2aSfgsch 		 to copy relocs into the output file.  */
17995f210c2aSfgsch 	      s->reloc_count = 0;
18005f210c2aSfgsch 	    }
18015f210c2aSfgsch 	}
18025f210c2aSfgsch       else if (strncmp (name, ".dlt", 4) != 0
18035f210c2aSfgsch 	       && strcmp (name, ".stub") != 0
18045f210c2aSfgsch 	       && strcmp (name, ".got") != 0)
18055f210c2aSfgsch 	{
18065f210c2aSfgsch 	  /* It's not one of our sections, so don't allocate space.  */
18075f210c2aSfgsch 	  continue;
18085f210c2aSfgsch 	}
18095f210c2aSfgsch 
18105f210c2aSfgsch       if (strip)
18115f210c2aSfgsch 	{
18125f210c2aSfgsch 	  _bfd_strip_section_from_output (info, s);
18135f210c2aSfgsch 	  continue;
18145f210c2aSfgsch 	}
18155f210c2aSfgsch 
18165f210c2aSfgsch       /* Allocate memory for the section contents if it has not
18175f210c2aSfgsch 	 been allocated already.  We use bfd_zalloc here in case
18185f210c2aSfgsch 	 unused entries are not reclaimed before the section's
18195f210c2aSfgsch 	 contents are written out.  This should not happen, but this
18205f210c2aSfgsch 	 way if it does, we get a R_PARISC_NONE reloc instead of
18215f210c2aSfgsch 	 garbage.  */
18225f210c2aSfgsch       if (s->contents == NULL)
18235f210c2aSfgsch 	{
18245f210c2aSfgsch 	  s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
18255f210c2aSfgsch 	  if (s->contents == NULL && s->_raw_size != 0)
1826d2201f2fSdrahn 	    return FALSE;
18275f210c2aSfgsch 	}
18285f210c2aSfgsch     }
18295f210c2aSfgsch 
18305f210c2aSfgsch   if (elf_hash_table (info)->dynamic_sections_created)
18315f210c2aSfgsch     {
18325f210c2aSfgsch       /* Always create a DT_PLTGOT.  It actually has nothing to do with
18335f210c2aSfgsch 	 the PLT, it is how we communicate the __gp value of a load
18345f210c2aSfgsch 	 module to the dynamic linker.  */
1835d2201f2fSdrahn #define add_dynamic_entry(TAG, VAL) \
1836cf2f2c56Smiod   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1837d2201f2fSdrahn 
1838d2201f2fSdrahn       if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0)
1839d2201f2fSdrahn 	  || !add_dynamic_entry (DT_PLTGOT, 0))
1840d2201f2fSdrahn 	return FALSE;
18415f210c2aSfgsch 
18425f210c2aSfgsch       /* Add some entries to the .dynamic section.  We fill in the
18435f210c2aSfgsch 	 values later, in elf64_hppa_finish_dynamic_sections, but we
18445f210c2aSfgsch 	 must add the entries now so that we get the correct size for
18455f210c2aSfgsch 	 the .dynamic section.  The DT_DEBUG entry is filled in by the
18465f210c2aSfgsch 	 dynamic linker and used by the debugger.  */
18475f210c2aSfgsch       if (! info->shared)
18485f210c2aSfgsch 	{
1849d2201f2fSdrahn 	  if (!add_dynamic_entry (DT_DEBUG, 0)
1850d2201f2fSdrahn 	      || !add_dynamic_entry (DT_HP_DLD_HOOK, 0)
1851d2201f2fSdrahn 	      || !add_dynamic_entry (DT_HP_LOAD_MAP, 0))
1852d2201f2fSdrahn 	    return FALSE;
18535f210c2aSfgsch 	}
18545f210c2aSfgsch 
1855d2201f2fSdrahn       /* Force DT_FLAGS to always be set.
1856d2201f2fSdrahn 	 Required by HPUX 11.00 patch PHSS_26559.  */
1857d2201f2fSdrahn       if (!add_dynamic_entry (DT_FLAGS, (info)->flags))
1858d2201f2fSdrahn 	return FALSE;
1859d2201f2fSdrahn 
18605f210c2aSfgsch       if (plt)
18615f210c2aSfgsch 	{
1862d2201f2fSdrahn 	  if (!add_dynamic_entry (DT_PLTRELSZ, 0)
1863d2201f2fSdrahn 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
1864d2201f2fSdrahn 	      || !add_dynamic_entry (DT_JMPREL, 0))
1865d2201f2fSdrahn 	    return FALSE;
18665f210c2aSfgsch 	}
18675f210c2aSfgsch 
18685f210c2aSfgsch       if (relocs)
18695f210c2aSfgsch 	{
1870d2201f2fSdrahn 	  if (!add_dynamic_entry (DT_RELA, 0)
1871d2201f2fSdrahn 	      || !add_dynamic_entry (DT_RELASZ, 0)
1872d2201f2fSdrahn 	      || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
1873d2201f2fSdrahn 	    return FALSE;
18745f210c2aSfgsch 	}
18755f210c2aSfgsch 
18765f210c2aSfgsch       if (reltext)
18775f210c2aSfgsch 	{
1878d2201f2fSdrahn 	  if (!add_dynamic_entry (DT_TEXTREL, 0))
1879d2201f2fSdrahn 	    return FALSE;
18805f210c2aSfgsch 	  info->flags |= DF_TEXTREL;
18815f210c2aSfgsch 	}
18825f210c2aSfgsch     }
1883d2201f2fSdrahn #undef add_dynamic_entry
18845f210c2aSfgsch 
1885d2201f2fSdrahn   return TRUE;
18865f210c2aSfgsch }
18875f210c2aSfgsch 
18885f210c2aSfgsch /* Called after we have output the symbol into the dynamic symbol
18895f210c2aSfgsch    table, but before we output the symbol into the normal symbol
18905f210c2aSfgsch    table.
18915f210c2aSfgsch 
18925f210c2aSfgsch    For some symbols we had to change their address when outputting
18935f210c2aSfgsch    the dynamic symbol table.  We undo that change here so that
18945f210c2aSfgsch    the symbols have their expected value in the normal symbol
18955f210c2aSfgsch    table.  Ick.  */
18965f210c2aSfgsch 
1897d2201f2fSdrahn static bfd_boolean
elf64_hppa_link_output_symbol_hook(info,name,sym,input_sec,h)1898cf2f2c56Smiod elf64_hppa_link_output_symbol_hook (info, name, sym, input_sec, h)
18995f210c2aSfgsch      struct bfd_link_info *info;
19005f210c2aSfgsch      const char *name;
19015f210c2aSfgsch      Elf_Internal_Sym *sym;
19025f210c2aSfgsch      asection *input_sec ATTRIBUTE_UNUSED;
1903cf2f2c56Smiod      struct elf_link_hash_entry *h;
19045f210c2aSfgsch {
19055f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
19065f210c2aSfgsch   struct elf64_hppa_dyn_hash_entry *dyn_h;
19075f210c2aSfgsch 
19085f210c2aSfgsch   /* We may be called with the file symbol or section symbols.
19095f210c2aSfgsch      They never need munging, so it is safe to ignore them.  */
19105f210c2aSfgsch   if (!name)
1911d2201f2fSdrahn     return TRUE;
19125f210c2aSfgsch 
19135f210c2aSfgsch   /* Get the PA dyn_symbol (if any) associated with NAME.  */
19145f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
19155f210c2aSfgsch   dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
1916d2201f2fSdrahn 				      name, FALSE, FALSE);
1917cf2f2c56Smiod   if (!dyn_h || dyn_h->h != h)
1918cf2f2c56Smiod     return TRUE;
19195f210c2aSfgsch 
19205f210c2aSfgsch   /* Function symbols for which we created .opd entries *may* have been
19215f210c2aSfgsch      munged by finish_dynamic_symbol and have to be un-munged here.
19225f210c2aSfgsch 
19235f210c2aSfgsch      Note that finish_dynamic_symbol sometimes turns dynamic symbols
19245f210c2aSfgsch      into non-dynamic ones, so we initialize st_shndx to -1 in
19255f210c2aSfgsch      mark_exported_functions and check to see if it was overwritten
19265f210c2aSfgsch      here instead of just checking dyn_h->h->dynindx.  */
1927cf2f2c56Smiod   if (dyn_h->want_opd && dyn_h->st_shndx != -1)
19285f210c2aSfgsch     {
19295f210c2aSfgsch       /* Restore the saved value and section index.  */
19305f210c2aSfgsch       sym->st_value = dyn_h->st_value;
19315f210c2aSfgsch       sym->st_shndx = dyn_h->st_shndx;
19325f210c2aSfgsch     }
19335f210c2aSfgsch 
1934d2201f2fSdrahn   return TRUE;
19355f210c2aSfgsch }
19365f210c2aSfgsch 
19375f210c2aSfgsch /* Finish up dynamic symbol handling.  We set the contents of various
19385f210c2aSfgsch    dynamic sections here.  */
19395f210c2aSfgsch 
1940d2201f2fSdrahn static bfd_boolean
elf64_hppa_finish_dynamic_symbol(output_bfd,info,h,sym)19415f210c2aSfgsch elf64_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
19425f210c2aSfgsch      bfd *output_bfd;
19435f210c2aSfgsch      struct bfd_link_info *info;
19445f210c2aSfgsch      struct elf_link_hash_entry *h;
19455f210c2aSfgsch      Elf_Internal_Sym *sym;
19465f210c2aSfgsch {
19475f210c2aSfgsch   asection *stub, *splt, *sdlt, *sopd, *spltrel, *sdltrel;
19485f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
19495f210c2aSfgsch   struct elf64_hppa_dyn_hash_entry *dyn_h;
19505f210c2aSfgsch 
19515f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
19525f210c2aSfgsch   dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
1953d2201f2fSdrahn 				      h->root.root.string, FALSE, FALSE);
19545f210c2aSfgsch 
19555f210c2aSfgsch   stub = hppa_info->stub_sec;
19565f210c2aSfgsch   splt = hppa_info->plt_sec;
19575f210c2aSfgsch   sdlt = hppa_info->dlt_sec;
19585f210c2aSfgsch   sopd = hppa_info->opd_sec;
19595f210c2aSfgsch   spltrel = hppa_info->plt_rel_sec;
19605f210c2aSfgsch   sdltrel = hppa_info->dlt_rel_sec;
19615f210c2aSfgsch 
19625f210c2aSfgsch   /* Incredible.  It is actually necessary to NOT use the symbol's real
19635f210c2aSfgsch      value when building the dynamic symbol table for a shared library.
19645f210c2aSfgsch      At least for symbols that refer to functions.
19655f210c2aSfgsch 
19665f210c2aSfgsch      We will store a new value and section index into the symbol long
19675f210c2aSfgsch      enough to output it into the dynamic symbol table, then we restore
19685f210c2aSfgsch      the original values (in elf64_hppa_link_output_symbol_hook).  */
19695f210c2aSfgsch   if (dyn_h && dyn_h->want_opd)
19705f210c2aSfgsch     {
1971d2201f2fSdrahn       BFD_ASSERT (sopd != NULL)
1972d2201f2fSdrahn 
19735f210c2aSfgsch       /* Save away the original value and section index so that we
19745f210c2aSfgsch 	 can restore them later.  */
19755f210c2aSfgsch       dyn_h->st_value = sym->st_value;
19765f210c2aSfgsch       dyn_h->st_shndx = sym->st_shndx;
19775f210c2aSfgsch 
19785f210c2aSfgsch       /* For the dynamic symbol table entry, we want the value to be
19795f210c2aSfgsch 	 address of this symbol's entry within the .opd section.  */
19805f210c2aSfgsch       sym->st_value = (dyn_h->opd_offset
19815f210c2aSfgsch 		       + sopd->output_offset
19825f210c2aSfgsch 		       + sopd->output_section->vma);
19835f210c2aSfgsch       sym->st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
19845f210c2aSfgsch 							 sopd->output_section);
19855f210c2aSfgsch     }
19865f210c2aSfgsch 
19875f210c2aSfgsch   /* Initialize a .plt entry if requested.  */
19885f210c2aSfgsch   if (dyn_h && dyn_h->want_plt
19895f210c2aSfgsch       && elf64_hppa_dynamic_symbol_p (dyn_h->h, info))
19905f210c2aSfgsch     {
19915f210c2aSfgsch       bfd_vma value;
19925f210c2aSfgsch       Elf_Internal_Rela rel;
1993d2201f2fSdrahn       bfd_byte *loc;
1994d2201f2fSdrahn 
1995d2201f2fSdrahn       BFD_ASSERT (splt != NULL && spltrel != NULL)
19965f210c2aSfgsch 
19975f210c2aSfgsch       /* We do not actually care about the value in the PLT entry
19985f210c2aSfgsch 	 if we are creating a shared library and the symbol is
19995f210c2aSfgsch 	 still undefined, we create a dynamic relocation to fill
20005f210c2aSfgsch 	 in the correct value.  */
20015f210c2aSfgsch       if (info->shared && h->root.type == bfd_link_hash_undefined)
20025f210c2aSfgsch 	value = 0;
20035f210c2aSfgsch       else
20045f210c2aSfgsch 	value = (h->root.u.def.value + h->root.u.def.section->vma);
20055f210c2aSfgsch 
20065f210c2aSfgsch       /* Fill in the entry in the procedure linkage table.
20075f210c2aSfgsch 
20085f210c2aSfgsch 	 The format of a plt entry is
20095f210c2aSfgsch 	 <funcaddr> <__gp>.
20105f210c2aSfgsch 
20115f210c2aSfgsch 	 plt_offset is the offset within the PLT section at which to
20125f210c2aSfgsch 	 install the PLT entry.
20135f210c2aSfgsch 
20145f210c2aSfgsch 	 We are modifying the in-memory PLT contents here, so we do not add
20155f210c2aSfgsch 	 in the output_offset of the PLT section.  */
20165f210c2aSfgsch 
20175f210c2aSfgsch       bfd_put_64 (splt->owner, value, splt->contents + dyn_h->plt_offset);
20185f210c2aSfgsch       value = _bfd_get_gp_value (splt->output_section->owner);
20195f210c2aSfgsch       bfd_put_64 (splt->owner, value, splt->contents + dyn_h->plt_offset + 0x8);
20205f210c2aSfgsch 
20215f210c2aSfgsch       /* Create a dynamic IPLT relocation for this entry.
20225f210c2aSfgsch 
20235f210c2aSfgsch 	 We are creating a relocation in the output file's PLT section,
20245f210c2aSfgsch 	 which is included within the DLT secton.  So we do need to include
20255f210c2aSfgsch 	 the PLT's output_offset in the computation of the relocation's
20265f210c2aSfgsch 	 address.  */
20275f210c2aSfgsch       rel.r_offset = (dyn_h->plt_offset + splt->output_offset
20285f210c2aSfgsch 		      + splt->output_section->vma);
20295f210c2aSfgsch       rel.r_info = ELF64_R_INFO (h->dynindx, R_PARISC_IPLT);
20305f210c2aSfgsch       rel.r_addend = 0;
20315f210c2aSfgsch 
2032d2201f2fSdrahn       loc = spltrel->contents;
2033d2201f2fSdrahn       loc += spltrel->reloc_count++ * sizeof (Elf64_External_Rela);
2034d2201f2fSdrahn       bfd_elf64_swap_reloca_out (splt->output_section->owner, &rel, loc);
20355f210c2aSfgsch     }
20365f210c2aSfgsch 
20375f210c2aSfgsch   /* Initialize an external call stub entry if requested.  */
20385f210c2aSfgsch   if (dyn_h && dyn_h->want_stub
20395f210c2aSfgsch       && elf64_hppa_dynamic_symbol_p (dyn_h->h, info))
20405f210c2aSfgsch     {
20415f210c2aSfgsch       bfd_vma value;
20425f210c2aSfgsch       int insn;
20435f210c2aSfgsch       unsigned int max_offset;
20445f210c2aSfgsch 
2045d2201f2fSdrahn       BFD_ASSERT (stub != NULL)
2046d2201f2fSdrahn 
20475f210c2aSfgsch       /* Install the generic stub template.
20485f210c2aSfgsch 
20495f210c2aSfgsch 	 We are modifying the contents of the stub section, so we do not
20505f210c2aSfgsch 	 need to include the stub section's output_offset here.  */
20515f210c2aSfgsch       memcpy (stub->contents + dyn_h->stub_offset, plt_stub, sizeof (plt_stub));
20525f210c2aSfgsch 
20535f210c2aSfgsch       /* Fix up the first ldd instruction.
20545f210c2aSfgsch 
20555f210c2aSfgsch 	 We are modifying the contents of the STUB section in memory,
20565f210c2aSfgsch 	 so we do not need to include its output offset in this computation.
20575f210c2aSfgsch 
20585f210c2aSfgsch 	 Note the plt_offset value is the value of the PLT entry relative to
20595f210c2aSfgsch 	 the start of the PLT section.  These instructions will reference
20605f210c2aSfgsch 	 data relative to the value of __gp, which may not necessarily have
20615f210c2aSfgsch 	 the same address as the start of the PLT section.
20625f210c2aSfgsch 
20635f210c2aSfgsch 	 gp_offset contains the offset of __gp within the PLT section.  */
20645f210c2aSfgsch       value = dyn_h->plt_offset - hppa_info->gp_offset;
20655f210c2aSfgsch 
20665f210c2aSfgsch       insn = bfd_get_32 (stub->owner, stub->contents + dyn_h->stub_offset);
20675f210c2aSfgsch       if (output_bfd->arch_info->mach >= 25)
20685f210c2aSfgsch 	{
20695f210c2aSfgsch 	  /* Wide mode allows 16 bit offsets.  */
20705f210c2aSfgsch 	  max_offset = 32768;
20715f210c2aSfgsch 	  insn &= ~ 0xfff1;
2072d2201f2fSdrahn 	  insn |= re_assemble_16 ((int) value);
20735f210c2aSfgsch 	}
20745f210c2aSfgsch       else
20755f210c2aSfgsch 	{
20765f210c2aSfgsch 	  max_offset = 8192;
20775f210c2aSfgsch 	  insn &= ~ 0x3ff1;
2078d2201f2fSdrahn 	  insn |= re_assemble_14 ((int) value);
20795f210c2aSfgsch 	}
20805f210c2aSfgsch 
20815f210c2aSfgsch       if ((value & 7) || value + max_offset >= 2*max_offset - 8)
20825f210c2aSfgsch 	{
20835f210c2aSfgsch 	  (*_bfd_error_handler) (_("stub entry for %s cannot load .plt, dp offset = %ld"),
20845f210c2aSfgsch 				 dyn_h->root.string,
20855f210c2aSfgsch 				 (long) value);
2086d2201f2fSdrahn 	  return FALSE;
20875f210c2aSfgsch 	}
20885f210c2aSfgsch 
2089d2201f2fSdrahn       bfd_put_32 (stub->owner, (bfd_vma) insn,
20905f210c2aSfgsch 		  stub->contents + dyn_h->stub_offset);
20915f210c2aSfgsch 
20925f210c2aSfgsch       /* Fix up the second ldd instruction.  */
20935f210c2aSfgsch       value += 8;
20945f210c2aSfgsch       insn = bfd_get_32 (stub->owner, stub->contents + dyn_h->stub_offset + 8);
20955f210c2aSfgsch       if (output_bfd->arch_info->mach >= 25)
20965f210c2aSfgsch 	{
20975f210c2aSfgsch 	  insn &= ~ 0xfff1;
2098d2201f2fSdrahn 	  insn |= re_assemble_16 ((int) value);
20995f210c2aSfgsch 	}
21005f210c2aSfgsch       else
21015f210c2aSfgsch 	{
21025f210c2aSfgsch 	  insn &= ~ 0x3ff1;
2103d2201f2fSdrahn 	  insn |= re_assemble_14 ((int) value);
21045f210c2aSfgsch 	}
2105d2201f2fSdrahn       bfd_put_32 (stub->owner, (bfd_vma) insn,
21065f210c2aSfgsch 		  stub->contents + dyn_h->stub_offset + 8);
21075f210c2aSfgsch     }
21085f210c2aSfgsch 
2109d2201f2fSdrahn   return TRUE;
21105f210c2aSfgsch }
21115f210c2aSfgsch 
21125f210c2aSfgsch /* The .opd section contains FPTRs for each function this file
21135f210c2aSfgsch    exports.  Initialize the FPTR entries.  */
21145f210c2aSfgsch 
2115d2201f2fSdrahn static bfd_boolean
elf64_hppa_finalize_opd(dyn_h,data)21165f210c2aSfgsch elf64_hppa_finalize_opd (dyn_h, data)
21175f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
21185f210c2aSfgsch      PTR data;
21195f210c2aSfgsch {
21205f210c2aSfgsch   struct bfd_link_info *info = (struct bfd_link_info *)data;
21215f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
2122d2201f2fSdrahn   struct elf_link_hash_entry *h = dyn_h ? dyn_h->h : NULL;
21235f210c2aSfgsch   asection *sopd;
21245f210c2aSfgsch   asection *sopdrel;
21255f210c2aSfgsch 
21265f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
21275f210c2aSfgsch   sopd = hppa_info->opd_sec;
21285f210c2aSfgsch   sopdrel = hppa_info->opd_rel_sec;
21295f210c2aSfgsch 
2130d2201f2fSdrahn   if (h && dyn_h->want_opd)
21315f210c2aSfgsch     {
21325f210c2aSfgsch       bfd_vma value;
21335f210c2aSfgsch 
21345f210c2aSfgsch       /* The first two words of an .opd entry are zero.
21355f210c2aSfgsch 
21365f210c2aSfgsch 	 We are modifying the contents of the OPD section in memory, so we
21375f210c2aSfgsch 	 do not need to include its output offset in this computation.  */
21385f210c2aSfgsch       memset (sopd->contents + dyn_h->opd_offset, 0, 16);
21395f210c2aSfgsch 
21405f210c2aSfgsch       value = (h->root.u.def.value
21415f210c2aSfgsch 	       + h->root.u.def.section->output_section->vma
21425f210c2aSfgsch 	       + h->root.u.def.section->output_offset);
21435f210c2aSfgsch 
21445f210c2aSfgsch       /* The next word is the address of the function.  */
21455f210c2aSfgsch       bfd_put_64 (sopd->owner, value, sopd->contents + dyn_h->opd_offset + 16);
21465f210c2aSfgsch 
21475f210c2aSfgsch       /* The last word is our local __gp value.  */
21485f210c2aSfgsch       value = _bfd_get_gp_value (sopd->output_section->owner);
21495f210c2aSfgsch       bfd_put_64 (sopd->owner, value, sopd->contents + dyn_h->opd_offset + 24);
21505f210c2aSfgsch     }
21515f210c2aSfgsch 
21525f210c2aSfgsch   /* If we are generating a shared library, we must generate EPLT relocations
21535f210c2aSfgsch      for each entry in the .opd, even for static functions (they may have
21545f210c2aSfgsch      had their address taken).  */
21555f210c2aSfgsch   if (info->shared && dyn_h && dyn_h->want_opd)
21565f210c2aSfgsch     {
2157d2201f2fSdrahn       Elf_Internal_Rela rel;
2158d2201f2fSdrahn       bfd_byte *loc;
21595f210c2aSfgsch       int dynindx;
21605f210c2aSfgsch 
21615f210c2aSfgsch       /* We may need to do a relocation against a local symbol, in
21625f210c2aSfgsch 	 which case we have to look up it's dynamic symbol index off
21635f210c2aSfgsch 	 the local symbol hash table.  */
21645f210c2aSfgsch       if (h && h->dynindx != -1)
21655f210c2aSfgsch 	dynindx = h->dynindx;
21665f210c2aSfgsch       else
21675f210c2aSfgsch 	dynindx
21685f210c2aSfgsch 	  = _bfd_elf_link_lookup_local_dynindx (info, dyn_h->owner,
21695f210c2aSfgsch 						dyn_h->sym_indx);
21705f210c2aSfgsch 
21715f210c2aSfgsch       /* The offset of this relocation is the absolute address of the
21725f210c2aSfgsch 	 .opd entry for this symbol.  */
21735f210c2aSfgsch       rel.r_offset = (dyn_h->opd_offset + sopd->output_offset
21745f210c2aSfgsch 		      + sopd->output_section->vma);
21755f210c2aSfgsch 
21765f210c2aSfgsch       /* If H is non-null, then we have an external symbol.
21775f210c2aSfgsch 
21785f210c2aSfgsch 	 It is imperative that we use a different dynamic symbol for the
21795f210c2aSfgsch 	 EPLT relocation if the symbol has global scope.
21805f210c2aSfgsch 
21815f210c2aSfgsch 	 In the dynamic symbol table, the function symbol will have a value
21825f210c2aSfgsch 	 which is address of the function's .opd entry.
21835f210c2aSfgsch 
21845f210c2aSfgsch 	 Thus, we can not use that dynamic symbol for the EPLT relocation
21855f210c2aSfgsch 	 (if we did, the data in the .opd would reference itself rather
21865f210c2aSfgsch 	 than the actual address of the function).  Instead we have to use
21875f210c2aSfgsch 	 a new dynamic symbol which has the same value as the original global
21885f210c2aSfgsch 	 function symbol.
21895f210c2aSfgsch 
21905f210c2aSfgsch 	 We prefix the original symbol with a "." and use the new symbol in
21915f210c2aSfgsch 	 the EPLT relocation.  This new symbol has already been recorded in
21925f210c2aSfgsch 	 the symbol table, we just have to look it up and use it.
21935f210c2aSfgsch 
21945f210c2aSfgsch 	 We do not have such problems with static functions because we do
21955f210c2aSfgsch 	 not make their addresses in the dynamic symbol table point to
21965f210c2aSfgsch 	 the .opd entry.  Ultimately this should be safe since a static
21975f210c2aSfgsch 	 function can not be directly referenced outside of its shared
21985f210c2aSfgsch 	 library.
21995f210c2aSfgsch 
22005f210c2aSfgsch 	 We do have to play similar games for FPTR relocations in shared
22015f210c2aSfgsch 	 libraries, including those for static symbols.  See the FPTR
22025f210c2aSfgsch 	 handling in elf64_hppa_finalize_dynreloc.  */
22035f210c2aSfgsch       if (h)
22045f210c2aSfgsch 	{
22055f210c2aSfgsch 	  char *new_name;
22065f210c2aSfgsch 	  struct elf_link_hash_entry *nh;
22075f210c2aSfgsch 
22085f210c2aSfgsch 	  new_name = alloca (strlen (h->root.root.string) + 2);
22095f210c2aSfgsch 	  new_name[0] = '.';
22105f210c2aSfgsch 	  strcpy (new_name + 1, h->root.root.string);
22115f210c2aSfgsch 
22125f210c2aSfgsch 	  nh = elf_link_hash_lookup (elf_hash_table (info),
2213d2201f2fSdrahn 				     new_name, FALSE, FALSE, FALSE);
22145f210c2aSfgsch 
22155f210c2aSfgsch 	  /* All we really want from the new symbol is its dynamic
22165f210c2aSfgsch 	     symbol index.  */
22175f210c2aSfgsch 	  dynindx = nh->dynindx;
22185f210c2aSfgsch 	}
22195f210c2aSfgsch 
22205f210c2aSfgsch       rel.r_addend = 0;
22215f210c2aSfgsch       rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT);
22225f210c2aSfgsch 
2223d2201f2fSdrahn       loc = sopdrel->contents;
2224d2201f2fSdrahn       loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela);
2225d2201f2fSdrahn       bfd_elf64_swap_reloca_out (sopd->output_section->owner, &rel, loc);
22265f210c2aSfgsch     }
2227d2201f2fSdrahn   return TRUE;
22285f210c2aSfgsch }
22295f210c2aSfgsch 
22305f210c2aSfgsch /* The .dlt section contains addresses for items referenced through the
22315f210c2aSfgsch    dlt.  Note that we can have a DLTIND relocation for a local symbol, thus
22325f210c2aSfgsch    we can not depend on finish_dynamic_symbol to initialize the .dlt.  */
22335f210c2aSfgsch 
2234d2201f2fSdrahn static bfd_boolean
elf64_hppa_finalize_dlt(dyn_h,data)22355f210c2aSfgsch elf64_hppa_finalize_dlt (dyn_h, data)
22365f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
22375f210c2aSfgsch      PTR data;
22385f210c2aSfgsch {
22395f210c2aSfgsch   struct bfd_link_info *info = (struct bfd_link_info *)data;
22405f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
22415f210c2aSfgsch   asection *sdlt, *sdltrel;
2242d2201f2fSdrahn   struct elf_link_hash_entry *h = dyn_h ? dyn_h->h : NULL;
22435f210c2aSfgsch 
22445f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
22455f210c2aSfgsch 
22465f210c2aSfgsch   sdlt = hppa_info->dlt_sec;
22475f210c2aSfgsch   sdltrel = hppa_info->dlt_rel_sec;
22485f210c2aSfgsch 
22495f210c2aSfgsch   /* H/DYN_H may refer to a local variable and we know it's
22505f210c2aSfgsch      address, so there is no need to create a relocation.  Just install
22515f210c2aSfgsch      the proper value into the DLT, note this shortcut can not be
22525f210c2aSfgsch      skipped when building a shared library.  */
2253d2201f2fSdrahn   if (! info->shared && h && dyn_h->want_dlt)
22545f210c2aSfgsch     {
22555f210c2aSfgsch       bfd_vma value;
22565f210c2aSfgsch 
22575f210c2aSfgsch       /* If we had an LTOFF_FPTR style relocation we want the DLT entry
22585f210c2aSfgsch 	 to point to the FPTR entry in the .opd section.
22595f210c2aSfgsch 
22605f210c2aSfgsch 	 We include the OPD's output offset in this computation as
22615f210c2aSfgsch 	 we are referring to an absolute address in the resulting
22625f210c2aSfgsch 	 object file.  */
22635f210c2aSfgsch       if (dyn_h->want_opd)
22645f210c2aSfgsch 	{
22655f210c2aSfgsch 	  value = (dyn_h->opd_offset
22665f210c2aSfgsch 		   + hppa_info->opd_sec->output_offset
22675f210c2aSfgsch 		   + hppa_info->opd_sec->output_section->vma);
22685f210c2aSfgsch 	}
2269cf2f2c56Smiod       else if ((h->root.type == bfd_link_hash_defined
2270cf2f2c56Smiod 		|| h->root.type == bfd_link_hash_defweak)
2271cf2f2c56Smiod 	       && h->root.u.def.section)
22725f210c2aSfgsch 	{
2273d2201f2fSdrahn 	  value = h->root.u.def.value + h->root.u.def.section->output_offset;
22745f210c2aSfgsch 	  if (h->root.u.def.section->output_section)
22755f210c2aSfgsch 	    value += h->root.u.def.section->output_section->vma;
22765f210c2aSfgsch 	  else
22775f210c2aSfgsch 	    value += h->root.u.def.section->vma;
22785f210c2aSfgsch 	}
2279d2201f2fSdrahn       else
2280d2201f2fSdrahn 	/* We have an undefined function reference.  */
2281d2201f2fSdrahn 	value = 0;
22825f210c2aSfgsch 
22835f210c2aSfgsch       /* We do not need to include the output offset of the DLT section
22845f210c2aSfgsch 	 here because we are modifying the in-memory contents.  */
22855f210c2aSfgsch       bfd_put_64 (sdlt->owner, value, sdlt->contents + dyn_h->dlt_offset);
22865f210c2aSfgsch     }
22875f210c2aSfgsch 
2288cf2f2c56Smiod   /* Create a relocation for the DLT entry associated with this symbol.
22895f210c2aSfgsch      When building a shared library the symbol does not have to be dynamic.  */
22905f210c2aSfgsch   if (dyn_h->want_dlt
22915f210c2aSfgsch       && (elf64_hppa_dynamic_symbol_p (dyn_h->h, info) || info->shared))
22925f210c2aSfgsch     {
2293d2201f2fSdrahn       Elf_Internal_Rela rel;
2294d2201f2fSdrahn       bfd_byte *loc;
22955f210c2aSfgsch       int dynindx;
22965f210c2aSfgsch 
22975f210c2aSfgsch       /* We may need to do a relocation against a local symbol, in
22985f210c2aSfgsch 	 which case we have to look up it's dynamic symbol index off
22995f210c2aSfgsch 	 the local symbol hash table.  */
23005f210c2aSfgsch       if (h && h->dynindx != -1)
23015f210c2aSfgsch 	dynindx = h->dynindx;
23025f210c2aSfgsch       else
23035f210c2aSfgsch 	dynindx
23045f210c2aSfgsch 	  = _bfd_elf_link_lookup_local_dynindx (info, dyn_h->owner,
23055f210c2aSfgsch 						dyn_h->sym_indx);
23065f210c2aSfgsch 
23075f210c2aSfgsch       /* Create a dynamic relocation for this entry.  Do include the output
23085f210c2aSfgsch 	 offset of the DLT entry since we need an absolute address in the
23095f210c2aSfgsch 	 resulting object file.  */
23105f210c2aSfgsch       rel.r_offset = (dyn_h->dlt_offset + sdlt->output_offset
23115f210c2aSfgsch 		      + sdlt->output_section->vma);
23125f210c2aSfgsch       if (h && h->type == STT_FUNC)
23135f210c2aSfgsch 	  rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_FPTR64);
23145f210c2aSfgsch       else
23155f210c2aSfgsch 	  rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_DIR64);
23165f210c2aSfgsch       rel.r_addend = 0;
23175f210c2aSfgsch 
2318d2201f2fSdrahn       loc = sdltrel->contents;
2319d2201f2fSdrahn       loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela);
2320d2201f2fSdrahn       bfd_elf64_swap_reloca_out (sdlt->output_section->owner, &rel, loc);
23215f210c2aSfgsch     }
2322d2201f2fSdrahn   return TRUE;
23235f210c2aSfgsch }
23245f210c2aSfgsch 
23255f210c2aSfgsch /* Finalize the dynamic relocations.  Specifically the FPTR relocations
23265f210c2aSfgsch    for dynamic functions used to initialize static data.  */
23275f210c2aSfgsch 
2328d2201f2fSdrahn static bfd_boolean
elf64_hppa_finalize_dynreloc(dyn_h,data)23295f210c2aSfgsch elf64_hppa_finalize_dynreloc (dyn_h, data)
23305f210c2aSfgsch      struct elf64_hppa_dyn_hash_entry *dyn_h;
23315f210c2aSfgsch      PTR data;
23325f210c2aSfgsch {
23335f210c2aSfgsch   struct bfd_link_info *info = (struct bfd_link_info *)data;
23345f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
23355f210c2aSfgsch   struct elf_link_hash_entry *h;
23365f210c2aSfgsch   int dynamic_symbol;
23375f210c2aSfgsch 
23385f210c2aSfgsch   dynamic_symbol = elf64_hppa_dynamic_symbol_p (dyn_h->h, info);
23395f210c2aSfgsch 
23405f210c2aSfgsch   if (!dynamic_symbol && !info->shared)
2341d2201f2fSdrahn     return TRUE;
23425f210c2aSfgsch 
23435f210c2aSfgsch   if (dyn_h->reloc_entries)
23445f210c2aSfgsch     {
23455f210c2aSfgsch       struct elf64_hppa_dyn_reloc_entry *rent;
23465f210c2aSfgsch       int dynindx;
23475f210c2aSfgsch 
23485f210c2aSfgsch       hppa_info = elf64_hppa_hash_table (info);
23495f210c2aSfgsch       h = dyn_h->h;
23505f210c2aSfgsch 
23515f210c2aSfgsch       /* We may need to do a relocation against a local symbol, in
23525f210c2aSfgsch 	 which case we have to look up it's dynamic symbol index off
23535f210c2aSfgsch 	 the local symbol hash table.  */
23545f210c2aSfgsch       if (h && h->dynindx != -1)
23555f210c2aSfgsch 	dynindx = h->dynindx;
23565f210c2aSfgsch       else
23575f210c2aSfgsch 	dynindx
23585f210c2aSfgsch 	  = _bfd_elf_link_lookup_local_dynindx (info, dyn_h->owner,
23595f210c2aSfgsch 						dyn_h->sym_indx);
23605f210c2aSfgsch 
23615f210c2aSfgsch       for (rent = dyn_h->reloc_entries; rent; rent = rent->next)
23625f210c2aSfgsch 	{
2363d2201f2fSdrahn 	  Elf_Internal_Rela rel;
2364d2201f2fSdrahn 	  bfd_byte *loc;
23655f210c2aSfgsch 
2366d2201f2fSdrahn 	  /* Allocate one iff we are building a shared library, the relocation
2367d2201f2fSdrahn 	     isn't a R_PARISC_FPTR64, or we don't want an opd entry.  */
2368d2201f2fSdrahn 	  if (!info->shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
23695f210c2aSfgsch 	    continue;
23705f210c2aSfgsch 
23715f210c2aSfgsch 	  /* Create a dynamic relocation for this entry.
23725f210c2aSfgsch 
23735f210c2aSfgsch 	     We need the output offset for the reloc's section because
23745f210c2aSfgsch 	     we are creating an absolute address in the resulting object
23755f210c2aSfgsch 	     file.  */
23765f210c2aSfgsch 	  rel.r_offset = (rent->offset + rent->sec->output_offset
23775f210c2aSfgsch 			  + rent->sec->output_section->vma);
23785f210c2aSfgsch 
23795f210c2aSfgsch 	  /* An FPTR64 relocation implies that we took the address of
23805f210c2aSfgsch 	     a function and that the function has an entry in the .opd
23815f210c2aSfgsch 	     section.  We want the FPTR64 relocation to reference the
23825f210c2aSfgsch 	     entry in .opd.
23835f210c2aSfgsch 
23845f210c2aSfgsch 	     We could munge the symbol value in the dynamic symbol table
23855f210c2aSfgsch 	     (in fact we already do for functions with global scope) to point
23865f210c2aSfgsch 	     to the .opd entry.  Then we could use that dynamic symbol in
23875f210c2aSfgsch 	     this relocation.
23885f210c2aSfgsch 
23895f210c2aSfgsch 	     Or we could do something sensible, not munge the symbol's
23905f210c2aSfgsch 	     address and instead just use a different symbol to reference
23915f210c2aSfgsch 	     the .opd entry.  At least that seems sensible until you
23925f210c2aSfgsch 	     realize there's no local dynamic symbols we can use for that
23935f210c2aSfgsch 	     purpose.  Thus the hair in the check_relocs routine.
23945f210c2aSfgsch 
23955f210c2aSfgsch 	     We use a section symbol recorded by check_relocs as the
23965f210c2aSfgsch 	     base symbol for the relocation.  The addend is the difference
23975f210c2aSfgsch 	     between the section symbol and the address of the .opd entry.  */
2398d2201f2fSdrahn 	  if (info->shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
23995f210c2aSfgsch 	    {
24005f210c2aSfgsch 	      bfd_vma value, value2;
24015f210c2aSfgsch 
24025f210c2aSfgsch 	      /* First compute the address of the opd entry for this symbol.  */
24035f210c2aSfgsch 	      value = (dyn_h->opd_offset
24045f210c2aSfgsch 		       + hppa_info->opd_sec->output_section->vma
24055f210c2aSfgsch 		       + hppa_info->opd_sec->output_offset);
24065f210c2aSfgsch 
24075f210c2aSfgsch 	      /* Compute the value of the start of the section with
24085f210c2aSfgsch 		 the relocation.  */
24095f210c2aSfgsch 	      value2 = (rent->sec->output_section->vma
24105f210c2aSfgsch 			+ rent->sec->output_offset);
24115f210c2aSfgsch 
24125f210c2aSfgsch 	      /* Compute the difference between the start of the section
24135f210c2aSfgsch 		 with the relocation and the opd entry.  */
24145f210c2aSfgsch 	      value -= value2;
24155f210c2aSfgsch 
24165f210c2aSfgsch 	      /* The result becomes the addend of the relocation.  */
24175f210c2aSfgsch 	      rel.r_addend = value;
24185f210c2aSfgsch 
24195f210c2aSfgsch 	      /* The section symbol becomes the symbol for the dynamic
24205f210c2aSfgsch 		 relocation.  */
24215f210c2aSfgsch 	      dynindx
24225f210c2aSfgsch 		= _bfd_elf_link_lookup_local_dynindx (info,
24235f210c2aSfgsch 						      rent->sec->owner,
24245f210c2aSfgsch 						      rent->sec_symndx);
24255f210c2aSfgsch 	    }
24265f210c2aSfgsch 	  else
24275f210c2aSfgsch 	    rel.r_addend = rent->addend;
24285f210c2aSfgsch 
24295f210c2aSfgsch 	  rel.r_info = ELF64_R_INFO (dynindx, rent->type);
24305f210c2aSfgsch 
2431d2201f2fSdrahn 	  loc = hppa_info->other_rel_sec->contents;
2432d2201f2fSdrahn 	  loc += (hppa_info->other_rel_sec->reloc_count++
2433d2201f2fSdrahn 		  * sizeof (Elf64_External_Rela));
24345f210c2aSfgsch 	  bfd_elf64_swap_reloca_out (hppa_info->other_rel_sec->output_section->owner,
2435d2201f2fSdrahn 				     &rel, loc);
24365f210c2aSfgsch 	}
24375f210c2aSfgsch     }
24385f210c2aSfgsch 
2439d2201f2fSdrahn   return TRUE;
2440d2201f2fSdrahn }
2441d2201f2fSdrahn 
2442d2201f2fSdrahn /* Used to decide how to sort relocs in an optimal manner for the
2443d2201f2fSdrahn    dynamic linker, before writing them out.  */
2444d2201f2fSdrahn 
2445d2201f2fSdrahn static enum elf_reloc_type_class
elf64_hppa_reloc_type_class(rela)2446d2201f2fSdrahn elf64_hppa_reloc_type_class (rela)
2447d2201f2fSdrahn      const Elf_Internal_Rela *rela;
2448d2201f2fSdrahn {
2449d2201f2fSdrahn   if (ELF64_R_SYM (rela->r_info) == 0)
2450d2201f2fSdrahn     return reloc_class_relative;
2451d2201f2fSdrahn 
2452d2201f2fSdrahn   switch ((int) ELF64_R_TYPE (rela->r_info))
2453d2201f2fSdrahn     {
2454d2201f2fSdrahn     case R_PARISC_IPLT:
2455d2201f2fSdrahn       return reloc_class_plt;
2456d2201f2fSdrahn     case R_PARISC_COPY:
2457d2201f2fSdrahn       return reloc_class_copy;
2458d2201f2fSdrahn     default:
2459d2201f2fSdrahn       return reloc_class_normal;
2460d2201f2fSdrahn     }
24615f210c2aSfgsch }
24625f210c2aSfgsch 
24635f210c2aSfgsch /* Finish up the dynamic sections.  */
24645f210c2aSfgsch 
2465d2201f2fSdrahn static bfd_boolean
elf64_hppa_finish_dynamic_sections(output_bfd,info)24665f210c2aSfgsch elf64_hppa_finish_dynamic_sections (output_bfd, info)
24675f210c2aSfgsch      bfd *output_bfd;
24685f210c2aSfgsch      struct bfd_link_info *info;
24695f210c2aSfgsch {
24705f210c2aSfgsch   bfd *dynobj;
24715f210c2aSfgsch   asection *sdyn;
24725f210c2aSfgsch   struct elf64_hppa_link_hash_table *hppa_info;
24735f210c2aSfgsch 
24745f210c2aSfgsch   hppa_info = elf64_hppa_hash_table (info);
24755f210c2aSfgsch 
24765f210c2aSfgsch   /* Finalize the contents of the .opd section.  */
24775f210c2aSfgsch   elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
24785f210c2aSfgsch 				elf64_hppa_finalize_opd,
24795f210c2aSfgsch 				info);
24805f210c2aSfgsch 
24815f210c2aSfgsch   elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
24825f210c2aSfgsch 				elf64_hppa_finalize_dynreloc,
24835f210c2aSfgsch 				info);
24845f210c2aSfgsch 
24855f210c2aSfgsch   /* Finalize the contents of the .dlt section.  */
24865f210c2aSfgsch   dynobj = elf_hash_table (info)->dynobj;
24875f210c2aSfgsch   /* Finalize the contents of the .dlt section.  */
24885f210c2aSfgsch   elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
24895f210c2aSfgsch 				elf64_hppa_finalize_dlt,
24905f210c2aSfgsch 				info);
24915f210c2aSfgsch 
24925f210c2aSfgsch   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
24935f210c2aSfgsch 
24945f210c2aSfgsch   if (elf_hash_table (info)->dynamic_sections_created)
24955f210c2aSfgsch     {
24965f210c2aSfgsch       Elf64_External_Dyn *dyncon, *dynconend;
24975f210c2aSfgsch 
24985f210c2aSfgsch       BFD_ASSERT (sdyn != NULL);
24995f210c2aSfgsch 
25005f210c2aSfgsch       dyncon = (Elf64_External_Dyn *) sdyn->contents;
25015f210c2aSfgsch       dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
25025f210c2aSfgsch       for (; dyncon < dynconend; dyncon++)
25035f210c2aSfgsch 	{
25045f210c2aSfgsch 	  Elf_Internal_Dyn dyn;
25055f210c2aSfgsch 	  asection *s;
25065f210c2aSfgsch 
25075f210c2aSfgsch 	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
25085f210c2aSfgsch 
25095f210c2aSfgsch 	  switch (dyn.d_tag)
25105f210c2aSfgsch 	    {
25115f210c2aSfgsch 	    default:
25125f210c2aSfgsch 	      break;
25135f210c2aSfgsch 
25145f210c2aSfgsch 	    case DT_HP_LOAD_MAP:
25155f210c2aSfgsch 	      /* Compute the absolute address of 16byte scratchpad area
25165f210c2aSfgsch 		 for the dynamic linker.
25175f210c2aSfgsch 
25185f210c2aSfgsch 		 By convention the linker script will allocate the scratchpad
25195f210c2aSfgsch 		 area at the start of the .data section.  So all we have to
25205f210c2aSfgsch 		 to is find the start of the .data section.  */
25215f210c2aSfgsch 	      s = bfd_get_section_by_name (output_bfd, ".data");
25225f210c2aSfgsch 	      dyn.d_un.d_ptr = s->vma;
25235f210c2aSfgsch 	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
25245f210c2aSfgsch 	      break;
25255f210c2aSfgsch 
25265f210c2aSfgsch 	    case DT_PLTGOT:
25275f210c2aSfgsch 	      /* HP's use PLTGOT to set the GOT register.  */
25285f210c2aSfgsch 	      dyn.d_un.d_ptr = _bfd_get_gp_value (output_bfd);
25295f210c2aSfgsch 	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
25305f210c2aSfgsch 	      break;
25315f210c2aSfgsch 
25325f210c2aSfgsch 	    case DT_JMPREL:
25335f210c2aSfgsch 	      s = hppa_info->plt_rel_sec;
25345f210c2aSfgsch 	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
25355f210c2aSfgsch 	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
25365f210c2aSfgsch 	      break;
25375f210c2aSfgsch 
25385f210c2aSfgsch 	    case DT_PLTRELSZ:
25395f210c2aSfgsch 	      s = hppa_info->plt_rel_sec;
25405f210c2aSfgsch 	      dyn.d_un.d_val = s->_raw_size;
25415f210c2aSfgsch 	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
25425f210c2aSfgsch 	      break;
25435f210c2aSfgsch 
25445f210c2aSfgsch 	    case DT_RELA:
25455f210c2aSfgsch 	      s = hppa_info->other_rel_sec;
2546d2201f2fSdrahn 	      if (! s || ! s->_raw_size)
25475f210c2aSfgsch 		s = hppa_info->dlt_rel_sec;
2548d2201f2fSdrahn 	      if (! s || ! s->_raw_size)
2549d2201f2fSdrahn 		s = hppa_info->opd_rel_sec;
25505f210c2aSfgsch 	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
25515f210c2aSfgsch 	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
25525f210c2aSfgsch 	      break;
25535f210c2aSfgsch 
25545f210c2aSfgsch 	    case DT_RELASZ:
25555f210c2aSfgsch 	      s = hppa_info->other_rel_sec;
25565f210c2aSfgsch 	      dyn.d_un.d_val = s->_raw_size;
25575f210c2aSfgsch 	      s = hppa_info->dlt_rel_sec;
25585f210c2aSfgsch 	      dyn.d_un.d_val += s->_raw_size;
25595f210c2aSfgsch 	      s = hppa_info->opd_rel_sec;
25605f210c2aSfgsch 	      dyn.d_un.d_val += s->_raw_size;
25615f210c2aSfgsch 	      /* There is some question about whether or not the size of
25625f210c2aSfgsch 		 the PLT relocs should be included here.  HP's tools do
25635f210c2aSfgsch 		 it, so we'll emulate them.  */
25645f210c2aSfgsch 	      s = hppa_info->plt_rel_sec;
25655f210c2aSfgsch 	      dyn.d_un.d_val += s->_raw_size;
25665f210c2aSfgsch 	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
25675f210c2aSfgsch 	      break;
25685f210c2aSfgsch 
25695f210c2aSfgsch 	    }
25705f210c2aSfgsch 	}
25715f210c2aSfgsch     }
25725f210c2aSfgsch 
2573d2201f2fSdrahn   return TRUE;
25745f210c2aSfgsch }
25755f210c2aSfgsch 
25765f210c2aSfgsch /* Return the number of additional phdrs we will need.
25775f210c2aSfgsch 
25785f210c2aSfgsch    The generic ELF code only creates PT_PHDRs for executables.  The HP
25795f210c2aSfgsch    dynamic linker requires PT_PHDRs for dynamic libraries too.
25805f210c2aSfgsch 
25815f210c2aSfgsch    This routine indicates that the backend needs one additional program
25825f210c2aSfgsch    header for that case.
25835f210c2aSfgsch 
25845f210c2aSfgsch    Note we do not have access to the link info structure here, so we have
25855f210c2aSfgsch    to guess whether or not we are building a shared library based on the
25865f210c2aSfgsch    existence of a .interp section.  */
25875f210c2aSfgsch 
25885f210c2aSfgsch static int
elf64_hppa_additional_program_headers(abfd)25895f210c2aSfgsch elf64_hppa_additional_program_headers (abfd)
25905f210c2aSfgsch      bfd *abfd;
25915f210c2aSfgsch {
25925f210c2aSfgsch   asection *s;
25935f210c2aSfgsch 
25945f210c2aSfgsch   /* If we are creating a shared library, then we have to create a
25955f210c2aSfgsch      PT_PHDR segment.  HP's dynamic linker chokes without it.  */
25965f210c2aSfgsch   s = bfd_get_section_by_name (abfd, ".interp");
25975f210c2aSfgsch   if (! s)
25985f210c2aSfgsch     return 1;
25995f210c2aSfgsch   return 0;
26005f210c2aSfgsch }
26015f210c2aSfgsch 
26025f210c2aSfgsch /* Allocate and initialize any program headers required by this
26035f210c2aSfgsch    specific backend.
26045f210c2aSfgsch 
26055f210c2aSfgsch    The generic ELF code only creates PT_PHDRs for executables.  The HP
26065f210c2aSfgsch    dynamic linker requires PT_PHDRs for dynamic libraries too.
26075f210c2aSfgsch 
26085f210c2aSfgsch    This allocates the PT_PHDR and initializes it in a manner suitable
26095f210c2aSfgsch    for the HP linker.
26105f210c2aSfgsch 
26115f210c2aSfgsch    Note we do not have access to the link info structure here, so we have
26125f210c2aSfgsch    to guess whether or not we are building a shared library based on the
26135f210c2aSfgsch    existence of a .interp section.  */
26145f210c2aSfgsch 
2615d2201f2fSdrahn static bfd_boolean
elf64_hppa_modify_segment_map(abfd,info)2616cf2f2c56Smiod elf64_hppa_modify_segment_map (abfd, info)
26175f210c2aSfgsch      bfd *abfd;
2618cf2f2c56Smiod      struct bfd_link_info *info ATTRIBUTE_UNUSED;
26195f210c2aSfgsch {
26205f210c2aSfgsch   struct elf_segment_map *m;
26215f210c2aSfgsch   asection *s;
26225f210c2aSfgsch 
26235f210c2aSfgsch   s = bfd_get_section_by_name (abfd, ".interp");
26245f210c2aSfgsch   if (! s)
26255f210c2aSfgsch     {
26265f210c2aSfgsch       for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
26275f210c2aSfgsch 	if (m->p_type == PT_PHDR)
26285f210c2aSfgsch 	  break;
26295f210c2aSfgsch       if (m == NULL)
26305f210c2aSfgsch 	{
2631d2201f2fSdrahn 	  m = ((struct elf_segment_map *)
2632d2201f2fSdrahn 	       bfd_zalloc (abfd, (bfd_size_type) sizeof *m));
26335f210c2aSfgsch 	  if (m == NULL)
2634d2201f2fSdrahn 	    return FALSE;
26355f210c2aSfgsch 
26365f210c2aSfgsch 	  m->p_type = PT_PHDR;
26375f210c2aSfgsch 	  m->p_flags = PF_R | PF_X;
26385f210c2aSfgsch 	  m->p_flags_valid = 1;
26395f210c2aSfgsch 	  m->p_paddr_valid = 1;
26405f210c2aSfgsch 	  m->includes_phdrs = 1;
26415f210c2aSfgsch 
26425f210c2aSfgsch 	  m->next = elf_tdata (abfd)->segment_map;
26435f210c2aSfgsch 	  elf_tdata (abfd)->segment_map = m;
26445f210c2aSfgsch 	}
26455f210c2aSfgsch     }
26465f210c2aSfgsch 
26475f210c2aSfgsch   for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
26485f210c2aSfgsch     if (m->p_type == PT_LOAD)
26495f210c2aSfgsch       {
26505f210c2aSfgsch 	unsigned int i;
26515f210c2aSfgsch 
26525f210c2aSfgsch 	for (i = 0; i < m->count; i++)
26535f210c2aSfgsch 	  {
26545f210c2aSfgsch 	    /* The code "hint" is not really a hint.  It is a requirement
26555f210c2aSfgsch 	       for certain versions of the HP dynamic linker.  Worse yet,
26565f210c2aSfgsch 	       it must be set even if the shared library does not have
26575f210c2aSfgsch 	       any code in its "text" segment (thus the check for .hash
26585f210c2aSfgsch 	       to catch this situation).  */
26595f210c2aSfgsch 	    if (m->sections[i]->flags & SEC_CODE
26605f210c2aSfgsch 		|| (strcmp (m->sections[i]->name, ".hash") == 0))
26615f210c2aSfgsch 	      m->p_flags |= (PF_X | PF_HP_CODE);
26625f210c2aSfgsch 	  }
26635f210c2aSfgsch       }
26645f210c2aSfgsch 
2665d2201f2fSdrahn   return TRUE;
26665f210c2aSfgsch }
26675f210c2aSfgsch 
26685f210c2aSfgsch /* Called when writing out an object file to decide the type of a
26695f210c2aSfgsch    symbol.  */
26705f210c2aSfgsch static int
elf64_hppa_elf_get_symbol_type(elf_sym,type)26715f210c2aSfgsch elf64_hppa_elf_get_symbol_type (elf_sym, type)
26725f210c2aSfgsch      Elf_Internal_Sym *elf_sym;
26735f210c2aSfgsch      int type;
26745f210c2aSfgsch {
26755f210c2aSfgsch   if (ELF_ST_TYPE (elf_sym->st_info) == STT_PARISC_MILLI)
26765f210c2aSfgsch     return STT_PARISC_MILLI;
26775f210c2aSfgsch   else
26785f210c2aSfgsch     return type;
26795f210c2aSfgsch }
26805f210c2aSfgsch 
2681cf2f2c56Smiod static struct bfd_elf_special_section const elf64_hppa_special_sections[]=
2682cf2f2c56Smiod {
2683cf2f2c56Smiod   { ".fini",    5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
2684cf2f2c56Smiod   { ".init",    5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
2685cf2f2c56Smiod   { NULL,       0, 0, 0,            0 }
2686cf2f2c56Smiod };
2687cf2f2c56Smiod 
26885f210c2aSfgsch /* The hash bucket size is the standard one, namely 4.  */
26895f210c2aSfgsch 
26905f210c2aSfgsch const struct elf_size_info hppa64_elf_size_info =
26915f210c2aSfgsch {
26925f210c2aSfgsch   sizeof (Elf64_External_Ehdr),
26935f210c2aSfgsch   sizeof (Elf64_External_Phdr),
26945f210c2aSfgsch   sizeof (Elf64_External_Shdr),
26955f210c2aSfgsch   sizeof (Elf64_External_Rel),
26965f210c2aSfgsch   sizeof (Elf64_External_Rela),
26975f210c2aSfgsch   sizeof (Elf64_External_Sym),
26985f210c2aSfgsch   sizeof (Elf64_External_Dyn),
26995f210c2aSfgsch   sizeof (Elf_External_Note),
27005f210c2aSfgsch   4,
27015f210c2aSfgsch   1,
2702cf2f2c56Smiod   64, 3,
27035f210c2aSfgsch   ELFCLASS64, EV_CURRENT,
27045f210c2aSfgsch   bfd_elf64_write_out_phdrs,
27055f210c2aSfgsch   bfd_elf64_write_shdrs_and_ehdr,
27065f210c2aSfgsch   bfd_elf64_write_relocs,
2707d2201f2fSdrahn   bfd_elf64_swap_symbol_in,
27085f210c2aSfgsch   bfd_elf64_swap_symbol_out,
27095f210c2aSfgsch   bfd_elf64_slurp_reloc_table,
27105f210c2aSfgsch   bfd_elf64_slurp_symbol_table,
27115f210c2aSfgsch   bfd_elf64_swap_dyn_in,
27125f210c2aSfgsch   bfd_elf64_swap_dyn_out,
2713d2201f2fSdrahn   bfd_elf64_swap_reloc_in,
2714d2201f2fSdrahn   bfd_elf64_swap_reloc_out,
2715d2201f2fSdrahn   bfd_elf64_swap_reloca_in,
2716d2201f2fSdrahn   bfd_elf64_swap_reloca_out
27175f210c2aSfgsch };
27185f210c2aSfgsch 
27195f210c2aSfgsch #define TARGET_BIG_SYM			bfd_elf64_hppa_vec
27205f210c2aSfgsch #define TARGET_BIG_NAME			"elf64-hppa"
27215f210c2aSfgsch #define ELF_ARCH			bfd_arch_hppa
27225f210c2aSfgsch #define ELF_MACHINE_CODE		EM_PARISC
27235f210c2aSfgsch /* This is not strictly correct.  The maximum page size for PA2.0 is
27245f210c2aSfgsch    64M.  But everything still uses 4k.  */
27255f210c2aSfgsch #define ELF_MAXPAGESIZE			0x1000
27265f210c2aSfgsch #define bfd_elf64_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup
27275f210c2aSfgsch #define bfd_elf64_bfd_is_local_label_name       elf_hppa_is_local_label_name
27285f210c2aSfgsch #define elf_info_to_howto		elf_hppa_info_to_howto
27295f210c2aSfgsch #define elf_info_to_howto_rel		elf_hppa_info_to_howto_rel
27305f210c2aSfgsch 
27315f210c2aSfgsch #define elf_backend_section_from_shdr	elf64_hppa_section_from_shdr
27325f210c2aSfgsch #define elf_backend_object_p		elf64_hppa_object_p
27335f210c2aSfgsch #define elf_backend_final_write_processing \
27345f210c2aSfgsch 					elf_hppa_final_write_processing
27355f210c2aSfgsch #define elf_backend_fake_sections	elf_hppa_fake_sections
27365f210c2aSfgsch #define elf_backend_add_symbol_hook	elf_hppa_add_symbol_hook
27375f210c2aSfgsch 
27385f210c2aSfgsch #define elf_backend_relocate_section	elf_hppa_relocate_section
27395f210c2aSfgsch 
27405f210c2aSfgsch #define bfd_elf64_bfd_final_link	elf_hppa_final_link
27415f210c2aSfgsch 
27425f210c2aSfgsch #define elf_backend_create_dynamic_sections \
27435f210c2aSfgsch 					elf64_hppa_create_dynamic_sections
27445f210c2aSfgsch #define elf_backend_post_process_headers	elf64_hppa_post_process_headers
27455f210c2aSfgsch 
27465f210c2aSfgsch #define elf_backend_adjust_dynamic_symbol \
27475f210c2aSfgsch 					elf64_hppa_adjust_dynamic_symbol
27485f210c2aSfgsch 
27495f210c2aSfgsch #define elf_backend_size_dynamic_sections \
27505f210c2aSfgsch 					elf64_hppa_size_dynamic_sections
27515f210c2aSfgsch 
27525f210c2aSfgsch #define elf_backend_finish_dynamic_symbol \
27535f210c2aSfgsch 					elf64_hppa_finish_dynamic_symbol
27545f210c2aSfgsch #define elf_backend_finish_dynamic_sections \
27555f210c2aSfgsch 					elf64_hppa_finish_dynamic_sections
27565f210c2aSfgsch 
27575f210c2aSfgsch /* Stuff for the BFD linker: */
27585f210c2aSfgsch #define bfd_elf64_bfd_link_hash_table_create \
27595f210c2aSfgsch 	elf64_hppa_hash_table_create
27605f210c2aSfgsch 
27615f210c2aSfgsch #define elf_backend_check_relocs \
27625f210c2aSfgsch 	elf64_hppa_check_relocs
27635f210c2aSfgsch 
27645f210c2aSfgsch #define elf_backend_size_info \
27655f210c2aSfgsch   hppa64_elf_size_info
27665f210c2aSfgsch 
27675f210c2aSfgsch #define elf_backend_additional_program_headers \
27685f210c2aSfgsch 	elf64_hppa_additional_program_headers
27695f210c2aSfgsch 
27705f210c2aSfgsch #define elf_backend_modify_segment_map \
27715f210c2aSfgsch 	elf64_hppa_modify_segment_map
27725f210c2aSfgsch 
27735f210c2aSfgsch #define elf_backend_link_output_symbol_hook \
27745f210c2aSfgsch 	elf64_hppa_link_output_symbol_hook
27755f210c2aSfgsch 
27765f210c2aSfgsch #define elf_backend_want_got_plt	0
27775f210c2aSfgsch #define elf_backend_plt_readonly	0
27785f210c2aSfgsch #define elf_backend_want_plt_sym	0
27795f210c2aSfgsch #define elf_backend_got_header_size     0
2780d2201f2fSdrahn #define elf_backend_type_change_ok	TRUE
27815f210c2aSfgsch #define elf_backend_get_symbol_type	elf64_hppa_elf_get_symbol_type
2782d2201f2fSdrahn #define elf_backend_reloc_type_class	elf64_hppa_reloc_type_class
2783d2201f2fSdrahn #define elf_backend_rela_normal		1
2784cf2f2c56Smiod #define elf_backend_special_sections	elf64_hppa_special_sections
27855f210c2aSfgsch 
27865f210c2aSfgsch #include "elf64-target.h"
27875f210c2aSfgsch 
27885f210c2aSfgsch #undef TARGET_BIG_SYM
27895f210c2aSfgsch #define TARGET_BIG_SYM			bfd_elf64_hppa_linux_vec
27905f210c2aSfgsch #undef TARGET_BIG_NAME
27915f210c2aSfgsch #define TARGET_BIG_NAME			"elf64-hppa-linux"
27925f210c2aSfgsch 
2793cf2f2c56Smiod #undef elf_backend_special_sections
2794cf2f2c56Smiod 
27955f210c2aSfgsch #define INCLUDED_TARGET_FILE 1
27965f210c2aSfgsch #include "elf64-target.h"
2797