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