1 |
/* SPARC-specific support for 64-bit ELF |
/* SPARC-specific support for 64-bit ELF |
2 |
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 |
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
3 |
Free Software Foundation, Inc. |
2003, 2004, 2005 Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
7 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
(at your option) any later version. |
11 |
|
|
12 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
GNU General Public License for more details. |
16 |
|
|
17 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 |
|
|
21 |
#include "bfd.h" |
#include "bfd.h" |
22 |
#include "sysdep.h" |
#include "sysdep.h" |
36 |
|
|
37 |
static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create |
static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create |
38 |
PARAMS ((bfd *)); |
PARAMS ((bfd *)); |
39 |
|
static bfd_boolean create_got_section |
40 |
|
PARAMS ((bfd *, struct bfd_link_info *)); |
41 |
|
static bfd_boolean sparc64_elf_create_dynamic_sections |
42 |
|
PARAMS ((bfd *, struct bfd_link_info *)); |
43 |
static bfd_reloc_status_type init_insn_reloc |
static bfd_reloc_status_type init_insn_reloc |
44 |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, |
45 |
bfd *, bfd_vma *, bfd_vma *)); |
bfd *, bfd_vma *, bfd_vma *)); |
55 |
static bfd_vma sparc64_elf_plt_ptr_offset |
static bfd_vma sparc64_elf_plt_ptr_offset |
56 |
PARAMS ((bfd_vma, bfd_vma)); |
PARAMS ((bfd_vma, bfd_vma)); |
57 |
|
|
58 |
static boolean sparc64_elf_check_relocs |
static bfd_boolean sparc64_elf_check_relocs |
59 |
PARAMS ((bfd *, struct bfd_link_info *, asection *sec, |
PARAMS ((bfd *, struct bfd_link_info *, asection *sec, |
60 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
61 |
static boolean sparc64_elf_adjust_dynamic_symbol |
static bfd_boolean sparc64_elf_adjust_dynamic_symbol |
62 |
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); |
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); |
63 |
static boolean sparc64_elf_size_dynamic_sections |
static bfd_boolean sparc64_elf_omit_section_dynsym |
64 |
|
PARAMS ((bfd *, struct bfd_link_info *, asection *)); |
65 |
|
static bfd_boolean sparc64_elf_size_dynamic_sections |
66 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
67 |
static int sparc64_elf_get_symbol_type |
static int sparc64_elf_get_symbol_type |
68 |
PARAMS (( Elf_Internal_Sym *, int)); |
PARAMS (( Elf_Internal_Sym *, int)); |
69 |
static boolean sparc64_elf_add_symbol_hook |
static bfd_boolean sparc64_elf_add_symbol_hook |
70 |
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, |
PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *, |
71 |
const char **, flagword *, asection **, bfd_vma *)); |
const char **, flagword *, asection **, bfd_vma *)); |
72 |
static boolean sparc64_elf_output_arch_syms |
static bfd_boolean sparc64_elf_output_arch_syms |
73 |
PARAMS ((bfd *, struct bfd_link_info *, PTR, |
PARAMS ((bfd *, struct bfd_link_info *, PTR, |
74 |
boolean (*) (PTR, const char *, Elf_Internal_Sym *, asection *))); |
bfd_boolean (*) (PTR, const char *, Elf_Internal_Sym *, |
75 |
|
asection *, struct elf_link_hash_entry *))); |
76 |
static void sparc64_elf_symbol_processing |
static void sparc64_elf_symbol_processing |
77 |
PARAMS ((bfd *, asymbol *)); |
PARAMS ((bfd *, asymbol *)); |
78 |
|
|
79 |
static boolean sparc64_elf_merge_private_bfd_data |
static bfd_boolean sparc64_elf_merge_private_bfd_data |
80 |
PARAMS ((bfd *, bfd *)); |
PARAMS ((bfd *, bfd *)); |
81 |
|
|
82 |
static boolean sparc64_elf_fake_sections |
static bfd_boolean sparc64_elf_fake_sections |
83 |
PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); |
PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); |
84 |
|
|
85 |
static const char *sparc64_elf_print_symbol_all |
static const char *sparc64_elf_print_symbol_all |
86 |
PARAMS ((bfd *, PTR, asymbol *)); |
PARAMS ((bfd *, PTR, asymbol *)); |
87 |
static boolean sparc64_elf_relax_section |
static bfd_boolean sparc64_elf_new_section_hook |
88 |
PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); |
PARAMS ((bfd *, asection *)); |
89 |
static boolean sparc64_elf_relocate_section |
static bfd_boolean sparc64_elf_relax_section |
90 |
|
PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *)); |
91 |
|
static bfd_boolean sparc64_elf_relocate_section |
92 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
93 |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
94 |
static boolean sparc64_elf_finish_dynamic_symbol |
static bfd_boolean sparc64_elf_finish_dynamic_symbol |
95 |
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, |
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, |
96 |
Elf_Internal_Sym *)); |
Elf_Internal_Sym *)); |
97 |
static boolean sparc64_elf_finish_dynamic_sections |
static bfd_boolean sparc64_elf_finish_dynamic_sections |
98 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
99 |
static boolean sparc64_elf_object_p PARAMS ((bfd *)); |
static bfd_boolean sparc64_elf_object_p PARAMS ((bfd *)); |
100 |
static long sparc64_elf_get_reloc_upper_bound PARAMS ((bfd *, asection *)); |
static long sparc64_elf_get_reloc_upper_bound PARAMS ((bfd *, asection *)); |
101 |
static long sparc64_elf_get_dynamic_reloc_upper_bound PARAMS ((bfd *)); |
static long sparc64_elf_get_dynamic_reloc_upper_bound PARAMS ((bfd *)); |
102 |
static boolean sparc64_elf_slurp_one_reloc_table |
static bfd_boolean sparc64_elf_slurp_one_reloc_table |
103 |
PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, asymbol **, boolean)); |
PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, asymbol **, bfd_boolean)); |
104 |
static boolean sparc64_elf_slurp_reloc_table |
static bfd_boolean sparc64_elf_slurp_reloc_table |
105 |
PARAMS ((bfd *, asection *, asymbol **, boolean)); |
PARAMS ((bfd *, asection *, asymbol **, bfd_boolean)); |
106 |
|
static long sparc64_elf_canonicalize_reloc |
107 |
|
PARAMS ((bfd *, asection *, arelent **, asymbol **)); |
108 |
static long sparc64_elf_canonicalize_dynamic_reloc |
static long sparc64_elf_canonicalize_dynamic_reloc |
109 |
PARAMS ((bfd *, arelent **, asymbol **)); |
PARAMS ((bfd *, arelent **, asymbol **)); |
110 |
static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR)); |
static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR)); |
124 |
|
|
125 |
static reloc_howto_type sparc64_elf_howto_table[] = |
static reloc_howto_type sparc64_elf_howto_table[] = |
126 |
{ |
{ |
127 |
HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), |
HOWTO(R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", FALSE,0,0x00000000,TRUE), |
128 |
HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", false,0,0x000000ff,true), |
HOWTO(R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", FALSE,0,0x000000ff,TRUE), |
129 |
HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", false,0,0x0000ffff,true), |
HOWTO(R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", FALSE,0,0x0000ffff,TRUE), |
130 |
HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true), |
HOWTO(R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", FALSE,0,0xffffffff,TRUE), |
131 |
HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true), |
HOWTO(R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE), |
132 |
HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true), |
HOWTO(R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE), |
133 |
HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0xffffffff,true), |
HOWTO(R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", FALSE,0,0xffffffff,TRUE), |
134 |
HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true), |
HOWTO(R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE), |
135 |
HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE), |
136 |
HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", FALSE,0,0x003fffff,TRUE), |
137 |
HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", FALSE,0,0x003fffff,TRUE), |
138 |
HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", false,0,0x00001fff,true), |
HOWTO(R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", FALSE,0,0x00001fff,TRUE), |
139 |
HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false,0,0x000003ff,true), |
HOWTO(R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", FALSE,0,0x000003ff,TRUE), |
140 |
HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", false,0,0x000003ff,true), |
HOWTO(R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE), |
141 |
HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", false,0,0x00001fff,true), |
HOWTO(R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE), |
142 |
HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE), |
143 |
HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", false,0,0x000003ff,true), |
HOWTO(R_SPARC_PC10, 0,2,10,TRUE, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", FALSE,0,0x000003ff,TRUE), |
144 |
HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_PC22, 10,2,22,TRUE, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", FALSE,0,0x003fffff,TRUE), |
145 |
HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false,0,0x3fffffff,true), |
HOWTO(R_SPARC_WPLT30, 2,2,30,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", FALSE,0,0x3fffffff,TRUE), |
146 |
HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false,0,0x00000000,true), |
HOWTO(R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", FALSE,0,0x00000000,TRUE), |
147 |
HOWTO(R_SPARC_GLOB_DAT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true), |
HOWTO(R_SPARC_GLOB_DAT, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE), |
148 |
HOWTO(R_SPARC_JMP_SLOT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",false,0,0x00000000,true), |
HOWTO(R_SPARC_JMP_SLOT, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE), |
149 |
HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true), |
HOWTO(R_SPARC_RELATIVE, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE), |
150 |
HOWTO(R_SPARC_UA32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0xffffffff,true), |
HOWTO(R_SPARC_UA32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA32", FALSE,0,0xffffffff,TRUE), |
151 |
#ifndef SPARC64_OLD_RELOCS |
#ifndef SPARC64_OLD_RELOCS |
152 |
HOWTO(R_SPARC_PLT32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT32", false,0,0xffffffff,true), |
HOWTO(R_SPARC_PLT32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT32", FALSE,0,0xffffffff,TRUE), |
153 |
/* These aren't implemented yet. */ |
/* These aren't implemented yet. */ |
154 |
HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true), |
HOWTO(R_SPARC_HIPLT22, 0,0,00,FALSE,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_HIPLT22", FALSE,0,0x00000000,TRUE), |
155 |
HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true), |
HOWTO(R_SPARC_LOPLT10, 0,0,00,FALSE,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_LOPLT10", FALSE,0,0x00000000,TRUE), |
156 |
HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true), |
HOWTO(R_SPARC_PCPLT32, 0,0,00,FALSE,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT32", FALSE,0,0x00000000,TRUE), |
157 |
HOWTO(R_SPARC_PCPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT22", false,0,0x00000000,true), |
HOWTO(R_SPARC_PCPLT22, 0,0,00,FALSE,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT22", FALSE,0,0x00000000,TRUE), |
158 |
HOWTO(R_SPARC_PCPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT10", false,0,0x00000000,true), |
HOWTO(R_SPARC_PCPLT10, 0,0,00,FALSE,0,complain_overflow_dont, sparc_elf_notsup_reloc, "R_SPARC_PCPLT10", FALSE,0,0x00000000,TRUE), |
159 |
#endif |
#endif |
160 |
HOWTO(R_SPARC_10, 0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", false,0,0x000003ff,true), |
HOWTO(R_SPARC_10, 0,2,10,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", FALSE,0,0x000003ff,TRUE), |
161 |
HOWTO(R_SPARC_11, 0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", false,0,0x000007ff,true), |
HOWTO(R_SPARC_11, 0,2,11,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", FALSE,0,0x000007ff,TRUE), |
162 |
HOWTO(R_SPARC_64, 0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_64", false,0,MINUS_ONE, true), |
HOWTO(R_SPARC_64, 0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_64", FALSE,0,MINUS_ONE, TRUE), |
163 |
HOWTO(R_SPARC_OLO10, 0,2,13,false,0,complain_overflow_signed, sparc_elf_notsup_reloc, "R_SPARC_OLO10", false,0,0x00001fff,true), |
HOWTO(R_SPARC_OLO10, 0,2,13,FALSE,0,complain_overflow_signed, sparc_elf_notsup_reloc, "R_SPARC_OLO10", FALSE,0,0x00001fff,TRUE), |
164 |
HOWTO(R_SPARC_HH22, 42,2,22,false,0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_HH22, 42,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_HH22", FALSE,0,0x003fffff,TRUE), |
165 |
HOWTO(R_SPARC_HM10, 32,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true), |
HOWTO(R_SPARC_HM10, 32,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", FALSE,0,0x000003ff,TRUE), |
166 |
HOWTO(R_SPARC_LM22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_LM22, 10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", FALSE,0,0x003fffff,TRUE), |
167 |
HOWTO(R_SPARC_PC_HH22, 42,2,22,true, 0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_PC_HH22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_PC_HH22, 42,2,22,TRUE, 0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_PC_HH22", FALSE,0,0x003fffff,TRUE), |
168 |
HOWTO(R_SPARC_PC_HM10, 32,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC_HM10", false,0,0x000003ff,true), |
HOWTO(R_SPARC_PC_HM10, 32,2,10,TRUE, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC_HM10", FALSE,0,0x000003ff,TRUE), |
169 |
HOWTO(R_SPARC_PC_LM22, 10,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC_LM22", false,0,0x003fffff,true), |
HOWTO(R_SPARC_PC_LM22, 10,2,22,TRUE, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC_LM22", FALSE,0,0x003fffff,TRUE), |
170 |
HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true), |
HOWTO(R_SPARC_WDISP16, 2,2,16,TRUE, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", FALSE,0,0x00000000,TRUE), |
171 |
HOWTO(R_SPARC_WDISP19, 2,2,19,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true), |
HOWTO(R_SPARC_WDISP19, 2,2,19,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", FALSE,0,0x0007ffff,TRUE), |
172 |
HOWTO(R_SPARC_UNUSED_42, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UNUSED_42",false,0,0x00000000,true), |
HOWTO(R_SPARC_UNUSED_42, 0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UNUSED_42",FALSE,0,0x00000000,TRUE), |
173 |
HOWTO(R_SPARC_7, 0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", false,0,0x0000007f,true), |
HOWTO(R_SPARC_7, 0,2, 7,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", FALSE,0,0x0000007f,TRUE), |
174 |
HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true), |
HOWTO(R_SPARC_5, 0,2, 5,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", FALSE,0,0x0000001f,TRUE), |
175 |
HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true), |
HOWTO(R_SPARC_6, 0,2, 6,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", FALSE,0,0x0000003f,TRUE), |
176 |
HOWTO(R_SPARC_DISP64, 0,4,64,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP64", false,0,MINUS_ONE, true), |
HOWTO(R_SPARC_DISP64, 0,4,64,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP64", FALSE,0,MINUS_ONE, TRUE), |
177 |
HOWTO(R_SPARC_PLT64, 0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT64", false,0,MINUS_ONE, true), |
HOWTO(R_SPARC_PLT64, 0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PLT64", FALSE,0,MINUS_ONE, TRUE), |
178 |
HOWTO(R_SPARC_HIX22, 0,4, 0,false,0,complain_overflow_bitfield,sparc_elf_hix22_reloc, "R_SPARC_HIX22", false,0,MINUS_ONE, false), |
HOWTO(R_SPARC_HIX22, 0,4, 0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc, "R_SPARC_HIX22", FALSE,0,MINUS_ONE, FALSE), |
179 |
HOWTO(R_SPARC_LOX10, 0,4, 0,false,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_LOX10", false,0,MINUS_ONE, false), |
HOWTO(R_SPARC_LOX10, 0,4, 0,FALSE,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_LOX10", FALSE,0,MINUS_ONE, FALSE), |
180 |
HOWTO(R_SPARC_H44, 22,2,22,false,0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_H44", false,0,0x003fffff,false), |
HOWTO(R_SPARC_H44, 22,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc, "R_SPARC_H44", FALSE,0,0x003fffff,FALSE), |
181 |
HOWTO(R_SPARC_M44, 12,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_M44", false,0,0x000003ff,false), |
HOWTO(R_SPARC_M44, 12,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_M44", FALSE,0,0x000003ff,FALSE), |
182 |
HOWTO(R_SPARC_L44, 0,2,13,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_L44", false,0,0x00000fff,false), |
HOWTO(R_SPARC_L44, 0,2,13,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_L44", FALSE,0,0x00000fff,FALSE), |
183 |
HOWTO(R_SPARC_REGISTER, 0,4, 0,false,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_REGISTER",false,0,MINUS_ONE, false), |
HOWTO(R_SPARC_REGISTER, 0,4, 0,FALSE,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_REGISTER",FALSE,0,MINUS_ONE, FALSE), |
184 |
HOWTO(R_SPARC_UA64, 0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA64", false,0,MINUS_ONE, true), |
HOWTO(R_SPARC_UA64, 0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA64", FALSE,0,MINUS_ONE, TRUE), |
185 |
HOWTO(R_SPARC_UA16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA16", false,0,0x0000ffff,true) |
HOWTO(R_SPARC_UA16, 0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_UA16", FALSE,0,0x0000ffff,TRUE), |
186 |
|
HOWTO(R_SPARC_TLS_GD_HI22,10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_GD_HI22",FALSE,0,0x003fffff,TRUE), |
187 |
|
HOWTO(R_SPARC_TLS_GD_LO10,0,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_GD_LO10",FALSE,0,0x000003ff,TRUE), |
188 |
|
HOWTO(R_SPARC_TLS_GD_ADD,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_GD_ADD",FALSE,0,0x00000000,TRUE), |
189 |
|
HOWTO(R_SPARC_TLS_GD_CALL,2,2,30,TRUE,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_TLS_GD_CALL",FALSE,0,0x3fffffff,TRUE), |
190 |
|
HOWTO(R_SPARC_TLS_LDM_HI22,10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_LDM_HI22",FALSE,0,0x003fffff,TRUE), |
191 |
|
HOWTO(R_SPARC_TLS_LDM_LO10,0,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_LDM_LO10",FALSE,0,0x000003ff,TRUE), |
192 |
|
HOWTO(R_SPARC_TLS_LDM_ADD,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_LDM_ADD",FALSE,0,0x00000000,TRUE), |
193 |
|
HOWTO(R_SPARC_TLS_LDM_CALL,2,2,30,TRUE,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_TLS_LDM_CALL",FALSE,0,0x3fffffff,TRUE), |
194 |
|
HOWTO(R_SPARC_TLS_LDO_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_TLS_LDO_HIX22",FALSE,0,0x003fffff, FALSE), |
195 |
|
HOWTO(R_SPARC_TLS_LDO_LOX10,0,2,0,FALSE,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_TLS_LDO_LOX10",FALSE,0,0x000003ff, FALSE), |
196 |
|
HOWTO(R_SPARC_TLS_LDO_ADD,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_LDO_ADD",FALSE,0,0x00000000,TRUE), |
197 |
|
HOWTO(R_SPARC_TLS_IE_HI22,10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_IE_HI22",FALSE,0,0x003fffff,TRUE), |
198 |
|
HOWTO(R_SPARC_TLS_IE_LO10,0,2,10,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_IE_LO10",FALSE,0,0x000003ff,TRUE), |
199 |
|
HOWTO(R_SPARC_TLS_IE_LD,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_IE_LD",FALSE,0,0x00000000,TRUE), |
200 |
|
HOWTO(R_SPARC_TLS_IE_LDX,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_IE_LDX",FALSE,0,0x00000000,TRUE), |
201 |
|
HOWTO(R_SPARC_TLS_IE_ADD,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_IE_ADD",FALSE,0,0x00000000,TRUE), |
202 |
|
HOWTO(R_SPARC_TLS_LE_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc, "R_SPARC_TLS_LE_HIX22",FALSE,0,0x003fffff, FALSE), |
203 |
|
HOWTO(R_SPARC_TLS_LE_LOX10,0,2,0,FALSE,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_TLS_LE_LOX10",FALSE,0,0x000003ff, FALSE), |
204 |
|
HOWTO(R_SPARC_TLS_DTPMOD32,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_DTPMOD32",FALSE,0,0x00000000,TRUE), |
205 |
|
HOWTO(R_SPARC_TLS_DTPMOD64,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_DTPMOD64",FALSE,0,0x00000000,TRUE), |
206 |
|
HOWTO(R_SPARC_TLS_DTPOFF32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF32",FALSE,0,0xffffffff,TRUE), |
207 |
|
HOWTO(R_SPARC_TLS_DTPOFF64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF64",FALSE,0,MINUS_ONE,TRUE), |
208 |
|
HOWTO(R_SPARC_TLS_TPOFF32,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_TPOFF32",FALSE,0,0x00000000,TRUE), |
209 |
|
HOWTO(R_SPARC_TLS_TPOFF64,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_TLS_TPOFF64",FALSE,0,0x00000000,TRUE) |
210 |
}; |
}; |
211 |
|
|
212 |
struct elf_reloc_map { |
struct elf_reloc_map { |
260 |
{ BFD_RELOC_SPARC_5, R_SPARC_5 }, |
{ BFD_RELOC_SPARC_5, R_SPARC_5 }, |
261 |
{ BFD_RELOC_SPARC_6, R_SPARC_6 }, |
{ BFD_RELOC_SPARC_6, R_SPARC_6 }, |
262 |
{ BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 }, |
{ BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 }, |
263 |
|
{ BFD_RELOC_SPARC_TLS_GD_HI22, R_SPARC_TLS_GD_HI22 }, |
264 |
|
{ BFD_RELOC_SPARC_TLS_GD_LO10, R_SPARC_TLS_GD_LO10 }, |
265 |
|
{ BFD_RELOC_SPARC_TLS_GD_ADD, R_SPARC_TLS_GD_ADD }, |
266 |
|
{ BFD_RELOC_SPARC_TLS_GD_CALL, R_SPARC_TLS_GD_CALL }, |
267 |
|
{ BFD_RELOC_SPARC_TLS_LDM_HI22, R_SPARC_TLS_LDM_HI22 }, |
268 |
|
{ BFD_RELOC_SPARC_TLS_LDM_LO10, R_SPARC_TLS_LDM_LO10 }, |
269 |
|
{ BFD_RELOC_SPARC_TLS_LDM_ADD, R_SPARC_TLS_LDM_ADD }, |
270 |
|
{ BFD_RELOC_SPARC_TLS_LDM_CALL, R_SPARC_TLS_LDM_CALL }, |
271 |
|
{ BFD_RELOC_SPARC_TLS_LDO_HIX22, R_SPARC_TLS_LDO_HIX22 }, |
272 |
|
{ BFD_RELOC_SPARC_TLS_LDO_LOX10, R_SPARC_TLS_LDO_LOX10 }, |
273 |
|
{ BFD_RELOC_SPARC_TLS_LDO_ADD, R_SPARC_TLS_LDO_ADD }, |
274 |
|
{ BFD_RELOC_SPARC_TLS_IE_HI22, R_SPARC_TLS_IE_HI22 }, |
275 |
|
{ BFD_RELOC_SPARC_TLS_IE_LO10, R_SPARC_TLS_IE_LO10 }, |
276 |
|
{ BFD_RELOC_SPARC_TLS_IE_LD, R_SPARC_TLS_IE_LD }, |
277 |
|
{ BFD_RELOC_SPARC_TLS_IE_LDX, R_SPARC_TLS_IE_LDX }, |
278 |
|
{ BFD_RELOC_SPARC_TLS_IE_ADD, R_SPARC_TLS_IE_ADD }, |
279 |
|
{ BFD_RELOC_SPARC_TLS_LE_HIX22, R_SPARC_TLS_LE_HIX22 }, |
280 |
|
{ BFD_RELOC_SPARC_TLS_LE_LOX10, R_SPARC_TLS_LE_LOX10 }, |
281 |
|
{ BFD_RELOC_SPARC_TLS_DTPMOD32, R_SPARC_TLS_DTPMOD32 }, |
282 |
|
{ BFD_RELOC_SPARC_TLS_DTPMOD64, R_SPARC_TLS_DTPMOD64 }, |
283 |
|
{ BFD_RELOC_SPARC_TLS_DTPOFF32, R_SPARC_TLS_DTPOFF32 }, |
284 |
|
{ BFD_RELOC_SPARC_TLS_DTPOFF64, R_SPARC_TLS_DTPOFF64 }, |
285 |
|
{ BFD_RELOC_SPARC_TLS_TPOFF32, R_SPARC_TLS_TPOFF32 }, |
286 |
|
{ BFD_RELOC_SPARC_TLS_TPOFF64, R_SPARC_TLS_TPOFF64 }, |
287 |
#ifndef SPARC64_OLD_RELOCS |
#ifndef SPARC64_OLD_RELOCS |
288 |
{ BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 }, |
{ BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 }, |
289 |
#endif |
#endif |
314 |
sparc64_elf_info_to_howto (abfd, cache_ptr, dst) |
sparc64_elf_info_to_howto (abfd, cache_ptr, dst) |
315 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
316 |
arelent *cache_ptr; |
arelent *cache_ptr; |
317 |
Elf64_Internal_Rela *dst; |
Elf_Internal_Rela *dst; |
318 |
{ |
{ |
319 |
BFD_ASSERT (ELF64_R_TYPE_ID (dst->r_info) < (unsigned int) R_SPARC_max_std); |
BFD_ASSERT (ELF64_R_TYPE_ID (dst->r_info) < (unsigned int) R_SPARC_max_std); |
320 |
cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (dst->r_info)]; |
cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (dst->r_info)]; |
321 |
} |
} |
322 |
|
|
323 |
|
struct sparc64_elf_section_data |
324 |
|
{ |
325 |
|
struct bfd_elf_section_data elf; |
326 |
|
unsigned int do_relax, reloc_count; |
327 |
|
}; |
328 |
|
|
329 |
|
#define sec_do_relax(sec) \ |
330 |
|
((struct sparc64_elf_section_data *) elf_section_data (sec))->do_relax |
331 |
|
#define canon_reloc_count(sec) \ |
332 |
|
((struct sparc64_elf_section_data *) elf_section_data (sec))->reloc_count |
333 |
|
|
334 |
/* Due to the way how we handle R_SPARC_OLO10, each entry in a SHT_RELA |
/* Due to the way how we handle R_SPARC_OLO10, each entry in a SHT_RELA |
335 |
section can represent up to two relocs, we must tell the user to allocate |
section can represent up to two relocs, we must tell the user to allocate |
336 |
more space. */ |
more space. */ |
355 |
has secondary addend in ELF64_R_TYPE_DATA. We handle it as two relocations |
has secondary addend in ELF64_R_TYPE_DATA. We handle it as two relocations |
356 |
for the same location, R_SPARC_LO10 and R_SPARC_13. */ |
for the same location, R_SPARC_LO10 and R_SPARC_13. */ |
357 |
|
|
358 |
static boolean |
static bfd_boolean |
359 |
sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, dynamic) |
sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, dynamic) |
360 |
bfd *abfd; |
bfd *abfd; |
361 |
asection *asect; |
asection *asect; |
362 |
Elf_Internal_Shdr *rel_hdr; |
Elf_Internal_Shdr *rel_hdr; |
363 |
asymbol **symbols; |
asymbol **symbols; |
364 |
boolean dynamic; |
bfd_boolean dynamic; |
365 |
{ |
{ |
366 |
PTR allocated = NULL; |
PTR allocated = NULL; |
367 |
bfd_byte *native_relocs; |
bfd_byte *native_relocs; |
381 |
|
|
382 |
native_relocs = (bfd_byte *) allocated; |
native_relocs = (bfd_byte *) allocated; |
383 |
|
|
384 |
relents = asect->relocation + asect->reloc_count; |
relents = asect->relocation + canon_reloc_count (asect); |
385 |
|
|
386 |
entsize = rel_hdr->sh_entsize; |
entsize = rel_hdr->sh_entsize; |
387 |
BFD_ASSERT (entsize == sizeof (Elf64_External_Rela)); |
BFD_ASSERT (entsize == sizeof (Elf64_External_Rela)); |
393 |
{ |
{ |
394 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
395 |
|
|
396 |
bfd_elf64_swap_reloca_in (abfd, (Elf64_External_Rela *) native_relocs, &rela); |
bfd_elf64_swap_reloca_in (abfd, native_relocs, &rela); |
397 |
|
|
398 |
/* The address of an ELF reloc is section relative for an object |
/* The address of an ELF reloc is section relative for an object |
399 |
file, and absolute for an executable file or shared library. |
file, and absolute for an executable file or shared library. |
436 |
relent->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (rela.r_info)]; |
relent->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (rela.r_info)]; |
437 |
} |
} |
438 |
|
|
439 |
asect->reloc_count += relent - relents; |
canon_reloc_count (asect) += relent - relents; |
440 |
|
|
441 |
if (allocated != NULL) |
if (allocated != NULL) |
442 |
free (allocated); |
free (allocated); |
443 |
|
|
444 |
return true; |
return TRUE; |
445 |
|
|
446 |
error_return: |
error_return: |
447 |
if (allocated != NULL) |
if (allocated != NULL) |
448 |
free (allocated); |
free (allocated); |
449 |
return false; |
return FALSE; |
450 |
} |
} |
451 |
|
|
452 |
/* Read in and swap the external relocs. */ |
/* Read in and swap the external relocs. */ |
453 |
|
|
454 |
static boolean |
static bfd_boolean |
455 |
sparc64_elf_slurp_reloc_table (abfd, asect, symbols, dynamic) |
sparc64_elf_slurp_reloc_table (abfd, asect, symbols, dynamic) |
456 |
bfd *abfd; |
bfd *abfd; |
457 |
asection *asect; |
asection *asect; |
458 |
asymbol **symbols; |
asymbol **symbols; |
459 |
boolean dynamic; |
bfd_boolean dynamic; |
460 |
{ |
{ |
461 |
struct bfd_elf_section_data * const d = elf_section_data (asect); |
struct bfd_elf_section_data * const d = elf_section_data (asect); |
462 |
Elf_Internal_Shdr *rel_hdr; |
Elf_Internal_Shdr *rel_hdr; |
464 |
bfd_size_type amt; |
bfd_size_type amt; |
465 |
|
|
466 |
if (asect->relocation != NULL) |
if (asect->relocation != NULL) |
467 |
return true; |
return TRUE; |
468 |
|
|
469 |
if (! dynamic) |
if (! dynamic) |
470 |
{ |
{ |
471 |
if ((asect->flags & SEC_RELOC) == 0 |
if ((asect->flags & SEC_RELOC) == 0 |
472 |
|| asect->reloc_count == 0) |
|| asect->reloc_count == 0) |
473 |
return true; |
return TRUE; |
474 |
|
|
475 |
rel_hdr = &d->rel_hdr; |
rel_hdr = &d->rel_hdr; |
476 |
rel_hdr2 = d->rel_hdr2; |
rel_hdr2 = d->rel_hdr2; |
484 |
case because relocations against this section may use the |
case because relocations against this section may use the |
485 |
dynamic symbol table, and in that case bfd_section_from_shdr |
dynamic symbol table, and in that case bfd_section_from_shdr |
486 |
in elf.c does not update the RELOC_COUNT. */ |
in elf.c does not update the RELOC_COUNT. */ |
487 |
if (asect->_raw_size == 0) |
if (asect->size == 0) |
488 |
return true; |
return TRUE; |
489 |
|
|
490 |
rel_hdr = &d->this_hdr; |
rel_hdr = &d->this_hdr; |
491 |
asect->reloc_count = NUM_SHDR_ENTRIES (rel_hdr); |
asect->reloc_count = NUM_SHDR_ENTRIES (rel_hdr); |
496 |
amt *= 2 * sizeof (arelent); |
amt *= 2 * sizeof (arelent); |
497 |
asect->relocation = (arelent *) bfd_alloc (abfd, amt); |
asect->relocation = (arelent *) bfd_alloc (abfd, amt); |
498 |
if (asect->relocation == NULL) |
if (asect->relocation == NULL) |
499 |
return false; |
return FALSE; |
500 |
|
|
501 |
/* The sparc64_elf_slurp_one_reloc_table routine increments reloc_count. */ |
/* The sparc64_elf_slurp_one_reloc_table routine increments |
502 |
asect->reloc_count = 0; |
canon_reloc_count. */ |
503 |
|
canon_reloc_count (asect) = 0; |
504 |
|
|
505 |
if (!sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, |
if (!sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, |
506 |
dynamic)) |
dynamic)) |
507 |
return false; |
return FALSE; |
508 |
|
|
509 |
if (rel_hdr2 |
if (rel_hdr2 |
510 |
&& !sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols, |
&& !sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols, |
511 |
dynamic)) |
dynamic)) |
512 |
return false; |
return FALSE; |
513 |
|
|
514 |
return true; |
return TRUE; |
515 |
} |
} |
516 |
|
|
517 |
|
/* Canonicalize the relocs. */ |
518 |
|
|
519 |
|
static long |
520 |
|
sparc64_elf_canonicalize_reloc (abfd, section, relptr, symbols) |
521 |
|
bfd *abfd; |
522 |
|
sec_ptr section; |
523 |
|
arelent **relptr; |
524 |
|
asymbol **symbols; |
525 |
|
{ |
526 |
|
arelent *tblptr; |
527 |
|
unsigned int i; |
528 |
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
529 |
|
|
530 |
|
if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE)) |
531 |
|
return -1; |
532 |
|
|
533 |
|
tblptr = section->relocation; |
534 |
|
for (i = 0; i < canon_reloc_count (section); i++) |
535 |
|
*relptr++ = tblptr++; |
536 |
|
|
537 |
|
*relptr = NULL; |
538 |
|
|
539 |
|
return canon_reloc_count (section); |
540 |
|
} |
541 |
|
|
542 |
|
|
543 |
/* Canonicalize the dynamic relocation entries. Note that we return |
/* Canonicalize the dynamic relocation entries. Note that we return |
544 |
the dynamic relocations as a single block, although they are |
the dynamic relocations as a single block, although they are |
545 |
actually associated with particular sections; the interface, which |
actually associated with particular sections; the interface, which |
573 |
arelent *p; |
arelent *p; |
574 |
long count, i; |
long count, i; |
575 |
|
|
576 |
if (! sparc64_elf_slurp_reloc_table (abfd, s, syms, true)) |
if (! sparc64_elf_slurp_reloc_table (abfd, s, syms, TRUE)) |
577 |
return -1; |
return -1; |
578 |
count = s->reloc_count; |
count = canon_reloc_count (s); |
579 |
p = s->relocation; |
p = s->relocation; |
580 |
for (i = 0; i < count; i++) |
for (i = 0; i < count; i++) |
581 |
*storage++ = p++; |
*storage++ = p++; |
596 |
asection *sec; |
asection *sec; |
597 |
PTR data; |
PTR data; |
598 |
{ |
{ |
599 |
boolean *failedp = (boolean *) data; |
bfd_boolean *failedp = (bfd_boolean *) data; |
600 |
Elf_Internal_Shdr *rela_hdr; |
Elf_Internal_Shdr *rela_hdr; |
601 |
Elf64_External_Rela *outbound_relocas, *src_rela; |
Elf64_External_Rela *outbound_relocas, *src_rela; |
602 |
unsigned int idx, count; |
unsigned int idx, count; |
647 |
rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); |
rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); |
648 |
if (rela_hdr->contents == NULL) |
if (rela_hdr->contents == NULL) |
649 |
{ |
{ |
650 |
*failedp = true; |
*failedp = TRUE; |
651 |
return; |
return; |
652 |
} |
} |
653 |
|
|
687 |
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); |
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); |
688 |
if (n < 0) |
if (n < 0) |
689 |
{ |
{ |
690 |
*failedp = true; |
*failedp = TRUE; |
691 |
return; |
return; |
692 |
} |
} |
693 |
last_sym_idx = n; |
last_sym_idx = n; |
697 |
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec |
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec |
698 |
&& ! _bfd_elf_validate_reloc (abfd, ptr)) |
&& ! _bfd_elf_validate_reloc (abfd, ptr)) |
699 |
{ |
{ |
700 |
*failedp = true; |
*failedp = TRUE; |
701 |
return; |
return; |
702 |
} |
} |
703 |
|
|
723 |
dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type); |
dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type); |
724 |
|
|
725 |
dst_rela.r_addend = ptr->addend; |
dst_rela.r_addend = ptr->addend; |
726 |
bfd_elf64_swap_reloca_out (abfd, &dst_rela, src_rela); |
bfd_elf64_swap_reloca_out (abfd, &dst_rela, (bfd_byte *) src_rela); |
727 |
++src_rela; |
++src_rela; |
728 |
} |
} |
729 |
} |
} |
742 |
{ |
{ |
743 |
struct elf_link_hash_table root; |
struct elf_link_hash_table root; |
744 |
|
|
745 |
|
/* Short-cuts to get to dynamic linker sections. */ |
746 |
|
asection *sgot; |
747 |
|
asection *srelgot; |
748 |
|
|
749 |
struct sparc64_elf_app_reg app_regs [4]; |
struct sparc64_elf_app_reg app_regs [4]; |
750 |
}; |
}; |
751 |
|
|
776 |
|
|
777 |
return &ret->root.root; |
return &ret->root.root; |
778 |
} |
} |
779 |
|
|
780 |
|
/* Create .got and .rela.got sections in DYNOBJ and set up |
781 |
|
shortcuts to them in our hash table. */ |
782 |
|
|
783 |
|
static bfd_boolean |
784 |
|
create_got_section (dynobj, info) |
785 |
|
bfd *dynobj; |
786 |
|
struct bfd_link_info *info; |
787 |
|
{ |
788 |
|
struct sparc64_elf_link_hash_table *htab; |
789 |
|
|
790 |
|
if (! _bfd_elf_create_got_section (dynobj, info)) |
791 |
|
return FALSE; |
792 |
|
|
793 |
|
htab = sparc64_elf_hash_table (info); |
794 |
|
htab->sgot = bfd_get_section_by_name (dynobj, ".got"); |
795 |
|
BFD_ASSERT (htab->sgot != NULL); |
796 |
|
|
797 |
|
htab->srelgot = bfd_make_section (dynobj, ".rela.got"); |
798 |
|
if (htab->srelgot == NULL |
799 |
|
|| ! bfd_set_section_flags (dynobj, htab->srelgot, SEC_ALLOC |
800 |
|
| SEC_LOAD |
801 |
|
| SEC_HAS_CONTENTS |
802 |
|
| SEC_IN_MEMORY |
803 |
|
| SEC_LINKER_CREATED |
804 |
|
| SEC_READONLY) |
805 |
|
|| ! bfd_set_section_alignment (dynobj, htab->srelgot, 3)) |
806 |
|
return FALSE; |
807 |
|
return TRUE; |
808 |
|
} |
809 |
|
|
810 |
|
/* Create .plt, .rela.plt, .got, .rela.got, .dynbss, and |
811 |
|
.rela.bss sections in DYNOBJ, and set up shortcuts to them in our |
812 |
|
hash table. */ |
813 |
|
|
814 |
|
static bfd_boolean |
815 |
|
sparc64_elf_create_dynamic_sections (dynobj, info) |
816 |
|
bfd *dynobj; |
817 |
|
struct bfd_link_info *info; |
818 |
|
{ |
819 |
|
struct sparc64_elf_link_hash_table *htab; |
820 |
|
|
821 |
|
htab = sparc64_elf_hash_table (info); |
822 |
|
if (!htab->sgot && !create_got_section (dynobj, info)) |
823 |
|
return FALSE; |
824 |
|
|
825 |
|
if (!_bfd_elf_create_dynamic_sections (dynobj, info)) |
826 |
|
return FALSE; |
827 |
|
|
828 |
|
return TRUE; |
829 |
|
} |
830 |
|
|
831 |
/* Utility for performing the standard initial work of an instruction |
/* Utility for performing the standard initial work of an instruction |
832 |
relocation. |
relocation. |
866 |
return bfd_reloc_ok; |
return bfd_reloc_ok; |
867 |
} |
} |
868 |
|
|
869 |
/* This works because partial_inplace is false. */ |
/* This works because partial_inplace is FALSE. */ |
870 |
if (output_bfd != NULL) |
if (output_bfd != NULL) |
871 |
return bfd_reloc_continue; |
return bfd_reloc_continue; |
872 |
|
|
873 |
if (reloc_entry->address > input_section->_cooked_size) |
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) |
874 |
return bfd_reloc_outofrange; |
return bfd_reloc_outofrange; |
875 |
|
|
876 |
relocation = (symbol->value |
relocation = (symbol->value |
1146 |
allocate space in the global offset table or procedure linkage |
allocate space in the global offset table or procedure linkage |
1147 |
table. */ |
table. */ |
1148 |
|
|
1149 |
static boolean |
static bfd_boolean |
1150 |
sparc64_elf_check_relocs (abfd, info, sec, relocs) |
sparc64_elf_check_relocs (abfd, info, sec, relocs) |
1151 |
bfd *abfd; |
bfd *abfd; |
1152 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1163 |
asection *srelgot; |
asection *srelgot; |
1164 |
asection *sreloc; |
asection *sreloc; |
1165 |
|
|
1166 |
if (info->relocateable || !(sec->flags & SEC_ALLOC)) |
if (info->relocatable || !(sec->flags & SEC_ALLOC)) |
1167 |
return true; |
return TRUE; |
1168 |
|
|
1169 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
1170 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
1196 |
|
|
1197 |
if (dynobj == NULL) |
if (dynobj == NULL) |
1198 |
{ |
{ |
1199 |
/* Create the .got section. */ |
/* Create the .got and .rela.got sections. */ |
1200 |
elf_hash_table (info)->dynobj = dynobj = abfd; |
elf_hash_table (info)->dynobj = dynobj = abfd; |
1201 |
if (! _bfd_elf_create_got_section (dynobj, info)) |
if (! create_got_section (dynobj, info)) |
1202 |
return false; |
return FALSE; |
1203 |
} |
} |
1204 |
|
|
1205 |
if (sgot == NULL) |
if (sgot == NULL) |
1206 |
{ |
{ |
1207 |
sgot = bfd_get_section_by_name (dynobj, ".got"); |
sgot = sparc64_elf_hash_table (info)->sgot; |
1208 |
BFD_ASSERT (sgot != NULL); |
BFD_ASSERT (sgot != NULL); |
1209 |
} |
} |
1210 |
|
|
1211 |
if (srelgot == NULL && (h != NULL || info->shared)) |
if (srelgot == NULL && (h != NULL || info->shared)) |
1212 |
{ |
{ |
1213 |
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
srelgot = sparc64_elf_hash_table (info)->srelgot; |
1214 |
if (srelgot == NULL) |
BFD_ASSERT (srelgot != NULL); |
|
{ |
|
|
srelgot = bfd_make_section (dynobj, ".rela.got"); |
|
|
if (srelgot == NULL |
|
|
|| ! bfd_set_section_flags (dynobj, srelgot, |
|
|
(SEC_ALLOC |
|
|
| SEC_LOAD |
|
|
| SEC_HAS_CONTENTS |
|
|
| SEC_IN_MEMORY |
|
|
| SEC_LINKER_CREATED |
|
|
| SEC_READONLY)) |
|
|
|| ! bfd_set_section_alignment (dynobj, srelgot, 3)) |
|
|
return false; |
|
|
} |
|
1215 |
} |
} |
1216 |
|
|
1217 |
if (h != NULL) |
if (h != NULL) |
1221 |
/* We have already allocated space in the .got. */ |
/* We have already allocated space in the .got. */ |
1222 |
break; |
break; |
1223 |
} |
} |
1224 |
h->got.offset = sgot->_raw_size; |
h->got.offset = sgot->size; |
1225 |
|
|
1226 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
1227 |
if (h->dynindx == -1) |
if (h->dynindx == -1) |
1228 |
{ |
{ |
1229 |
if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
1230 |
return false; |
return FALSE; |
1231 |
} |
} |
1232 |
|
|
1233 |
srelgot->_raw_size += sizeof (Elf64_External_Rela); |
srelgot->size += sizeof (Elf64_External_Rela); |
1234 |
} |
} |
1235 |
else |
else |
1236 |
{ |
{ |
1245 |
size *= sizeof (bfd_vma); |
size *= sizeof (bfd_vma); |
1246 |
local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size); |
local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size); |
1247 |
if (local_got_offsets == NULL) |
if (local_got_offsets == NULL) |
1248 |
return false; |
return FALSE; |
1249 |
elf_local_got_offsets (abfd) = local_got_offsets; |
elf_local_got_offsets (abfd) = local_got_offsets; |
1250 |
for (i = 0; i < symtab_hdr->sh_info; i++) |
for (i = 0; i < symtab_hdr->sh_info; i++) |
1251 |
local_got_offsets[i] = (bfd_vma) -1; |
local_got_offsets[i] = (bfd_vma) -1; |
1255 |
/* We have already allocated space in the .got. */ |
/* We have already allocated space in the .got. */ |
1256 |
break; |
break; |
1257 |
} |
} |
1258 |
local_got_offsets[r_symndx] = sgot->_raw_size; |
local_got_offsets[r_symndx] = sgot->size; |
1259 |
|
|
1260 |
if (info->shared) |
if (info->shared) |
1261 |
{ |
{ |
1262 |
/* If we are generating a shared object, we need to |
/* If we are generating a shared object, we need to |
1263 |
output a R_SPARC_RELATIVE reloc so that the |
output a R_SPARC_RELATIVE reloc so that the |
1264 |
dynamic linker can adjust this GOT entry. */ |
dynamic linker can adjust this GOT entry. */ |
1265 |
srelgot->_raw_size += sizeof (Elf64_External_Rela); |
srelgot->size += sizeof (Elf64_External_Rela); |
1266 |
} |
} |
1267 |
} |
} |
1268 |
|
|
1269 |
sgot->_raw_size += 8; |
sgot->size += 8; |
1270 |
|
|
|
#if 0 |
|
1271 |
/* Doesn't work for 64-bit -fPIC, since sethi/or builds |
/* Doesn't work for 64-bit -fPIC, since sethi/or builds |
1272 |
unsigned numbers. If we permit ourselves to modify |
unsigned numbers. If we permit ourselves to modify |
1273 |
code so we get sethi/xor, this could work. |
code so we get sethi/xor, this could work. |
1276 |
/* If the .got section is more than 0x1000 bytes, we add |
/* If the .got section is more than 0x1000 bytes, we add |
1277 |
0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13 |
0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13 |
1278 |
bit relocations have a greater chance of working. */ |
bit relocations have a greater chance of working. */ |
1279 |
if (sgot->_raw_size >= 0x1000 |
/* |
1280 |
|
if (sgot->size >= 0x1000 |
1281 |
&& elf_hash_table (info)->hgot->root.u.def.value == 0) |
&& elf_hash_table (info)->hgot->root.u.def.value == 0) |
1282 |
elf_hash_table (info)->hgot->root.u.def.value = 0x1000; |
elf_hash_table (info)->hgot->root.u.def.value = 0x1000; |
1283 |
#endif |
*/ |
1284 |
|
|
1285 |
break; |
break; |
1286 |
|
|
1303 |
/* It does not make sense to have a procedure linkage |
/* It does not make sense to have a procedure linkage |
1304 |
table entry for a local symbol. */ |
table entry for a local symbol. */ |
1305 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
1306 |
return false; |
return FALSE; |
1307 |
} |
} |
1308 |
|
|
1309 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
1310 |
if (h->dynindx == -1) |
if (h->dynindx == -1) |
1311 |
{ |
{ |
1312 |
if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
1313 |
return false; |
return FALSE; |
1314 |
} |
} |
1315 |
|
|
1316 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 1; |
1317 |
if (ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT32 |
if (ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT32 |
1318 |
&& ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT64) |
&& ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT64) |
1319 |
break; |
break; |
1382 |
elf_elfheader (abfd)->e_shstrndx, |
elf_elfheader (abfd)->e_shstrndx, |
1383 |
elf_section_data (sec)->rel_hdr.sh_name)); |
elf_section_data (sec)->rel_hdr.sh_name)); |
1384 |
if (name == NULL) |
if (name == NULL) |
1385 |
return false; |
return FALSE; |
1386 |
|
|
1387 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
1388 |
&& strcmp (bfd_get_section_name (abfd, sec), |
&& strcmp (bfd_get_section_name (abfd, sec), |
1401 |
if (sreloc == NULL |
if (sreloc == NULL |
1402 |
|| ! bfd_set_section_flags (dynobj, sreloc, flags) |
|| ! bfd_set_section_flags (dynobj, sreloc, flags) |
1403 |
|| ! bfd_set_section_alignment (dynobj, sreloc, 3)) |
|| ! bfd_set_section_alignment (dynobj, sreloc, 3)) |
1404 |
return false; |
return FALSE; |
1405 |
} |
} |
1406 |
if (sec->flags & SEC_READONLY) |
if (sec->flags & SEC_READONLY) |
1407 |
info->flags |= DF_TEXTREL; |
info->flags |= DF_TEXTREL; |
1408 |
} |
} |
1409 |
|
|
1410 |
sreloc->_raw_size += sizeof (Elf64_External_Rela); |
sreloc->size += sizeof (Elf64_External_Rela); |
1411 |
} |
} |
1412 |
break; |
break; |
1413 |
|
|
1416 |
break; |
break; |
1417 |
|
|
1418 |
default: |
default: |
1419 |
(*_bfd_error_handler) (_("%s: check_relocs: unhandled reloc type %d"), |
(*_bfd_error_handler) (_("%B: check_relocs: unhandled reloc type %d"), |
1420 |
bfd_archive_filename (abfd), |
abfd, ELF64_R_TYPE_ID (rel->r_info)); |
1421 |
ELF64_R_TYPE_ID (rel->r_info)); |
return FALSE; |
|
return false; |
|
1422 |
} |
} |
1423 |
} |
} |
1424 |
|
|
1425 |
return true; |
return TRUE; |
1426 |
} |
} |
1427 |
|
|
1428 |
/* Hook called by the linker routine which adds symbols from an object |
/* Hook called by the linker routine which adds symbols from an object |
1429 |
file. We use it for STT_REGISTER symbols. */ |
file. We use it for STT_REGISTER symbols. */ |
1430 |
|
|
1431 |
static boolean |
static bfd_boolean |
1432 |
sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
1433 |
bfd *abfd; |
bfd *abfd; |
1434 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1435 |
const Elf_Internal_Sym *sym; |
Elf_Internal_Sym *sym; |
1436 |
const char **namep; |
const char **namep; |
1437 |
flagword *flagsp ATTRIBUTE_UNUSED; |
flagword *flagsp ATTRIBUTE_UNUSED; |
1438 |
asection **secp ATTRIBUTE_UNUSED; |
asection **secp ATTRIBUTE_UNUSED; |
1452 |
case 6: reg -= 4; break; |
case 6: reg -= 4; break; |
1453 |
default: |
default: |
1454 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
1455 |
(_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"), |
(_("%B: Only registers %%g[2367] can be declared using STT_REGISTER"), |
1456 |
bfd_archive_filename (abfd)); |
abfd); |
1457 |
return false; |
return FALSE; |
1458 |
} |
} |
1459 |
|
|
1460 |
if (info->hash->creator != abfd->xvec |
if (info->hash->creator != abfd->xvec |
1464 |
If STT_REGISTER comes from a dynamic object, don't put it into |
If STT_REGISTER comes from a dynamic object, don't put it into |
1465 |
the output bfd. The dynamic linker will recheck it. */ |
the output bfd. The dynamic linker will recheck it. */ |
1466 |
*namep = NULL; |
*namep = NULL; |
1467 |
return true; |
return TRUE; |
1468 |
} |
} |
1469 |
|
|
1470 |
p = sparc64_elf_hash_table(info)->app_regs + reg; |
p = sparc64_elf_hash_table(info)->app_regs + reg; |
1472 |
if (p->name != NULL && strcmp (p->name, *namep)) |
if (p->name != NULL && strcmp (p->name, *namep)) |
1473 |
{ |
{ |
1474 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
1475 |
(_("Register %%g%d used incompatibly: %s in %s, previously %s in %s"), |
(_("Register %%g%d used incompatibly: %s in %B, previously %s in %B"), |
1476 |
(int) sym->st_value, |
abfd, p->abfd, (int) sym->st_value, |
1477 |
**namep ? *namep : "#scratch", bfd_archive_filename (abfd), |
**namep ? *namep : "#scratch", |
1478 |
*p->name ? p->name : "#scratch", bfd_archive_filename (p->abfd)); |
*p->name ? p->name : "#scratch"); |
1479 |
return false; |
return FALSE; |
1480 |
} |
} |
1481 |
|
|
1482 |
if (p->name == NULL) |
if (p->name == NULL) |
1486 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
1487 |
|
|
1488 |
h = (struct elf_link_hash_entry *) |
h = (struct elf_link_hash_entry *) |
1489 |
bfd_link_hash_lookup (info->hash, *namep, false, false, false); |
bfd_link_hash_lookup (info->hash, *namep, FALSE, FALSE, FALSE); |
1490 |
|
|
1491 |
if (h != NULL) |
if (h != NULL) |
1492 |
{ |
{ |
1495 |
if (type > STT_FUNC) |
if (type > STT_FUNC) |
1496 |
type = 0; |
type = 0; |
1497 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
1498 |
(_("Symbol `%s' has differing types: REGISTER in %s, previously %s in %s"), |
(_("Symbol `%s' has differing types: REGISTER in %B, previously %s in %B"), |
1499 |
*namep, bfd_archive_filename (abfd), |
abfd, p->abfd, *namep, stt_types[type]); |
1500 |
stt_types[type], bfd_archive_filename (p->abfd)); |
return FALSE; |
|
return false; |
|
1501 |
} |
} |
1502 |
|
|
1503 |
p->name = bfd_hash_allocate (&info->hash->table, |
p->name = bfd_hash_allocate (&info->hash->table, |
1504 |
strlen (*namep) + 1); |
strlen (*namep) + 1); |
1505 |
if (!p->name) |
if (!p->name) |
1506 |
return false; |
return FALSE; |
1507 |
|
|
1508 |
strcpy (p->name, *namep); |
strcpy (p->name, *namep); |
1509 |
} |
} |
1523 |
} |
} |
1524 |
} |
} |
1525 |
*namep = NULL; |
*namep = NULL; |
1526 |
return true; |
return TRUE; |
1527 |
} |
} |
1528 |
else if (*namep && **namep |
else if (*namep && **namep |
1529 |
&& info->hash->creator == abfd->xvec) |
&& info->hash->creator == abfd->xvec) |
1540 |
if (type > STT_FUNC) |
if (type > STT_FUNC) |
1541 |
type = 0; |
type = 0; |
1542 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
1543 |
(_("Symbol `%s' has differing types: %s in %s, previously REGISTER in %s"), |
(_("Symbol `%s' has differing types: %s in %B, previously REGISTER in %B"), |
1544 |
*namep, stt_types[type], bfd_archive_filename (abfd), |
abfd, p->abfd, *namep, stt_types[type]); |
1545 |
bfd_archive_filename (p->abfd)); |
return FALSE; |
|
return false; |
|
1546 |
} |
} |
1547 |
} |
} |
1548 |
return true; |
return TRUE; |
1549 |
} |
} |
1550 |
|
|
1551 |
/* This function takes care of emiting STT_REGISTER symbols |
/* This function takes care of emitting STT_REGISTER symbols |
1552 |
which we cannot easily keep in the symbol hash table. */ |
which we cannot easily keep in the symbol hash table. */ |
1553 |
|
|
1554 |
static boolean |
static bfd_boolean |
1555 |
sparc64_elf_output_arch_syms (output_bfd, info, finfo, func) |
sparc64_elf_output_arch_syms (output_bfd, info, finfo, func) |
1556 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
bfd *output_bfd ATTRIBUTE_UNUSED; |
1557 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1558 |
PTR finfo; |
PTR finfo; |
1559 |
boolean (*func) PARAMS ((PTR, const char *, |
bfd_boolean (*func) |
1560 |
Elf_Internal_Sym *, asection *)); |
PARAMS ((PTR, const char *, Elf_Internal_Sym *, asection *, |
1561 |
|
struct elf_link_hash_entry *)); |
1562 |
{ |
{ |
1563 |
int reg; |
int reg; |
1564 |
struct sparc64_elf_app_reg *app_regs = |
struct sparc64_elf_app_reg *app_regs = |
1586 |
} |
} |
1587 |
|
|
1588 |
if (info->strip == strip_all) |
if (info->strip == strip_all) |
1589 |
return true; |
return TRUE; |
1590 |
|
|
1591 |
for (reg = 0; reg < 4; reg++) |
for (reg = 0; reg < 4; reg++) |
1592 |
if (app_regs [reg].name != NULL) |
if (app_regs [reg].name != NULL) |
1594 |
if (info->strip == strip_some |
if (info->strip == strip_some |
1595 |
&& bfd_hash_lookup (info->keep_hash, |
&& bfd_hash_lookup (info->keep_hash, |
1596 |
app_regs [reg].name, |
app_regs [reg].name, |
1597 |
false, false) == NULL) |
FALSE, FALSE) == NULL) |
1598 |
continue; |
continue; |
1599 |
|
|
1600 |
sym.st_value = reg < 2 ? reg + 2 : reg + 4; |
sym.st_value = reg < 2 ? reg + 2 : reg + 4; |
1604 |
sym.st_shndx = app_regs [reg].shndx; |
sym.st_shndx = app_regs [reg].shndx; |
1605 |
if (! (*func) (finfo, app_regs [reg].name, &sym, |
if (! (*func) (finfo, app_regs [reg].name, &sym, |
1606 |
sym.st_shndx == SHN_ABS |
sym.st_shndx == SHN_ABS |
1607 |
? bfd_abs_section_ptr : bfd_und_section_ptr)) |
? bfd_abs_section_ptr : bfd_und_section_ptr, |
1608 |
return false; |
NULL)) |
1609 |
|
return FALSE; |
1610 |
} |
} |
1611 |
|
|
1612 |
return true; |
return TRUE; |
1613 |
} |
} |
1614 |
|
|
1615 |
static int |
static int |
1647 |
change the definition to something the rest of the link can |
change the definition to something the rest of the link can |
1648 |
understand. */ |
understand. */ |
1649 |
|
|
1650 |
static boolean |
static bfd_boolean |
1651 |
sparc64_elf_adjust_dynamic_symbol (info, h) |
sparc64_elf_adjust_dynamic_symbol (info, h) |
1652 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1653 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
1660 |
|
|
1661 |
/* Make sure we know what is going on here. */ |
/* Make sure we know what is going on here. */ |
1662 |
BFD_ASSERT (dynobj != NULL |
BFD_ASSERT (dynobj != NULL |
1663 |
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) |
&& (h->needs_plt |
1664 |
|| h->weakdef != NULL |
|| h->u.weakdef != NULL |
1665 |
|| ((h->elf_link_hash_flags |
|| (h->def_dynamic |
1666 |
& ELF_LINK_HASH_DEF_DYNAMIC) != 0 |
&& h->ref_regular |
1667 |
&& (h->elf_link_hash_flags |
&& !h->def_regular))); |
|
& ELF_LINK_HASH_REF_REGULAR) != 0 |
|
|
&& (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_REGULAR) == 0))); |
|
1668 |
|
|
1669 |
/* If this is a function, put it in the procedure linkage table. We |
/* If this is a function, put it in the procedure linkage table. We |
1670 |
will fill in the contents of the procedure linkage table later |
will fill in the contents of the procedure linkage table later |
1674 |
some of their functions as STT_NOTYPE when they really should be |
some of their functions as STT_NOTYPE when they really should be |
1675 |
STT_FUNC. */ |
STT_FUNC. */ |
1676 |
if (h->type == STT_FUNC |
if (h->type == STT_FUNC |
1677 |
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0 |
|| h->needs_plt |
1678 |
|| (h->type == STT_NOTYPE |
|| (h->type == STT_NOTYPE |
1679 |
&& (h->root.type == bfd_link_hash_defined |
&& (h->root.type == bfd_link_hash_defined |
1680 |
|| h->root.type == bfd_link_hash_defweak) |
|| h->root.type == bfd_link_hash_defweak) |
1681 |
&& (h->root.u.def.section->flags & SEC_CODE) != 0)) |
&& (h->root.u.def.section->flags & SEC_CODE) != 0)) |
1682 |
{ |
{ |
1683 |
if (! elf_hash_table (info)->dynamic_sections_created) |
if (! info->shared |
1684 |
|
&& !h->def_dynamic |
1685 |
|
&& !h->ref_dynamic |
1686 |
|
&& h->root.type != bfd_link_hash_undefweak |
1687 |
|
&& h->root.type != bfd_link_hash_undefined) |
1688 |
{ |
{ |
1689 |
/* This case can occur if we saw a WPLT30 reloc in an input |
/* This case can occur if we saw a WPLT30 reloc in an input |
1690 |
file, but none of the input files were dynamic objects. |
file, but none of the input files were dynamic objects. |
1691 |
In such a case, we don't actually need to build a |
In such a case, we don't actually need to build a |
1692 |
procedure linkage table, and we can just do a WDISP30 |
procedure linkage table, and we can just do a WDISP30 |
1693 |
reloc instead. */ |
reloc instead. */ |
1694 |
BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); |
BFD_ASSERT (h->needs_plt); |
1695 |
return true; |
return TRUE; |
1696 |
} |
} |
1697 |
|
|
1698 |
s = bfd_get_section_by_name (dynobj, ".plt"); |
s = bfd_get_section_by_name (dynobj, ".plt"); |
1699 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1700 |
|
|
1701 |
/* The first four bit in .plt is reserved. */ |
/* The first four bit in .plt is reserved. */ |
1702 |
if (s->_raw_size == 0) |
if (s->size == 0) |
1703 |
s->_raw_size = PLT_HEADER_SIZE; |
s->size = PLT_HEADER_SIZE; |
1704 |
|
|
1705 |
|
/* To simplify matters later, just store the plt index here. */ |
1706 |
|
h->plt.offset = s->size / PLT_ENTRY_SIZE; |
1707 |
|
|
1708 |
/* If this symbol is not defined in a regular file, and we are |
/* If this symbol is not defined in a regular file, and we are |
1709 |
not generating a shared library, then set the symbol to this |
not generating a shared library, then set the symbol to this |
1711 |
pointers compare as equal between the normal executable and |
pointers compare as equal between the normal executable and |
1712 |
the shared library. */ |
the shared library. */ |
1713 |
if (! info->shared |
if (! info->shared |
1714 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
&& !h->def_regular) |
1715 |
{ |
{ |
1716 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
1717 |
h->root.u.def.value = s->_raw_size; |
h->root.u.def.value = sparc64_elf_plt_entry_offset (h->plt.offset); |
1718 |
} |
} |
1719 |
|
|
|
/* To simplify matters later, just store the plt index here. */ |
|
|
h->plt.offset = s->_raw_size / PLT_ENTRY_SIZE; |
|
|
|
|
1720 |
/* Make room for this entry. */ |
/* Make room for this entry. */ |
1721 |
s->_raw_size += PLT_ENTRY_SIZE; |
s->size += PLT_ENTRY_SIZE; |
1722 |
|
|
1723 |
/* We also need to make an entry in the .rela.plt section. */ |
/* We also need to make an entry in the .rela.plt section. */ |
1724 |
|
|
1725 |
s = bfd_get_section_by_name (dynobj, ".rela.plt"); |
s = bfd_get_section_by_name (dynobj, ".rela.plt"); |
1726 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1727 |
|
|
1728 |
s->_raw_size += sizeof (Elf64_External_Rela); |
s->size += sizeof (Elf64_External_Rela); |
1729 |
|
|
1730 |
/* The procedure linkage table size is bounded by the magnitude |
/* The procedure linkage table size is bounded by the magnitude |
1731 |
of the offset we can describe in the entry. */ |
of the offset we can describe in the entry. */ |
1732 |
if (s->_raw_size >= (bfd_vma)1 << 32) |
if (s->size >= (bfd_vma)1 << 32) |
1733 |
{ |
{ |
1734 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
1735 |
return false; |
return FALSE; |
1736 |
} |
} |
1737 |
|
|
1738 |
return true; |
return TRUE; |
1739 |
} |
} |
1740 |
|
|
1741 |
/* If this is a weak symbol, and there is a real definition, the |
/* If this is a weak symbol, and there is a real definition, the |
1742 |
processor independent code will have arranged for us to see the |
processor independent code will have arranged for us to see the |
1743 |
real definition first, and we can just use the same value. */ |
real definition first, and we can just use the same value. */ |
1744 |
if (h->weakdef != NULL) |
if (h->u.weakdef != NULL) |
1745 |
{ |
{ |
1746 |
BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined |
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined |
1747 |
|| h->weakdef->root.type == bfd_link_hash_defweak); |
|| h->u.weakdef->root.type == bfd_link_hash_defweak); |
1748 |
h->root.u.def.section = h->weakdef->root.u.def.section; |
h->root.u.def.section = h->u.weakdef->root.u.def.section; |
1749 |
h->root.u.def.value = h->weakdef->root.u.def.value; |
h->root.u.def.value = h->u.weakdef->root.u.def.value; |
1750 |
return true; |
return TRUE; |
1751 |
} |
} |
1752 |
|
|
1753 |
/* This is a reference to a symbol defined by a dynamic object which |
/* This is a reference to a symbol defined by a dynamic object which |
1758 |
For such cases we need not do anything here; the relocations will |
For such cases we need not do anything here; the relocations will |
1759 |
be handled correctly by relocate_section. */ |
be handled correctly by relocate_section. */ |
1760 |
if (info->shared) |
if (info->shared) |
1761 |
return true; |
return TRUE; |
1762 |
|
|
1763 |
/* We must allocate the symbol in our .dynbss section, which will |
/* We must allocate the symbol in our .dynbss section, which will |
1764 |
become part of the .bss section of the executable. There will be |
become part of the .bss section of the executable. There will be |
1783 |
|
|
1784 |
srel = bfd_get_section_by_name (dynobj, ".rela.bss"); |
srel = bfd_get_section_by_name (dynobj, ".rela.bss"); |
1785 |
BFD_ASSERT (srel != NULL); |
BFD_ASSERT (srel != NULL); |
1786 |
srel->_raw_size += sizeof (Elf64_External_Rela); |
srel->size += sizeof (Elf64_External_Rela); |
1787 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; |
h->needs_copy = 1; |
1788 |
} |
} |
1789 |
|
|
1790 |
/* We need to figure out the alignment required for this symbol. I |
/* We need to figure out the alignment required for this symbol. I |
1795 |
power_of_two = 4; |
power_of_two = 4; |
1796 |
|
|
1797 |
/* Apply the required alignment. */ |
/* Apply the required alignment. */ |
1798 |
s->_raw_size = BFD_ALIGN (s->_raw_size, |
s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); |
|
(bfd_size_type) (1 << power_of_two)); |
|
1799 |
if (power_of_two > bfd_get_section_alignment (dynobj, s)) |
if (power_of_two > bfd_get_section_alignment (dynobj, s)) |
1800 |
{ |
{ |
1801 |
if (! bfd_set_section_alignment (dynobj, s, power_of_two)) |
if (! bfd_set_section_alignment (dynobj, s, power_of_two)) |
1802 |
return false; |
return FALSE; |
1803 |
} |
} |
1804 |
|
|
1805 |
/* Define the symbol as being at this point in the section. */ |
/* Define the symbol as being at this point in the section. */ |
1806 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
1807 |
h->root.u.def.value = s->_raw_size; |
h->root.u.def.value = s->size; |
1808 |
|
|
1809 |
/* Increment the section size to make room for the symbol. */ |
/* Increment the section size to make room for the symbol. */ |
1810 |
s->_raw_size += h->size; |
s->size += h->size; |
1811 |
|
|
1812 |
|
return TRUE; |
1813 |
|
} |
1814 |
|
|
1815 |
|
/* Return true if the dynamic symbol for a given section should be |
1816 |
|
omitted when creating a shared library. */ |
1817 |
|
|
1818 |
|
static bfd_boolean |
1819 |
|
sparc64_elf_omit_section_dynsym (bfd *output_bfd, |
1820 |
|
struct bfd_link_info *info, |
1821 |
|
asection *p) |
1822 |
|
{ |
1823 |
|
/* We keep the .got section symbol so that explicit relocations |
1824 |
|
against the _GLOBAL_OFFSET_TABLE_ symbol emitted in PIC mode |
1825 |
|
can be turned into relocations against the .got symbol. */ |
1826 |
|
if (strcmp (p->name, ".got") == 0) |
1827 |
|
return FALSE; |
1828 |
|
|
1829 |
return true; |
return _bfd_elf_link_omit_section_dynsym (output_bfd, info, p); |
1830 |
} |
} |
1831 |
|
|
1832 |
/* Set the sizes of the dynamic sections. */ |
/* Set the sizes of the dynamic sections. */ |
1833 |
|
|
1834 |
static boolean |
static bfd_boolean |
1835 |
sparc64_elf_size_dynamic_sections (output_bfd, info) |
sparc64_elf_size_dynamic_sections (output_bfd, info) |
1836 |
bfd *output_bfd; |
bfd *output_bfd; |
1837 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1838 |
{ |
{ |
1839 |
bfd *dynobj; |
bfd *dynobj; |
1840 |
asection *s; |
asection *s; |
1841 |
boolean relplt; |
bfd_boolean relplt; |
1842 |
|
|
1843 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
1844 |
BFD_ASSERT (dynobj != NULL); |
BFD_ASSERT (dynobj != NULL); |
1846 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (elf_hash_table (info)->dynamic_sections_created) |
1847 |
{ |
{ |
1848 |
/* Set the contents of the .interp section to the interpreter. */ |
/* Set the contents of the .interp section to the interpreter. */ |
1849 |
if (! info->shared) |
if (info->executable) |
1850 |
{ |
{ |
1851 |
s = bfd_get_section_by_name (dynobj, ".interp"); |
s = bfd_get_section_by_name (dynobj, ".interp"); |
1852 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1853 |
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; |
s->size = sizeof ELF_DYNAMIC_INTERPRETER; |
1854 |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
1855 |
} |
} |
1856 |
} |
} |
1861 |
not actually use these entries. Reset the size of .rela.got, |
not actually use these entries. Reset the size of .rela.got, |
1862 |
which will cause it to get stripped from the output file |
which will cause it to get stripped from the output file |
1863 |
below. */ |
below. */ |
1864 |
s = bfd_get_section_by_name (dynobj, ".rela.got"); |
s = sparc64_elf_hash_table (info)->srelgot; |
1865 |
if (s != NULL) |
if (s != NULL) |
1866 |
s->_raw_size = 0; |
s->size = 0; |
1867 |
} |
} |
1868 |
|
|
1869 |
/* The check_relocs and adjust_dynamic_symbol entry points have |
/* The check_relocs and adjust_dynamic_symbol entry points have |
1870 |
determined the sizes of the various dynamic sections. Allocate |
determined the sizes of the various dynamic sections. Allocate |
1871 |
memory for them. */ |
memory for them. */ |
1872 |
relplt = false; |
relplt = FALSE; |
1873 |
for (s = dynobj->sections; s != NULL; s = s->next) |
for (s = dynobj->sections; s != NULL; s = s->next) |
1874 |
{ |
{ |
1875 |
const char *name; |
const char *name; |
1876 |
boolean strip; |
bfd_boolean strip; |
1877 |
|
|
1878 |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
1879 |
continue; |
continue; |
1882 |
of the dynobj section names depend upon the input files. */ |
of the dynobj section names depend upon the input files. */ |
1883 |
name = bfd_get_section_name (dynobj, s); |
name = bfd_get_section_name (dynobj, s); |
1884 |
|
|
1885 |
strip = false; |
strip = FALSE; |
1886 |
|
|
1887 |
if (strncmp (name, ".rela", 5) == 0) |
if (strncmp (name, ".rela", 5) == 0) |
1888 |
{ |
{ |
1889 |
if (s->_raw_size == 0) |
if (s->size == 0) |
1890 |
{ |
{ |
1891 |
/* If we don't need this section, strip it from the |
/* If we don't need this section, strip it from the |
1892 |
output file. This is to handle .rela.bss and |
output file. This is to handle .rela.bss and |
1897 |
adjust_dynamic_symbol is called, and it is that |
adjust_dynamic_symbol is called, and it is that |
1898 |
function which decides whether anything needs to go |
function which decides whether anything needs to go |
1899 |
into these sections. */ |
into these sections. */ |
1900 |
strip = true; |
strip = TRUE; |
1901 |
} |
} |
1902 |
else |
else |
1903 |
{ |
{ |
1904 |
if (strcmp (name, ".rela.plt") == 0) |
if (strcmp (name, ".rela.plt") == 0) |
1905 |
relplt = true; |
relplt = TRUE; |
1906 |
|
|
1907 |
/* We use the reloc_count field as a counter if we need |
/* We use the reloc_count field as a counter if we need |
1908 |
to copy relocs into the output file. */ |
to copy relocs into the output file. */ |
1925 |
/* Allocate memory for the section contents. Zero the memory |
/* Allocate memory for the section contents. Zero the memory |
1926 |
for the benefit of .rela.plt, which has 4 unused entries |
for the benefit of .rela.plt, which has 4 unused entries |
1927 |
at the beginning, and we don't want garbage. */ |
at the beginning, and we don't want garbage. */ |
1928 |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); |
1929 |
if (s->contents == NULL && s->_raw_size != 0) |
if (s->contents == NULL && s->size != 0) |
1930 |
return false; |
return FALSE; |
1931 |
} |
} |
1932 |
|
|
1933 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (elf_hash_table (info)->dynamic_sections_created) |
1938 |
the .dynamic section. The DT_DEBUG entry is filled in by the |
the .dynamic section. The DT_DEBUG entry is filled in by the |
1939 |
dynamic linker and used by the debugger. */ |
dynamic linker and used by the debugger. */ |
1940 |
#define add_dynamic_entry(TAG, VAL) \ |
#define add_dynamic_entry(TAG, VAL) \ |
1941 |
bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) |
_bfd_elf_add_dynamic_entry (info, TAG, VAL) |
1942 |
|
|
1943 |
int reg; |
int reg; |
1944 |
struct sparc64_elf_app_reg * app_regs; |
struct sparc64_elf_app_reg * app_regs; |
1945 |
struct elf_strtab_hash *dynstr; |
struct elf_strtab_hash *dynstr; |
1946 |
struct elf_link_hash_table *eht = elf_hash_table (info); |
struct elf_link_hash_table *eht = elf_hash_table (info); |
1947 |
|
|
1948 |
if (!info->shared) |
if (info->executable) |
1949 |
{ |
{ |
1950 |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
1951 |
return false; |
return FALSE; |
1952 |
} |
} |
1953 |
|
|
1954 |
if (relplt) |
if (relplt) |
1957 |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
1958 |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
1959 |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
1960 |
return false; |
return FALSE; |
1961 |
} |
} |
1962 |
|
|
1963 |
if (!add_dynamic_entry (DT_RELA, 0) |
if (!add_dynamic_entry (DT_RELA, 0) |
1964 |
|| !add_dynamic_entry (DT_RELASZ, 0) |
|| !add_dynamic_entry (DT_RELASZ, 0) |
1965 |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) |
1966 |
return false; |
return FALSE; |
1967 |
|
|
1968 |
if (info->flags & DF_TEXTREL) |
if (info->flags & DF_TEXTREL) |
1969 |
{ |
{ |
1970 |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
1971 |
return false; |
return FALSE; |
1972 |
} |
} |
1973 |
|
|
1974 |
/* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER |
/* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER |
1982 |
struct elf_link_local_dynamic_entry *entry, *e; |
struct elf_link_local_dynamic_entry *entry, *e; |
1983 |
|
|
1984 |
if (!add_dynamic_entry (DT_SPARC_REGISTER, 0)) |
if (!add_dynamic_entry (DT_SPARC_REGISTER, 0)) |
1985 |
return false; |
return FALSE; |
1986 |
|
|
1987 |
entry = (struct elf_link_local_dynamic_entry *) |
entry = (struct elf_link_local_dynamic_entry *) |
1988 |
bfd_hash_allocate (&info->hash->table, sizeof (*entry)); |
bfd_hash_allocate (&info->hash->table, sizeof (*entry)); |
1989 |
if (entry == NULL) |
if (entry == NULL) |
1990 |
return false; |
return FALSE; |
1991 |
|
|
1992 |
/* We cheat here a little bit: the symbol will not be local, so we |
/* We cheat here a little bit: the symbol will not be local, so we |
1993 |
put it at the end of the dynlocal linked list. We will fix it |
put it at the end of the dynlocal linked list. We will fix it |
1996 |
entry->isym.st_size = 0; |
entry->isym.st_size = 0; |
1997 |
if (*app_regs [reg].name != '\0') |
if (*app_regs [reg].name != '\0') |
1998 |
entry->isym.st_name |
entry->isym.st_name |
1999 |
= _bfd_elf_strtab_add (dynstr, app_regs[reg].name, false); |
= _bfd_elf_strtab_add (dynstr, app_regs[reg].name, FALSE); |
2000 |
else |
else |
2001 |
entry->isym.st_name = 0; |
entry->isym.st_name = 0; |
2002 |
entry->isym.st_other = 0; |
entry->isym.st_other = 0; |
2020 |
} |
} |
2021 |
#undef add_dynamic_entry |
#undef add_dynamic_entry |
2022 |
|
|
2023 |
return true; |
return TRUE; |
2024 |
} |
} |
2025 |
|
|
2026 |
#define SET_SEC_DO_RELAX(section) do { elf_section_data(section)->tdata = (void *)1; } while (0) |
static bfd_boolean |
2027 |
#define SEC_DO_RELAX(section) (elf_section_data(section)->tdata == (void *)1) |
sparc64_elf_new_section_hook (abfd, sec) |
2028 |
|
bfd *abfd; |
2029 |
|
asection *sec; |
2030 |
|
{ |
2031 |
|
struct sparc64_elf_section_data *sdata; |
2032 |
|
bfd_size_type amt = sizeof (*sdata); |
2033 |
|
|
2034 |
|
sdata = (struct sparc64_elf_section_data *) bfd_zalloc (abfd, amt); |
2035 |
|
if (sdata == NULL) |
2036 |
|
return FALSE; |
2037 |
|
sec->used_by_bfd = (PTR) sdata; |
2038 |
|
|
2039 |
|
return _bfd_elf_new_section_hook (abfd, sec); |
2040 |
|
} |
2041 |
|
|
2042 |
static boolean |
static bfd_boolean |
2043 |
sparc64_elf_relax_section (abfd, section, link_info, again) |
sparc64_elf_relax_section (abfd, section, link_info, again) |
2044 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
2045 |
asection *section ATTRIBUTE_UNUSED; |
asection *section ATTRIBUTE_UNUSED; |
2046 |
struct bfd_link_info *link_info ATTRIBUTE_UNUSED; |
struct bfd_link_info *link_info ATTRIBUTE_UNUSED; |
2047 |
boolean *again; |
bfd_boolean *again; |
2048 |
{ |
{ |
2049 |
*again = false; |
*again = FALSE; |
2050 |
SET_SEC_DO_RELAX (section); |
sec_do_relax (section) = 1; |
2051 |
return true; |
return TRUE; |
2052 |
} |
} |
2053 |
|
|
|
/* This is the condition under which finish_dynamic_symbol will be called |
|
|
from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol |
|
|
routine, we'll need to do something about initializing any .plt and |
|
|
.got entries in relocate_section. */ |
|
|
#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ |
|
|
((DYN) \ |
|
|
&& ((INFO)->shared \ |
|
|
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ |
|
|
&& ((H)->dynindx != -1 \ |
|
|
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) |
|
|
|
|
2054 |
/* Relocate a SPARC64 ELF section. */ |
/* Relocate a SPARC64 ELF section. */ |
2055 |
|
|
2056 |
static boolean |
static bfd_boolean |
2057 |
sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
2058 |
contents, relocs, local_syms, local_sections) |
contents, relocs, local_syms, local_sections) |
2059 |
bfd *output_bfd; |
bfd *output_bfd; |
2076 |
Elf_Internal_Rela *rel; |
Elf_Internal_Rela *rel; |
2077 |
Elf_Internal_Rela *relend; |
Elf_Internal_Rela *relend; |
2078 |
|
|
2079 |
|
if (info->relocatable) |
2080 |
|
return TRUE; |
2081 |
|
|
2082 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
2083 |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
2084 |
sym_hashes = elf_sym_hashes (input_bfd); |
sym_hashes = elf_sym_hashes (input_bfd); |
2090 |
got_base = elf_hash_table (info)->hgot->root.u.def.value; |
got_base = elf_hash_table (info)->hgot->root.u.def.value; |
2091 |
|
|
2092 |
sgot = splt = sreloc = NULL; |
sgot = splt = sreloc = NULL; |
2093 |
|
if (dynobj != NULL) |
2094 |
|
splt = bfd_get_section_by_name (dynobj, ".plt"); |
2095 |
|
|
2096 |
rel = relocs; |
rel = relocs; |
2097 |
relend = relocs + NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr); |
relend = relocs + NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr); |
2105 |
asection *sec; |
asection *sec; |
2106 |
bfd_vma relocation, off; |
bfd_vma relocation, off; |
2107 |
bfd_reloc_status_type r; |
bfd_reloc_status_type r; |
2108 |
boolean is_plt = false; |
bfd_boolean is_plt = FALSE; |
2109 |
boolean unresolved_reloc; |
bfd_boolean unresolved_reloc; |
2110 |
|
|
2111 |
r_type = ELF64_R_TYPE_ID (rel->r_info); |
r_type = ELF64_R_TYPE_ID (rel->r_info); |
2112 |
if (r_type < 0 || r_type >= (int) R_SPARC_max_std) |
if (r_type < 0 || r_type >= (int) R_SPARC_max_std) |
2113 |
{ |
{ |
2114 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
2115 |
return false; |
return FALSE; |
2116 |
} |
} |
2117 |
howto = sparc64_elf_howto_table + r_type; |
howto = sparc64_elf_howto_table + r_type; |
2118 |
|
|
|
r_symndx = ELF64_R_SYM (rel->r_info); |
|
|
|
|
|
if (info->relocateable) |
|
|
{ |
|
|
/* This is a relocateable link. We don't have to change |
|
|
anything, unless the reloc is against a section symbol, |
|
|
in which case we have to adjust according to where the |
|
|
section symbol winds up in the output section. */ |
|
|
if (r_symndx < symtab_hdr->sh_info) |
|
|
{ |
|
|
sym = local_syms + r_symndx; |
|
|
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) |
|
|
{ |
|
|
sec = local_sections[r_symndx]; |
|
|
rel->r_addend += sec->output_offset + sym->st_value; |
|
|
} |
|
|
} |
|
|
|
|
|
continue; |
|
|
} |
|
|
|
|
2119 |
/* This is a final link. */ |
/* This is a final link. */ |
2120 |
|
r_symndx = ELF64_R_SYM (rel->r_info); |
2121 |
h = NULL; |
h = NULL; |
2122 |
sym = NULL; |
sym = NULL; |
2123 |
sec = NULL; |
sec = NULL; |
2124 |
unresolved_reloc = false; |
unresolved_reloc = FALSE; |
2125 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
2126 |
{ |
{ |
2127 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
2128 |
sec = local_sections[r_symndx]; |
sec = local_sections[r_symndx]; |
2129 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
2130 |
} |
} |
2131 |
else |
else |
2132 |
{ |
{ |
2133 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
bfd_boolean warned; |
|
while (h->root.type == bfd_link_hash_indirect |
|
|
|| h->root.type == bfd_link_hash_warning) |
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
2134 |
|
|
2135 |
relocation = 0; |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
2136 |
if (h->root.type == bfd_link_hash_defined |
r_symndx, symtab_hdr, sym_hashes, |
2137 |
|| h->root.type == bfd_link_hash_defweak) |
h, sec, relocation, |
2138 |
|
unresolved_reloc, warned); |
2139 |
|
if (warned) |
2140 |
{ |
{ |
|
sec = h->root.u.def.section; |
|
|
if (sec->output_section == NULL) |
|
|
/* Set a flag that will be cleared later if we find a |
|
|
relocation value for this symbol. output_section |
|
|
is typically NULL for symbols satisfied by a shared |
|
|
library. */ |
|
|
unresolved_reloc = true; |
|
|
else |
|
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
; |
|
|
else if (info->shared |
|
|
&& (!info->symbolic || info->allow_shlib_undefined) |
|
|
&& !info->no_undefined |
|
|
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) |
|
|
; |
|
|
else |
|
|
{ |
|
|
if (! ((*info->callbacks->undefined_symbol) |
|
|
(info, h->root.root.string, input_bfd, |
|
|
input_section, rel->r_offset, |
|
|
(!info->shared || info->no_undefined |
|
|
|| ELF_ST_VISIBILITY (h->other))))) |
|
|
return false; |
|
|
|
|
2141 |
/* To avoid generating warning messages about truncated |
/* To avoid generating warning messages about truncated |
2142 |
relocations, set the relocation's address to be the same as |
relocations, set the relocation's address to be the same as |
2143 |
the start of this section. */ |
the start of this section. */ |
|
|
|
2144 |
if (input_section->output_section != NULL) |
if (input_section->output_section != NULL) |
2145 |
relocation = input_section->output_section->vma; |
relocation = input_section->output_section->vma; |
2146 |
else |
else |
2202 |
case R_SPARC_UA16: |
case R_SPARC_UA16: |
2203 |
{ |
{ |
2204 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
2205 |
boolean skip, relocate; |
bfd_byte *loc; |
2206 |
|
bfd_boolean skip, relocate; |
2207 |
|
|
2208 |
if (sreloc == NULL) |
if (sreloc == NULL) |
2209 |
{ |
{ |
2214 |
elf_section_data (input_section)->rel_hdr.sh_name)); |
elf_section_data (input_section)->rel_hdr.sh_name)); |
2215 |
|
|
2216 |
if (name == NULL) |
if (name == NULL) |
2217 |
return false; |
return FALSE; |
2218 |
|
|
2219 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
2220 |
&& strcmp (bfd_get_section_name(input_bfd, |
&& strcmp (bfd_get_section_name(input_bfd, |
2225 |
BFD_ASSERT (sreloc != NULL); |
BFD_ASSERT (sreloc != NULL); |
2226 |
} |
} |
2227 |
|
|
2228 |
skip = false; |
skip = FALSE; |
2229 |
relocate = false; |
relocate = FALSE; |
2230 |
|
|
2231 |
outrel.r_offset = |
outrel.r_offset = |
2232 |
_bfd_elf_section_offset (output_bfd, info, input_section, |
_bfd_elf_section_offset (output_bfd, info, input_section, |
2233 |
rel->r_offset); |
rel->r_offset); |
2234 |
if (outrel.r_offset == (bfd_vma) -1) |
if (outrel.r_offset == (bfd_vma) -1) |
2235 |
skip = true; |
skip = TRUE; |
2236 |
else if (outrel.r_offset == (bfd_vma) -2) |
else if (outrel.r_offset == (bfd_vma) -2) |
2237 |
skip = true, relocate = true; |
skip = TRUE, relocate = TRUE; |
2238 |
|
|
2239 |
outrel.r_offset += (input_section->output_section->vma |
outrel.r_offset += (input_section->output_section->vma |
2240 |
+ input_section->output_offset); |
+ input_section->output_offset); |
2271 |
FIXME: Add code tracking needed dynamic relocs as |
FIXME: Add code tracking needed dynamic relocs as |
2272 |
e.g. i386 has. */ |
e.g. i386 has. */ |
2273 |
if (h->dynindx == -1) |
if (h->dynindx == -1) |
2274 |
skip = true, relocate = true; |
skip = TRUE, relocate = TRUE; |
2275 |
break; |
break; |
2276 |
} |
} |
2277 |
|
|
2278 |
|
/* FIXME: Dynamic reloc handling really needs to be rewritten. */ |
2279 |
|
if (!skip |
2280 |
|
&& h != NULL |
2281 |
|
&& ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
2282 |
|
&& h->root.type == bfd_link_hash_undefweak) |
2283 |
|
skip = TRUE, relocate = TRUE; |
2284 |
|
|
2285 |
if (skip) |
if (skip) |
2286 |
memset (&outrel, 0, sizeof outrel); |
memset (&outrel, 0, sizeof outrel); |
2287 |
/* h->dynindx may be -1 if the symbol was marked to |
/* h->dynindx may be -1 if the symbol was marked to |
2288 |
become local. */ |
become local. */ |
2289 |
else if (h != NULL && ! is_plt |
else if (h != NULL && ! is_plt |
2290 |
&& ((! info->symbolic && h->dynindx != -1) |
&& ((! info->symbolic && h->dynindx != -1) |
2291 |
|| (h->elf_link_hash_flags |
|| !h->def_regular)) |
|
& ELF_LINK_HASH_DEF_REGULAR) == 0)) |
|
2292 |
{ |
{ |
2293 |
BFD_ASSERT (h->dynindx != -1); |
BFD_ASSERT (h->dynindx != -1); |
2294 |
outrel.r_info |
outrel.r_info |
2300 |
} |
} |
2301 |
else |
else |
2302 |
{ |
{ |
2303 |
|
outrel.r_addend = relocation + rel->r_addend; |
2304 |
if (r_type == R_SPARC_64) |
if (r_type == R_SPARC_64) |
2305 |
{ |
outrel.r_info = ELF64_R_INFO (0, R_SPARC_RELATIVE); |
|
outrel.r_info = ELF64_R_INFO (0, R_SPARC_RELATIVE); |
|
|
outrel.r_addend = relocation + rel->r_addend; |
|
|
} |
|
2306 |
else |
else |
2307 |
{ |
{ |
2308 |
long indx; |
long indx; |
2309 |
|
|
2310 |
if (is_plt) |
if (is_plt) |
2311 |
sec = splt; |
sec = splt; |
2312 |
else if (h == NULL) |
|
2313 |
sec = local_sections[r_symndx]; |
if (bfd_is_abs_section (sec)) |
|
else |
|
|
{ |
|
|
BFD_ASSERT (h->root.type == bfd_link_hash_defined |
|
|
|| (h->root.type |
|
|
== bfd_link_hash_defweak)); |
|
|
sec = h->root.u.def.section; |
|
|
} |
|
|
if (sec != NULL && bfd_is_abs_section (sec)) |
|
2314 |
indx = 0; |
indx = 0; |
2315 |
else if (sec == NULL || sec->owner == NULL) |
else if (sec == NULL || sec->owner == NULL) |
2316 |
{ |
{ |
2317 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
2318 |
return false; |
return FALSE; |
2319 |
} |
} |
2320 |
else |
else |
2321 |
{ |
{ |
2324 |
osec = sec->output_section; |
osec = sec->output_section; |
2325 |
indx = elf_section_data (osec)->dynindx; |
indx = elf_section_data (osec)->dynindx; |
2326 |
|
|
2327 |
|
/* We are turning this relocation into one |
2328 |
|
against a section symbol, so subtract out |
2329 |
|
the output section's address but not the |
2330 |
|
offset of the input section in the output |
2331 |
|
section. */ |
2332 |
|
outrel.r_addend -= osec->vma; |
2333 |
|
|
2334 |
/* FIXME: we really should be able to link non-pic |
/* FIXME: we really should be able to link non-pic |
2335 |
shared libraries. */ |
shared libraries. */ |
2336 |
if (indx == 0) |
if (indx == 0) |
2337 |
{ |
{ |
2338 |
BFD_FAIL (); |
BFD_FAIL (); |
2339 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2340 |
(_("%s: probably compiled without -fPIC?"), |
(_("%B: probably compiled without -fPIC?"), |
2341 |
bfd_archive_filename (input_bfd)); |
input_bfd); |
2342 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
2343 |
return false; |
return FALSE; |
2344 |
} |
} |
2345 |
} |
} |
2346 |
|
|
2349 |
ELF64_R_TYPE_INFO ( |
ELF64_R_TYPE_INFO ( |
2350 |
ELF64_R_TYPE_DATA (rel->r_info), |
ELF64_R_TYPE_DATA (rel->r_info), |
2351 |
r_type)); |
r_type)); |
|
outrel.r_addend = relocation + rel->r_addend; |
|
2352 |
} |
} |
2353 |
} |
} |
2354 |
|
|
2355 |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, |
loc = sreloc->contents; |
2356 |
(((Elf64_External_Rela *) |
loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); |
2357 |
sreloc->contents) |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
|
+ sreloc->reloc_count)); |
|
|
++sreloc->reloc_count; |
|
2358 |
|
|
2359 |
/* This reloc will be computed at runtime, so there's no |
/* This reloc will be computed at runtime, so there's no |
2360 |
need to do anything now. */ |
need to do anything now. */ |
2374 |
offset table. */ |
offset table. */ |
2375 |
if (sgot == NULL) |
if (sgot == NULL) |
2376 |
{ |
{ |
2377 |
sgot = bfd_get_section_by_name (dynobj, ".got"); |
sgot = sparc64_elf_hash_table (info)->sgot; |
2378 |
BFD_ASSERT (sgot != NULL); |
BFD_ASSERT (sgot != NULL); |
2379 |
} |
} |
2380 |
|
|
2381 |
if (h != NULL) |
if (h != NULL) |
2382 |
{ |
{ |
2383 |
boolean dyn; |
bfd_boolean dyn; |
2384 |
|
|
2385 |
off = h->got.offset; |
off = h->got.offset; |
2386 |
BFD_ASSERT (off != (bfd_vma) -1); |
BFD_ASSERT (off != (bfd_vma) -1); |
2387 |
dyn = elf_hash_table (info)->dynamic_sections_created; |
dyn = elf_hash_table (info)->dynamic_sections_created; |
2388 |
|
|
2389 |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
2390 |
|| (info->shared |
|| (info->shared |
2391 |
&& (info->symbolic |
&& (info->symbolic |
2392 |
|| h->dynindx == -1 |
|| h->dynindx == -1 |
2393 |
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) |
|| h->forced_local) |
2394 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) |
&& h->def_regular)) |
2395 |
{ |
{ |
2396 |
/* This is actually a static link, or it is a -Bsymbolic |
/* This is actually a static link, or it is a -Bsymbolic |
2397 |
link and the symbol is defined locally, or the symbol |
link and the symbol is defined locally, or the symbol |
2415 |
} |
} |
2416 |
} |
} |
2417 |
else |
else |
2418 |
unresolved_reloc = false; |
unresolved_reloc = FALSE; |
2419 |
} |
} |
2420 |
else |
else |
2421 |
{ |
{ |
2434 |
|
|
2435 |
if (info->shared) |
if (info->shared) |
2436 |
{ |
{ |
2437 |
asection *srelgot; |
asection *s; |
2438 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
2439 |
|
bfd_byte *loc; |
2440 |
|
|
2441 |
/* The Solaris 2.7 64-bit linker adds the contents |
/* The Solaris 2.7 64-bit linker adds the contents |
2442 |
of the location to the value of the reloc. |
of the location to the value of the reloc. |
2448 |
|
|
2449 |
/* We need to generate a R_SPARC_RELATIVE reloc |
/* We need to generate a R_SPARC_RELATIVE reloc |
2450 |
for the dynamic linker. */ |
for the dynamic linker. */ |
2451 |
srelgot = bfd_get_section_by_name(dynobj, ".rela.got"); |
s = sparc64_elf_hash_table (info)->srelgot; |
2452 |
BFD_ASSERT (srelgot != NULL); |
BFD_ASSERT (s != NULL); |
2453 |
|
|
2454 |
outrel.r_offset = (sgot->output_section->vma |
outrel.r_offset = (sgot->output_section->vma |
2455 |
+ sgot->output_offset |
+ sgot->output_offset |
2456 |
+ off); |
+ off); |
2457 |
outrel.r_info = ELF64_R_INFO (0, R_SPARC_RELATIVE); |
outrel.r_info = ELF64_R_INFO (0, R_SPARC_RELATIVE); |
2458 |
outrel.r_addend = relocation; |
outrel.r_addend = relocation; |
2459 |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, |
loc = s->contents; |
2460 |
(((Elf64_External_Rela *) |
loc += s->reloc_count++ * sizeof (Elf64_External_Rela); |
2461 |
srelgot->contents) |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
|
+ srelgot->reloc_count)); |
|
|
++srelgot->reloc_count; |
|
2462 |
} |
} |
2463 |
else |
else |
2464 |
bfd_put_64 (output_bfd, relocation, sgot->contents + off); |
bfd_put_64 (output_bfd, relocation, sgot->contents + off); |
2479 |
procedure linkage table. */ |
procedure linkage table. */ |
2480 |
BFD_ASSERT (h != NULL); |
BFD_ASSERT (h != NULL); |
2481 |
|
|
2482 |
if (h->plt.offset == (bfd_vma) -1) |
if (h->plt.offset == (bfd_vma) -1 || splt == NULL) |
2483 |
{ |
{ |
2484 |
/* We didn't make a PLT entry for this symbol. This |
/* We didn't make a PLT entry for this symbol. This |
2485 |
happens when statically linking PIC code, or when |
happens when statically linking PIC code, or when |
2487 |
goto do_default; |
goto do_default; |
2488 |
} |
} |
2489 |
|
|
|
if (splt == NULL) |
|
|
{ |
|
|
splt = bfd_get_section_by_name (dynobj, ".plt"); |
|
|
BFD_ASSERT (splt != NULL); |
|
|
} |
|
|
|
|
2490 |
relocation = (splt->output_section->vma |
relocation = (splt->output_section->vma |
2491 |
+ splt->output_offset |
+ splt->output_offset |
2492 |
+ sparc64_elf_plt_entry_offset (h->plt.offset)); |
+ sparc64_elf_plt_entry_offset (h->plt.offset)); |
2493 |
unresolved_reloc = false; |
unresolved_reloc = FALSE; |
2494 |
if (r_type == R_SPARC_WPLT30) |
if (r_type == R_SPARC_WPLT30) |
2495 |
goto do_wplt30; |
goto do_wplt30; |
2496 |
if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64) |
if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64) |
2497 |
{ |
{ |
2498 |
r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64; |
r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64; |
2499 |
is_plt = true; |
is_plt = TRUE; |
2500 |
goto do_dynreloc; |
goto do_dynreloc; |
2501 |
} |
} |
2502 |
goto do_default; |
goto do_default; |
2577 |
|
|
2578 |
case R_SPARC_WDISP30: |
case R_SPARC_WDISP30: |
2579 |
do_wplt30: |
do_wplt30: |
2580 |
if (SEC_DO_RELAX (input_section) |
if (sec_do_relax (input_section) |
2581 |
&& rel->r_offset + 4 < input_section->_raw_size) |
&& rel->r_offset + 4 < input_section->size) |
2582 |
{ |
{ |
2583 |
#define G0 0 |
#define G0 0 |
2584 |
#define O7 15 |
#define O7 15 |
2664 |
} |
} |
2665 |
} |
} |
2666 |
} |
} |
2667 |
/* FALLTHROUGH */ |
/* Fall through. */ |
2668 |
|
|
2669 |
default: |
default: |
2670 |
do_default: |
do_default: |
2679 |
not process them. */ |
not process them. */ |
2680 |
if (unresolved_reloc |
if (unresolved_reloc |
2681 |
&& !((input_section->flags & SEC_DEBUGGING) != 0 |
&& !((input_section->flags & SEC_DEBUGGING) != 0 |
2682 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) |
&& h->def_dynamic)) |
2683 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2684 |
(_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), |
(_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"), |
2685 |
bfd_archive_filename (input_bfd), |
input_bfd, input_section, |
|
bfd_get_section_name (input_bfd, input_section), |
|
2686 |
(long) rel->r_offset, |
(long) rel->r_offset, |
2687 |
h->root.root.string); |
h->root.root.string); |
2688 |
|
|
2702 |
/* The Solaris native linker silently disregards |
/* The Solaris native linker silently disregards |
2703 |
overflows. We don't, but this breaks stabs debugging |
overflows. We don't, but this breaks stabs debugging |
2704 |
info, whose relocations are only 32-bits wide. Ignore |
info, whose relocations are only 32-bits wide. Ignore |
2705 |
overflows in this case. */ |
overflows in this case and also for discarded entries. */ |
2706 |
if (r_type == R_SPARC_32 |
if ((r_type == R_SPARC_32 || r_type == R_SPARC_DISP32) |
2707 |
&& (input_section->flags & SEC_DEBUGGING) != 0 |
&& (((input_section->flags & SEC_DEBUGGING) != 0 |
2708 |
&& strcmp (bfd_section_name (input_bfd, input_section), |
&& strcmp (bfd_section_name (input_bfd, input_section), |
2709 |
".stab") == 0) |
".stab") == 0) |
2710 |
|
|| _bfd_elf_section_offset (output_bfd, info, |
2711 |
|
input_section, |
2712 |
|
rel->r_offset) == (bfd_vma)-1)) |
2713 |
break; |
break; |
2714 |
|
|
2715 |
if (h != NULL) |
if (h != NULL) |
2725 |
break; |
break; |
2726 |
} |
} |
2727 |
|
|
2728 |
name = h->root.root.string; |
name = NULL; |
2729 |
} |
} |
2730 |
else |
else |
2731 |
{ |
{ |
2734 |
symtab_hdr->sh_link, |
symtab_hdr->sh_link, |
2735 |
sym->st_name)); |
sym->st_name)); |
2736 |
if (name == NULL) |
if (name == NULL) |
2737 |
return false; |
return FALSE; |
2738 |
if (*name == '\0') |
if (*name == '\0') |
2739 |
name = bfd_section_name (input_bfd, sec); |
name = bfd_section_name (input_bfd, sec); |
2740 |
} |
} |
2741 |
if (! ((*info->callbacks->reloc_overflow) |
if (! ((*info->callbacks->reloc_overflow) |
2742 |
(info, name, howto->name, (bfd_vma) 0, |
(info, (h ? &h->root : NULL), name, howto->name, |
2743 |
input_bfd, input_section, rel->r_offset))) |
(bfd_vma) 0, input_bfd, input_section, |
2744 |
return false; |
rel->r_offset))) |
2745 |
|
return FALSE; |
2746 |
} |
} |
2747 |
break; |
break; |
2748 |
} |
} |
2749 |
} |
} |
2750 |
|
|
2751 |
return true; |
return TRUE; |
2752 |
} |
} |
2753 |
|
|
2754 |
/* Finish up dynamic symbol handling. We set the contents of various |
/* Finish up dynamic symbol handling. We set the contents of various |
2755 |
dynamic sections here. */ |
dynamic sections here. */ |
2756 |
|
|
2757 |
static boolean |
static bfd_boolean |
2758 |
sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) |
sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) |
2759 |
bfd *output_bfd; |
bfd *output_bfd; |
2760 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
2770 |
asection *splt; |
asection *splt; |
2771 |
asection *srela; |
asection *srela; |
2772 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
2773 |
|
bfd_byte *loc; |
2774 |
|
|
2775 |
/* This symbol has an entry in the PLT. Set it up. */ |
/* This symbol has an entry in the PLT. Set it up. */ |
2776 |
|
|
2789 |
} |
} |
2790 |
else |
else |
2791 |
{ |
{ |
2792 |
bfd_vma max = splt->_raw_size / PLT_ENTRY_SIZE; |
bfd_vma max = splt->size / PLT_ENTRY_SIZE; |
2793 |
rela.r_offset = sparc64_elf_plt_ptr_offset (h->plt.offset, max); |
rela.r_offset = sparc64_elf_plt_ptr_offset (h->plt.offset, max); |
2794 |
rela.r_addend = -(sparc64_elf_plt_entry_offset (h->plt.offset) + 4) |
rela.r_addend = -(sparc64_elf_plt_entry_offset (h->plt.offset) + 4) |
2795 |
-(splt->output_section->vma + splt->output_offset); |
-(splt->output_section->vma + splt->output_offset); |
2802 |
Sun forgot to read their own ABI and copied elf32-sparc behaviour, |
Sun forgot to read their own ABI and copied elf32-sparc behaviour, |
2803 |
thus .plt[4] has corresponding .rela.plt[0] and so on. */ |
thus .plt[4] has corresponding .rela.plt[0] and so on. */ |
2804 |
|
|
2805 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, |
loc = srela->contents; |
2806 |
((Elf64_External_Rela *) srela->contents |
loc += (h->plt.offset - 4) * sizeof (Elf64_External_Rela); |
2807 |
+ (h->plt.offset - 4))); |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
2808 |
|
|
2809 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
if (!h->def_regular) |
2810 |
{ |
{ |
2811 |
/* Mark the symbol as undefined, rather than as defined in |
/* Mark the symbol as undefined, rather than as defined in |
2812 |
the .plt section. Leave the value alone. */ |
the .plt section. Leave the value alone. */ |
2815 |
Otherwise, the PLT entry would provide a definition for |
Otherwise, the PLT entry would provide a definition for |
2816 |
the symbol even if the symbol wasn't defined anywhere, |
the symbol even if the symbol wasn't defined anywhere, |
2817 |
and so the symbol would never be NULL. */ |
and so the symbol would never be NULL. */ |
2818 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) |
if (!h->ref_regular_nonweak) |
|
== 0) |
|
2819 |
sym->st_value = 0; |
sym->st_value = 0; |
2820 |
} |
} |
2821 |
} |
} |
2825 |
asection *sgot; |
asection *sgot; |
2826 |
asection *srela; |
asection *srela; |
2827 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
2828 |
|
bfd_byte *loc; |
2829 |
|
|
2830 |
/* This symbol has an entry in the GOT. Set it up. */ |
/* This symbol has an entry in the GOT. Set it up. */ |
2831 |
|
|
2832 |
sgot = bfd_get_section_by_name (dynobj, ".got"); |
sgot = sparc64_elf_hash_table (info)->sgot; |
2833 |
srela = bfd_get_section_by_name (dynobj, ".rela.got"); |
srela = sparc64_elf_hash_table (info)->srelgot; |
2834 |
BFD_ASSERT (sgot != NULL && srela != NULL); |
BFD_ASSERT (sgot != NULL && srela != NULL); |
2835 |
|
|
2836 |
rela.r_offset = (sgot->output_section->vma |
rela.r_offset = (sgot->output_section->vma |
2844 |
initialized in the relocate_section function. */ |
initialized in the relocate_section function. */ |
2845 |
if (info->shared |
if (info->shared |
2846 |
&& (info->symbolic || h->dynindx == -1) |
&& (info->symbolic || h->dynindx == -1) |
2847 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) |
&& h->def_regular) |
2848 |
{ |
{ |
2849 |
asection *sec = h->root.u.def.section; |
asection *sec = h->root.u.def.section; |
2850 |
rela.r_info = ELF64_R_INFO (0, R_SPARC_RELATIVE); |
rela.r_info = ELF64_R_INFO (0, R_SPARC_RELATIVE); |
2854 |
} |
} |
2855 |
else |
else |
2856 |
{ |
{ |
|
bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); |
|
2857 |
rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_GLOB_DAT); |
rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_GLOB_DAT); |
2858 |
rela.r_addend = 0; |
rela.r_addend = 0; |
2859 |
} |
} |
2860 |
|
|
2861 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, |
bfd_put_64 (output_bfd, (bfd_vma) 0, |
2862 |
((Elf64_External_Rela *) srela->contents |
sgot->contents + (h->got.offset &~ (bfd_vma) 1)); |
2863 |
+ srela->reloc_count)); |
loc = srela->contents; |
2864 |
++srela->reloc_count; |
loc += srela->reloc_count++ * sizeof (Elf64_External_Rela); |
2865 |
|
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
2866 |
} |
} |
2867 |
|
|
2868 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) |
if (h->needs_copy) |
2869 |
{ |
{ |
2870 |
asection *s; |
asection *s; |
2871 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
2872 |
|
bfd_byte *loc; |
2873 |
|
|
2874 |
/* This symbols needs a copy reloc. Set it up. */ |
/* This symbols needs a copy reloc. Set it up. */ |
|
|
|
2875 |
BFD_ASSERT (h->dynindx != -1); |
BFD_ASSERT (h->dynindx != -1); |
2876 |
|
|
2877 |
s = bfd_get_section_by_name (h->root.u.def.section->owner, |
s = bfd_get_section_by_name (h->root.u.def.section->owner, |
2883 |
+ h->root.u.def.section->output_offset); |
+ h->root.u.def.section->output_offset); |
2884 |
rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_COPY); |
rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_COPY); |
2885 |
rela.r_addend = 0; |
rela.r_addend = 0; |
2886 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, |
loc = s->contents + s->reloc_count++ * sizeof (Elf64_External_Rela); |
2887 |
((Elf64_External_Rela *) s->contents |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
|
+ s->reloc_count)); |
|
|
++s->reloc_count; |
|
2888 |
} |
} |
2889 |
|
|
2890 |
/* Mark some specially defined symbols as absolute. */ |
/* Mark some specially defined symbols as absolute. */ |
2893 |
|| strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) |
|| strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) |
2894 |
sym->st_shndx = SHN_ABS; |
sym->st_shndx = SHN_ABS; |
2895 |
|
|
2896 |
return true; |
return TRUE; |
2897 |
} |
} |
2898 |
|
|
2899 |
/* Finish up the dynamic sections. */ |
/* Finish up the dynamic sections. */ |
2900 |
|
|
2901 |
static boolean |
static bfd_boolean |
2902 |
sparc64_elf_finish_dynamic_sections (output_bfd, info) |
sparc64_elf_finish_dynamic_sections (output_bfd, info) |
2903 |
bfd *output_bfd; |
bfd *output_bfd; |
2904 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
2921 |
BFD_ASSERT (splt != NULL && sdyn != NULL); |
BFD_ASSERT (splt != NULL && sdyn != NULL); |
2922 |
|
|
2923 |
dyncon = (Elf64_External_Dyn *) sdyn->contents; |
dyncon = (Elf64_External_Dyn *) sdyn->contents; |
2924 |
dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); |
dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); |
2925 |
for (; dyncon < dynconend; dyncon++) |
for (; dyncon < dynconend; dyncon++) |
2926 |
{ |
{ |
2927 |
Elf_Internal_Dyn dyn; |
Elf_Internal_Dyn dyn; |
2928 |
const char *name; |
const char *name; |
2929 |
boolean size; |
bfd_boolean size; |
2930 |
|
|
2931 |
bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); |
bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); |
2932 |
|
|
2933 |
switch (dyn.d_tag) |
switch (dyn.d_tag) |
2934 |
{ |
{ |
2935 |
case DT_PLTGOT: name = ".plt"; size = false; break; |
case DT_PLTGOT: name = ".plt"; size = FALSE; break; |
2936 |
case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; |
case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break; |
2937 |
case DT_JMPREL: name = ".rela.plt"; size = false; break; |
case DT_JMPREL: name = ".rela.plt"; size = FALSE; break; |
2938 |
case DT_SPARC_REGISTER: |
case DT_SPARC_REGISTER: |
2939 |
if (stt_regidx == -1) |
if (stt_regidx == -1) |
2940 |
{ |
{ |
2941 |
stt_regidx = |
stt_regidx = |
2942 |
_bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1); |
_bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1); |
2943 |
if (stt_regidx == -1) |
if (stt_regidx == -1) |
2944 |
return false; |
return FALSE; |
2945 |
} |
} |
2946 |
dyn.d_un.d_val = stt_regidx++; |
dyn.d_un.d_val = stt_regidx++; |
2947 |
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); |
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); |
2948 |
/* fallthrough */ |
/* fallthrough */ |
2949 |
default: name = NULL; size = false; break; |
default: name = NULL; size = FALSE; break; |
2950 |
} |
} |
2951 |
|
|
2952 |
if (name != NULL) |
if (name != NULL) |
2961 |
if (! size) |
if (! size) |
2962 |
dyn.d_un.d_ptr = s->vma; |
dyn.d_un.d_ptr = s->vma; |
2963 |
else |
else |
2964 |
{ |
dyn.d_un.d_val = s->size; |
|
if (s->_cooked_size != 0) |
|
|
dyn.d_un.d_val = s->_cooked_size; |
|
|
else |
|
|
dyn.d_un.d_val = s->_raw_size; |
|
|
} |
|
2965 |
} |
} |
2966 |
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); |
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); |
2967 |
} |
} |
2968 |
} |
} |
2969 |
|
|
2970 |
/* Initialize the contents of the .plt section. */ |
/* Initialize the contents of the .plt section. */ |
2971 |
if (splt->_raw_size > 0) |
if (splt->size > 0) |
2972 |
{ |
sparc64_elf_build_plt (output_bfd, splt->contents, |
2973 |
sparc64_elf_build_plt (output_bfd, splt->contents, |
(int) (splt->size / PLT_ENTRY_SIZE)); |
|
(int) (splt->_raw_size / PLT_ENTRY_SIZE)); |
|
|
} |
|
2974 |
|
|
2975 |
elf_section_data (splt->output_section)->this_hdr.sh_entsize = |
elf_section_data (splt->output_section)->this_hdr.sh_entsize = |
2976 |
PLT_ENTRY_SIZE; |
PLT_ENTRY_SIZE; |
2978 |
|
|
2979 |
/* Set the first entry in the global offset table to the address of |
/* Set the first entry in the global offset table to the address of |
2980 |
the dynamic section. */ |
the dynamic section. */ |
2981 |
sgot = bfd_get_section_by_name (dynobj, ".got"); |
sgot = sparc64_elf_hash_table (info)->sgot; |
2982 |
BFD_ASSERT (sgot != NULL); |
BFD_ASSERT (sgot != NULL); |
2983 |
if (sgot->_raw_size > 0) |
if (sgot->size > 0) |
2984 |
{ |
{ |
2985 |
if (sdyn == NULL) |
if (sdyn == NULL) |
2986 |
bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents); |
bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents); |
2992 |
|
|
2993 |
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8; |
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8; |
2994 |
|
|
2995 |
return true; |
return TRUE; |
2996 |
} |
} |
2997 |
|
|
2998 |
static enum elf_reloc_type_class |
static enum elf_reloc_type_class |
3017 |
/* Merge backend specific data from an object file to the output |
/* Merge backend specific data from an object file to the output |
3018 |
object file when linking. */ |
object file when linking. */ |
3019 |
|
|
3020 |
static boolean |
static bfd_boolean |
3021 |
sparc64_elf_merge_private_bfd_data (ibfd, obfd) |
sparc64_elf_merge_private_bfd_data (ibfd, obfd) |
3022 |
bfd *ibfd; |
bfd *ibfd; |
3023 |
bfd *obfd; |
bfd *obfd; |
3024 |
{ |
{ |
3025 |
boolean error; |
bfd_boolean error; |
3026 |
flagword new_flags, old_flags; |
flagword new_flags, old_flags; |
3027 |
int new_mm, old_mm; |
int new_mm, old_mm; |
3028 |
|
|
3029 |
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
3030 |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
3031 |
return true; |
return TRUE; |
3032 |
|
|
3033 |
new_flags = elf_elfheader (ibfd)->e_flags; |
new_flags = elf_elfheader (ibfd)->e_flags; |
3034 |
old_flags = elf_elfheader (obfd)->e_flags; |
old_flags = elf_elfheader (obfd)->e_flags; |
3035 |
|
|
3036 |
if (!elf_flags_init (obfd)) /* First call, no flags set */ |
if (!elf_flags_init (obfd)) /* First call, no flags set */ |
3037 |
{ |
{ |
3038 |
elf_flags_init (obfd) = true; |
elf_flags_init (obfd) = TRUE; |
3039 |
elf_elfheader (obfd)->e_flags = new_flags; |
elf_elfheader (obfd)->e_flags = new_flags; |
3040 |
} |
} |
3041 |
|
|
3044 |
|
|
3045 |
else /* Incompatible flags */ |
else /* Incompatible flags */ |
3046 |
{ |
{ |
3047 |
error = false; |
error = FALSE; |
3048 |
|
|
3049 |
#define EF_SPARC_ISA_EXTENSIONS \ |
#define EF_SPARC_ISA_EXTENSIONS \ |
3050 |
(EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1) |
(EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1) |
3066 |
if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3)) |
if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3)) |
3067 |
&& (old_flags & EF_SPARC_HAL_R1)) |
&& (old_flags & EF_SPARC_HAL_R1)) |
3068 |
{ |
{ |
3069 |
error = true; |
error = TRUE; |
3070 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
3071 |
(_("%s: linking UltraSPARC specific with HAL specific code"), |
(_("%B: linking UltraSPARC specific with HAL specific code"), |
3072 |
bfd_archive_filename (ibfd)); |
ibfd); |
3073 |
} |
} |
3074 |
/* Choose the most restrictive memory ordering. */ |
/* Choose the most restrictive memory ordering. */ |
3075 |
old_mm = (old_flags & EF_SPARCV9_MM); |
old_mm = (old_flags & EF_SPARCV9_MM); |
3085 |
/* Warn about any other mismatches */ |
/* Warn about any other mismatches */ |
3086 |
if (new_flags != old_flags) |
if (new_flags != old_flags) |
3087 |
{ |
{ |
3088 |
error = true; |
error = TRUE; |
3089 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
3090 |
(_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), |
(_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), |
3091 |
bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags); |
ibfd, (long) new_flags, (long) old_flags); |
3092 |
} |
} |
3093 |
|
|
3094 |
elf_elfheader (obfd)->e_flags = old_flags; |
elf_elfheader (obfd)->e_flags = old_flags; |
3096 |
if (error) |
if (error) |
3097 |
{ |
{ |
3098 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
3099 |
return false; |
return FALSE; |
3100 |
} |
} |
3101 |
} |
} |
3102 |
return true; |
return TRUE; |
3103 |
} |
} |
3104 |
|
|
3105 |
/* MARCO: Set the correct entry size for the .stab section. */ |
/* MARCO: Set the correct entry size for the .stab section. */ |
3106 |
|
|
3107 |
static boolean |
static bfd_boolean |
3108 |
sparc64_elf_fake_sections (abfd, hdr, sec) |
sparc64_elf_fake_sections (abfd, hdr, sec) |
3109 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
3110 |
Elf32_Internal_Shdr *hdr ATTRIBUTE_UNUSED; |
Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED; |
3111 |
asection *sec; |
asection *sec; |
3112 |
{ |
{ |
3113 |
const char *name; |
const char *name; |
3119 |
/* Even in the 64bit case the stab entries are only 12 bytes long. */ |
/* Even in the 64bit case the stab entries are only 12 bytes long. */ |
3120 |
elf_section_data (sec)->this_hdr.sh_entsize = 12; |
elf_section_data (sec)->this_hdr.sh_entsize = 12; |
3121 |
} |
} |
3122 |
|
|
3123 |
return true; |
return TRUE; |
3124 |
} |
} |
3125 |
|
|
3126 |
/* Print a STT_REGISTER symbol to file FILE. */ |
/* Print a STT_REGISTER symbol to file FILE. */ |
3153 |
|
|
3154 |
/* Set the right machine number for a SPARC64 ELF file. */ |
/* Set the right machine number for a SPARC64 ELF file. */ |
3155 |
|
|
3156 |
static boolean |
static bfd_boolean |
3157 |
sparc64_elf_object_p (abfd) |
sparc64_elf_object_p (abfd) |
3158 |
bfd *abfd; |
bfd *abfd; |
3159 |
{ |
{ |
3166 |
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, mach); |
return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, mach); |
3167 |
} |
} |
3168 |
|
|
3169 |
|
/* Return address for Ith PLT stub in section PLT, for relocation REL |
3170 |
|
or (bfd_vma) -1 if it should not be included. */ |
3171 |
|
|
3172 |
|
static bfd_vma |
3173 |
|
sparc64_elf_plt_sym_val (bfd_vma i, const asection *plt, |
3174 |
|
const arelent *rel ATTRIBUTE_UNUSED) |
3175 |
|
{ |
3176 |
|
bfd_vma j; |
3177 |
|
|
3178 |
|
i += PLT_HEADER_SIZE / PLT_ENTRY_SIZE; |
3179 |
|
if (i < LARGE_PLT_THRESHOLD) |
3180 |
|
return plt->vma + i * PLT_ENTRY_SIZE; |
3181 |
|
|
3182 |
|
j = (i - LARGE_PLT_THRESHOLD) % 160; |
3183 |
|
i -= j; |
3184 |
|
return plt->vma + i * PLT_ENTRY_SIZE + j * 4 * 6; |
3185 |
|
} |
3186 |
|
|
3187 |
/* Relocations in the 64 bit SPARC ELF ABI are more complex than in |
/* Relocations in the 64 bit SPARC ELF ABI are more complex than in |
3188 |
standard ELF, because R_SPARC_OLO10 has secondary addend in |
standard ELF, because R_SPARC_OLO10 has secondary addend in |
3189 |
ELF64_R_TYPE_DATA field. This structure is used to redirect the |
ELF64_R_TYPE_DATA field. This structure is used to redirect the |
3199 |
sizeof (Elf64_External_Sym), |
sizeof (Elf64_External_Sym), |
3200 |
sizeof (Elf64_External_Dyn), |
sizeof (Elf64_External_Dyn), |
3201 |
sizeof (Elf_External_Note), |
sizeof (Elf_External_Note), |
3202 |
4, /* hash-table entry size */ |
4, /* hash-table entry size. */ |
3203 |
/* internal relocations per external relocations. |
/* Internal relocations per external relocations. |
3204 |
For link purposes we use just 1 internal per |
For link purposes we use just 1 internal per |
3205 |
1 external, for assembly and slurp symbol table |
1 external, for assembly and slurp symbol table |
3206 |
we use 2. */ |
we use 2. */ |
3207 |
1, |
1, |
3208 |
64, /* arch_size */ |
64, /* arch_size. */ |
3209 |
8, /* file_align */ |
3, /* log_file_align. */ |
3210 |
ELFCLASS64, |
ELFCLASS64, |
3211 |
EV_CURRENT, |
EV_CURRENT, |
3212 |
bfd_elf64_write_out_phdrs, |
bfd_elf64_write_out_phdrs, |
3218 |
bfd_elf64_slurp_symbol_table, |
bfd_elf64_slurp_symbol_table, |
3219 |
bfd_elf64_swap_dyn_in, |
bfd_elf64_swap_dyn_in, |
3220 |
bfd_elf64_swap_dyn_out, |
bfd_elf64_swap_dyn_out, |
3221 |
NULL, |
bfd_elf64_swap_reloc_in, |
3222 |
NULL, |
bfd_elf64_swap_reloc_out, |
3223 |
NULL, |
bfd_elf64_swap_reloca_in, |
3224 |
NULL |
bfd_elf64_swap_reloca_out |
3225 |
}; |
}; |
3226 |
|
|
3227 |
#define TARGET_BIG_SYM bfd_elf64_sparc_vec |
#define TARGET_BIG_SYM bfd_elf64_sparc_vec |
3244 |
sparc64_elf_get_reloc_upper_bound |
sparc64_elf_get_reloc_upper_bound |
3245 |
#define bfd_elf64_get_dynamic_reloc_upper_bound \ |
#define bfd_elf64_get_dynamic_reloc_upper_bound \ |
3246 |
sparc64_elf_get_dynamic_reloc_upper_bound |
sparc64_elf_get_dynamic_reloc_upper_bound |
3247 |
|
#define bfd_elf64_canonicalize_reloc \ |
3248 |
|
sparc64_elf_canonicalize_reloc |
3249 |
#define bfd_elf64_canonicalize_dynamic_reloc \ |
#define bfd_elf64_canonicalize_dynamic_reloc \ |
3250 |
sparc64_elf_canonicalize_dynamic_reloc |
sparc64_elf_canonicalize_dynamic_reloc |
3251 |
#define bfd_elf64_bfd_reloc_type_lookup \ |
#define bfd_elf64_bfd_reloc_type_lookup \ |
3252 |
sparc64_elf_reloc_type_lookup |
sparc64_elf_reloc_type_lookup |
3253 |
#define bfd_elf64_bfd_relax_section \ |
#define bfd_elf64_bfd_relax_section \ |
3254 |
sparc64_elf_relax_section |
sparc64_elf_relax_section |
3255 |
|
#define bfd_elf64_new_section_hook \ |
3256 |
|
sparc64_elf_new_section_hook |
3257 |
|
|
3258 |
#define elf_backend_create_dynamic_sections \ |
#define elf_backend_create_dynamic_sections \ |
3259 |
_bfd_elf_create_dynamic_sections |
sparc64_elf_create_dynamic_sections |
3260 |
#define elf_backend_add_symbol_hook \ |
#define elf_backend_add_symbol_hook \ |
3261 |
sparc64_elf_add_symbol_hook |
sparc64_elf_add_symbol_hook |
3262 |
#define elf_backend_get_symbol_type \ |
#define elf_backend_get_symbol_type \ |
3267 |
sparc64_elf_check_relocs |
sparc64_elf_check_relocs |
3268 |
#define elf_backend_adjust_dynamic_symbol \ |
#define elf_backend_adjust_dynamic_symbol \ |
3269 |
sparc64_elf_adjust_dynamic_symbol |
sparc64_elf_adjust_dynamic_symbol |
3270 |
|
#define elf_backend_omit_section_dynsym \ |
3271 |
|
sparc64_elf_omit_section_dynsym |
3272 |
#define elf_backend_size_dynamic_sections \ |
#define elf_backend_size_dynamic_sections \ |
3273 |
sparc64_elf_size_dynamic_sections |
sparc64_elf_size_dynamic_sections |
3274 |
#define elf_backend_relocate_section \ |
#define elf_backend_relocate_section \ |
3285 |
sparc64_elf_merge_private_bfd_data |
sparc64_elf_merge_private_bfd_data |
3286 |
#define elf_backend_fake_sections \ |
#define elf_backend_fake_sections \ |
3287 |
sparc64_elf_fake_sections |
sparc64_elf_fake_sections |
3288 |
|
#define elf_backend_plt_sym_val \ |
3289 |
|
sparc64_elf_plt_sym_val |
3290 |
|
|
3291 |
#define elf_backend_size_info \ |
#define elf_backend_size_info \ |
3292 |
sparc64_elf_size_info |
sparc64_elf_size_info |
3298 |
#define elf_backend_want_got_plt 0 |
#define elf_backend_want_got_plt 0 |
3299 |
#define elf_backend_plt_readonly 0 |
#define elf_backend_plt_readonly 0 |
3300 |
#define elf_backend_want_plt_sym 1 |
#define elf_backend_want_plt_sym 1 |
3301 |
|
#define elf_backend_rela_normal 1 |
3302 |
|
|
3303 |
/* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */ |
/* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */ |
3304 |
#define elf_backend_plt_alignment 8 |
#define elf_backend_plt_alignment 8 |
3305 |
|
|
3306 |
#define elf_backend_got_header_size 8 |
#define elf_backend_got_header_size 8 |
|
#define elf_backend_plt_header_size PLT_HEADER_SIZE |
|
3307 |
|
|
3308 |
#include "elf64-target.h" |
#include "elf64-target.h" |