1d2201f2fSdrahn /* FRV-specific support for 32-bit ELF.
2*cf2f2c56Smiod Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
3d2201f2fSdrahn
4d2201f2fSdrahn This file is part of BFD, the Binary File Descriptor library.
5d2201f2fSdrahn
6d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
7d2201f2fSdrahn it under the terms of the GNU General Public License as published by
8d2201f2fSdrahn the Free Software Foundation; either version 2 of the License, or
9d2201f2fSdrahn (at your option) any later version.
10d2201f2fSdrahn
11d2201f2fSdrahn This program is distributed in the hope that it will be useful,
12d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
13d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14d2201f2fSdrahn GNU General Public License for more details.
15d2201f2fSdrahn
16d2201f2fSdrahn You should have received a copy of the GNU General Public License
17d2201f2fSdrahn along with this program; if not, write to the Free Software
18d2201f2fSdrahn Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19d2201f2fSdrahn
20d2201f2fSdrahn #include "bfd.h"
21d2201f2fSdrahn #include "sysdep.h"
22d2201f2fSdrahn #include "libbfd.h"
23d2201f2fSdrahn #include "elf-bfd.h"
24d2201f2fSdrahn #include "elf/frv.h"
25*cf2f2c56Smiod #include "elf/dwarf2.h"
26*cf2f2c56Smiod #include "hashtab.h"
27d2201f2fSdrahn
28d2201f2fSdrahn /* Forward declarations. */
29d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_lo16
30d2201f2fSdrahn PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
31d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_hi16
32d2201f2fSdrahn PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
33d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_label24
34d2201f2fSdrahn PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
35d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_gprel12
36d2201f2fSdrahn PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
37d2201f2fSdrahn bfd_byte *, bfd_vma));
38d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_gprelu12
39d2201f2fSdrahn PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
40d2201f2fSdrahn bfd_byte *, bfd_vma));
41d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_gprello
42d2201f2fSdrahn PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
43d2201f2fSdrahn bfd_byte *, bfd_vma));
44d2201f2fSdrahn static bfd_reloc_status_type elf32_frv_relocate_gprelhi
45d2201f2fSdrahn PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
46d2201f2fSdrahn bfd_byte *, bfd_vma));
47d2201f2fSdrahn static reloc_howto_type *frv_reloc_type_lookup
48d2201f2fSdrahn PARAMS ((bfd *, bfd_reloc_code_real_type));
49d2201f2fSdrahn static void frv_info_to_howto_rela
50d2201f2fSdrahn PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
51d2201f2fSdrahn static bfd_boolean elf32_frv_relocate_section
52d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
53d2201f2fSdrahn Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
54d2201f2fSdrahn static bfd_boolean elf32_frv_add_symbol_hook
55*cf2f2c56Smiod PARAMS (( bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
56d2201f2fSdrahn const char **, flagword *, asection **, bfd_vma *));
57d2201f2fSdrahn static bfd_reloc_status_type frv_final_link_relocate
58d2201f2fSdrahn PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
59d2201f2fSdrahn Elf_Internal_Rela *, bfd_vma));
60d2201f2fSdrahn static bfd_boolean elf32_frv_gc_sweep_hook
61d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, asection *, const
62d2201f2fSdrahn Elf_Internal_Rela *));
63d2201f2fSdrahn static asection * elf32_frv_gc_mark_hook
64d2201f2fSdrahn PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
65d2201f2fSdrahn struct elf_link_hash_entry *, Elf_Internal_Sym *));
66d2201f2fSdrahn static bfd_boolean elf32_frv_check_relocs
67d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, asection *,
68d2201f2fSdrahn const Elf_Internal_Rela *));
69d2201f2fSdrahn static int elf32_frv_machine
70d2201f2fSdrahn PARAMS ((bfd *));
71d2201f2fSdrahn static bfd_boolean elf32_frv_object_p
72d2201f2fSdrahn PARAMS ((bfd *));
73d2201f2fSdrahn static bfd_boolean frv_elf_set_private_flags
74d2201f2fSdrahn PARAMS ((bfd *, flagword));
75d2201f2fSdrahn static bfd_boolean frv_elf_copy_private_bfd_data
76d2201f2fSdrahn PARAMS ((bfd *, bfd *));
77d2201f2fSdrahn static bfd_boolean frv_elf_merge_private_bfd_data
78d2201f2fSdrahn PARAMS ((bfd *, bfd *));
79d2201f2fSdrahn static bfd_boolean frv_elf_print_private_bfd_data
80d2201f2fSdrahn PARAMS ((bfd *, PTR));
81d2201f2fSdrahn
82d2201f2fSdrahn static reloc_howto_type elf32_frv_howto_table [] =
83d2201f2fSdrahn {
84d2201f2fSdrahn /* This reloc does nothing. */
85d2201f2fSdrahn HOWTO (R_FRV_NONE, /* type */
86d2201f2fSdrahn 0, /* rightshift */
87d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
88d2201f2fSdrahn 32, /* bitsize */
89d2201f2fSdrahn FALSE, /* pc_relative */
90d2201f2fSdrahn 0, /* bitpos */
91d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
92d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
93d2201f2fSdrahn "R_FRV_NONE", /* name */
94d2201f2fSdrahn FALSE, /* partial_inplace */
95d2201f2fSdrahn 0, /* src_mask */
96d2201f2fSdrahn 0, /* dst_mask */
97d2201f2fSdrahn FALSE), /* pcrel_offset */
98d2201f2fSdrahn
99d2201f2fSdrahn /* A 32 bit absolute relocation. */
100d2201f2fSdrahn HOWTO (R_FRV_32, /* type */
101d2201f2fSdrahn 0, /* rightshift */
102d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
103d2201f2fSdrahn 32, /* bitsize */
104d2201f2fSdrahn FALSE, /* pc_relative */
105d2201f2fSdrahn 0, /* bitpos */
106d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
107d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
108d2201f2fSdrahn "R_FRV_32", /* name */
109d2201f2fSdrahn FALSE, /* partial_inplace */
110d2201f2fSdrahn 0xffffffff, /* src_mask */
111d2201f2fSdrahn 0xffffffff, /* dst_mask */
112d2201f2fSdrahn FALSE), /* pcrel_offset */
113d2201f2fSdrahn
114d2201f2fSdrahn /* A 16 bit pc-relative relocation. */
115d2201f2fSdrahn HOWTO (R_FRV_LABEL16, /* type */
116*cf2f2c56Smiod 2, /* rightshift */
117d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
118d2201f2fSdrahn 16, /* bitsize */
119d2201f2fSdrahn TRUE, /* pc_relative */
120d2201f2fSdrahn 0, /* bitpos */
121*cf2f2c56Smiod complain_overflow_signed, /* complain_on_overflow */
122d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
123d2201f2fSdrahn "R_FRV_LABEL16", /* name */
124d2201f2fSdrahn FALSE, /* partial_inplace */
125d2201f2fSdrahn 0xffff, /* src_mask */
126d2201f2fSdrahn 0xffff, /* dst_mask */
127d2201f2fSdrahn TRUE), /* pcrel_offset */
128d2201f2fSdrahn
129d2201f2fSdrahn /* A 24-bit pc-relative relocation. */
130d2201f2fSdrahn HOWTO (R_FRV_LABEL24, /* type */
131d2201f2fSdrahn 2, /* rightshift */
132d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
133d2201f2fSdrahn 26, /* bitsize */
134d2201f2fSdrahn TRUE, /* pc_relative */
135d2201f2fSdrahn 0, /* bitpos */
136d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
137d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
138d2201f2fSdrahn "R_FRV_LABEL24", /* name */
139d2201f2fSdrahn FALSE, /* partial_inplace */
140d2201f2fSdrahn 0x7e03ffff, /* src_mask */
141d2201f2fSdrahn 0x7e03ffff, /* dst_mask */
142d2201f2fSdrahn TRUE), /* pcrel_offset */
143d2201f2fSdrahn
144d2201f2fSdrahn HOWTO (R_FRV_LO16, /* type */
145d2201f2fSdrahn 0, /* rightshift */
146d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
147d2201f2fSdrahn 16, /* bitsize */
148d2201f2fSdrahn FALSE, /* pc_relative */
149d2201f2fSdrahn 0, /* bitpos */
150d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
151d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
152d2201f2fSdrahn "R_FRV_LO16", /* name */
153d2201f2fSdrahn FALSE, /* partial_inplace */
154d2201f2fSdrahn 0xffff, /* src_mask */
155d2201f2fSdrahn 0xffff, /* dst_mask */
156d2201f2fSdrahn FALSE), /* pcrel_offset */
157d2201f2fSdrahn
158d2201f2fSdrahn HOWTO (R_FRV_HI16, /* type */
159d2201f2fSdrahn 0, /* rightshift */
160d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
161d2201f2fSdrahn 16, /* bitsize */
162d2201f2fSdrahn FALSE, /* pc_relative */
163d2201f2fSdrahn 0, /* bitpos */
164d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
165d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
166d2201f2fSdrahn "R_FRV_HI16", /* name */
167d2201f2fSdrahn FALSE, /* partial_inplace */
168d2201f2fSdrahn 0xffff, /* src_mask */
169d2201f2fSdrahn 0xffff, /* dst_mask */
170d2201f2fSdrahn FALSE), /* pcrel_offset */
171d2201f2fSdrahn
172d2201f2fSdrahn HOWTO (R_FRV_GPREL12, /* type */
173d2201f2fSdrahn 0, /* rightshift */
174d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
175d2201f2fSdrahn 12, /* bitsize */
176d2201f2fSdrahn FALSE, /* pc_relative */
177d2201f2fSdrahn 0, /* bitpos */
178d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
179d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
180d2201f2fSdrahn "R_FRV_GPREL12", /* name */
181d2201f2fSdrahn FALSE, /* partial_inplace */
182d2201f2fSdrahn 0xfff, /* src_mask */
183d2201f2fSdrahn 0xfff, /* dst_mask */
184d2201f2fSdrahn FALSE), /* pcrel_offset */
185d2201f2fSdrahn
186d2201f2fSdrahn HOWTO (R_FRV_GPRELU12, /* type */
187d2201f2fSdrahn 0, /* rightshift */
188d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
189d2201f2fSdrahn 12, /* bitsize */
190d2201f2fSdrahn FALSE, /* pc_relative */
191d2201f2fSdrahn 0, /* bitpos */
192d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
193d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
194d2201f2fSdrahn "R_FRV_GPRELU12", /* name */
195d2201f2fSdrahn FALSE, /* partial_inplace */
196d2201f2fSdrahn 0xfff, /* src_mask */
197d2201f2fSdrahn 0x3f03f, /* dst_mask */
198d2201f2fSdrahn FALSE), /* pcrel_offset */
199d2201f2fSdrahn
200d2201f2fSdrahn HOWTO (R_FRV_GPREL32, /* type */
201d2201f2fSdrahn 0, /* rightshift */
202d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
203d2201f2fSdrahn 32, /* bitsize */
204d2201f2fSdrahn FALSE, /* pc_relative */
205d2201f2fSdrahn 0, /* bitpos */
206d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
207d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
208d2201f2fSdrahn "R_FRV_GPREL32", /* name */
209d2201f2fSdrahn FALSE, /* partial_inplace */
210d2201f2fSdrahn 0xffffffff, /* src_mask */
211d2201f2fSdrahn 0xffffffff, /* dst_mask */
212d2201f2fSdrahn FALSE), /* pcrel_offset */
213d2201f2fSdrahn
214d2201f2fSdrahn HOWTO (R_FRV_GPRELHI, /* type */
215d2201f2fSdrahn 0, /* rightshift */
216d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
217d2201f2fSdrahn 16, /* bitsize */
218d2201f2fSdrahn FALSE, /* pc_relative */
219d2201f2fSdrahn 0, /* bitpos */
220d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
221d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
222d2201f2fSdrahn "R_FRV_GPRELHI", /* name */
223d2201f2fSdrahn FALSE, /* partial_inplace */
224d2201f2fSdrahn 0xffff, /* src_mask */
225d2201f2fSdrahn 0xffff, /* dst_mask */
226d2201f2fSdrahn FALSE), /* pcrel_offset */
227d2201f2fSdrahn
228d2201f2fSdrahn HOWTO (R_FRV_GPRELLO, /* type */
229d2201f2fSdrahn 0, /* rightshift */
230d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
231d2201f2fSdrahn 16, /* bitsize */
232d2201f2fSdrahn FALSE, /* pc_relative */
233d2201f2fSdrahn 0, /* bitpos */
234d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
235d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
236d2201f2fSdrahn "R_FRV_GPRELLO", /* name */
237d2201f2fSdrahn FALSE, /* partial_inplace */
238d2201f2fSdrahn 0xffff, /* src_mask */
239d2201f2fSdrahn 0xffff, /* dst_mask */
240d2201f2fSdrahn FALSE), /* pcrel_offset */
241*cf2f2c56Smiod
242*cf2f2c56Smiod /* A 12-bit signed operand with the GOT offset for the address of
243*cf2f2c56Smiod the symbol. */
244*cf2f2c56Smiod HOWTO (R_FRV_GOT12, /* type */
245*cf2f2c56Smiod 0, /* rightshift */
246*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
247*cf2f2c56Smiod 12, /* bitsize */
248*cf2f2c56Smiod FALSE, /* pc_relative */
249*cf2f2c56Smiod 0, /* bitpos */
250*cf2f2c56Smiod complain_overflow_signed, /* complain_on_overflow */
251*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
252*cf2f2c56Smiod "R_FRV_GOT12", /* name */
253*cf2f2c56Smiod FALSE, /* partial_inplace */
254*cf2f2c56Smiod 0xfff, /* src_mask */
255*cf2f2c56Smiod 0xfff, /* dst_mask */
256*cf2f2c56Smiod FALSE), /* pcrel_offset */
257*cf2f2c56Smiod
258*cf2f2c56Smiod /* The upper 16 bits of the GOT offset for the address of the
259*cf2f2c56Smiod symbol. */
260*cf2f2c56Smiod HOWTO (R_FRV_GOTHI, /* type */
261*cf2f2c56Smiod 0, /* rightshift */
262*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
263*cf2f2c56Smiod 16, /* bitsize */
264*cf2f2c56Smiod FALSE, /* pc_relative */
265*cf2f2c56Smiod 0, /* bitpos */
266*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
267*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
268*cf2f2c56Smiod "R_FRV_GOTHI", /* name */
269*cf2f2c56Smiod FALSE, /* partial_inplace */
270*cf2f2c56Smiod 0xffff, /* src_mask */
271*cf2f2c56Smiod 0xffff, /* dst_mask */
272*cf2f2c56Smiod FALSE), /* pcrel_offset */
273*cf2f2c56Smiod
274*cf2f2c56Smiod /* The lower 16 bits of the GOT offset for the address of the
275*cf2f2c56Smiod symbol. */
276*cf2f2c56Smiod HOWTO (R_FRV_GOTLO, /* type */
277*cf2f2c56Smiod 0, /* rightshift */
278*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
279*cf2f2c56Smiod 16, /* bitsize */
280*cf2f2c56Smiod FALSE, /* pc_relative */
281*cf2f2c56Smiod 0, /* bitpos */
282*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
283*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
284*cf2f2c56Smiod "R_FRV_GOTLO", /* name */
285*cf2f2c56Smiod FALSE, /* partial_inplace */
286*cf2f2c56Smiod 0xffff, /* src_mask */
287*cf2f2c56Smiod 0xffff, /* dst_mask */
288*cf2f2c56Smiod FALSE), /* pcrel_offset */
289*cf2f2c56Smiod
290*cf2f2c56Smiod /* The 32-bit address of the canonical descriptor of a function. */
291*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC, /* type */
292*cf2f2c56Smiod 0, /* rightshift */
293*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
294*cf2f2c56Smiod 32, /* bitsize */
295*cf2f2c56Smiod FALSE, /* pc_relative */
296*cf2f2c56Smiod 0, /* bitpos */
297*cf2f2c56Smiod complain_overflow_bitfield, /* complain_on_overflow */
298*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
299*cf2f2c56Smiod "R_FRV_FUNCDESC", /* name */
300*cf2f2c56Smiod FALSE, /* partial_inplace */
301*cf2f2c56Smiod 0xffffffff, /* src_mask */
302*cf2f2c56Smiod 0xffffffff, /* dst_mask */
303*cf2f2c56Smiod FALSE), /* pcrel_offset */
304*cf2f2c56Smiod
305*cf2f2c56Smiod /* A 12-bit signed operand with the GOT offset for the address of
306*cf2f2c56Smiod canonical descriptor of a function. */
307*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_GOT12, /* type */
308*cf2f2c56Smiod 0, /* rightshift */
309*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
310*cf2f2c56Smiod 12, /* bitsize */
311*cf2f2c56Smiod FALSE, /* pc_relative */
312*cf2f2c56Smiod 0, /* bitpos */
313*cf2f2c56Smiod complain_overflow_signed, /* complain_on_overflow */
314*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
315*cf2f2c56Smiod "R_FRV_FUNCDESC_GOT12", /* name */
316*cf2f2c56Smiod FALSE, /* partial_inplace */
317*cf2f2c56Smiod 0xfff, /* src_mask */
318*cf2f2c56Smiod 0xfff, /* dst_mask */
319*cf2f2c56Smiod FALSE), /* pcrel_offset */
320*cf2f2c56Smiod
321*cf2f2c56Smiod /* The upper 16 bits of the GOT offset for the address of the
322*cf2f2c56Smiod canonical descriptor of a function. */
323*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_GOTHI, /* type */
324*cf2f2c56Smiod 0, /* rightshift */
325*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
326*cf2f2c56Smiod 16, /* bitsize */
327*cf2f2c56Smiod FALSE, /* pc_relative */
328*cf2f2c56Smiod 0, /* bitpos */
329*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
330*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
331*cf2f2c56Smiod "R_FRV_FUNCDESC_GOTHI", /* name */
332*cf2f2c56Smiod FALSE, /* partial_inplace */
333*cf2f2c56Smiod 0xffff, /* src_mask */
334*cf2f2c56Smiod 0xffff, /* dst_mask */
335*cf2f2c56Smiod FALSE), /* pcrel_offset */
336*cf2f2c56Smiod
337*cf2f2c56Smiod /* The lower 16 bits of the GOT offset for the address of the
338*cf2f2c56Smiod canonical descriptor of a function. */
339*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_GOTLO, /* type */
340*cf2f2c56Smiod 0, /* rightshift */
341*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
342*cf2f2c56Smiod 16, /* bitsize */
343*cf2f2c56Smiod FALSE, /* pc_relative */
344*cf2f2c56Smiod 0, /* bitpos */
345*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
346*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
347*cf2f2c56Smiod "R_FRV_FUNCDESC_GOTLO", /* name */
348*cf2f2c56Smiod FALSE, /* partial_inplace */
349*cf2f2c56Smiod 0xffff, /* src_mask */
350*cf2f2c56Smiod 0xffff, /* dst_mask */
351*cf2f2c56Smiod FALSE), /* pcrel_offset */
352*cf2f2c56Smiod
353*cf2f2c56Smiod /* The 32-bit address of the canonical descriptor of a function. */
354*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_VALUE, /* type */
355*cf2f2c56Smiod 0, /* rightshift */
356*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
357*cf2f2c56Smiod 64, /* bitsize */
358*cf2f2c56Smiod FALSE, /* pc_relative */
359*cf2f2c56Smiod 0, /* bitpos */
360*cf2f2c56Smiod complain_overflow_bitfield, /* complain_on_overflow */
361*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
362*cf2f2c56Smiod "R_FRV_FUNCDESC_VALUE", /* name */
363*cf2f2c56Smiod FALSE, /* partial_inplace */
364*cf2f2c56Smiod 0xffffffff, /* src_mask */
365*cf2f2c56Smiod 0xffffffff, /* dst_mask */
366*cf2f2c56Smiod FALSE), /* pcrel_offset */
367*cf2f2c56Smiod
368*cf2f2c56Smiod /* A 12-bit signed operand with the GOT offset for the address of
369*cf2f2c56Smiod canonical descriptor of a function. */
370*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_GOTOFF12, /* type */
371*cf2f2c56Smiod 0, /* rightshift */
372*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
373*cf2f2c56Smiod 12, /* bitsize */
374*cf2f2c56Smiod FALSE, /* pc_relative */
375*cf2f2c56Smiod 0, /* bitpos */
376*cf2f2c56Smiod complain_overflow_signed, /* complain_on_overflow */
377*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
378*cf2f2c56Smiod "R_FRV_FUNCDESC_GOTOFF12", /* name */
379*cf2f2c56Smiod FALSE, /* partial_inplace */
380*cf2f2c56Smiod 0xfff, /* src_mask */
381*cf2f2c56Smiod 0xfff, /* dst_mask */
382*cf2f2c56Smiod FALSE), /* pcrel_offset */
383*cf2f2c56Smiod
384*cf2f2c56Smiod /* The upper 16 bits of the GOT offset for the address of the
385*cf2f2c56Smiod canonical descriptor of a function. */
386*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_GOTOFFHI, /* type */
387*cf2f2c56Smiod 0, /* rightshift */
388*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
389*cf2f2c56Smiod 16, /* bitsize */
390*cf2f2c56Smiod FALSE, /* pc_relative */
391*cf2f2c56Smiod 0, /* bitpos */
392*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
393*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
394*cf2f2c56Smiod "R_FRV_FUNCDESC_GOTOFFHI", /* name */
395*cf2f2c56Smiod FALSE, /* partial_inplace */
396*cf2f2c56Smiod 0xffff, /* src_mask */
397*cf2f2c56Smiod 0xffff, /* dst_mask */
398*cf2f2c56Smiod FALSE), /* pcrel_offset */
399*cf2f2c56Smiod
400*cf2f2c56Smiod /* The lower 16 bits of the GOT offset for the address of the
401*cf2f2c56Smiod canonical descriptor of a function. */
402*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_GOTOFFLO, /* type */
403*cf2f2c56Smiod 0, /* rightshift */
404*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
405*cf2f2c56Smiod 16, /* bitsize */
406*cf2f2c56Smiod FALSE, /* pc_relative */
407*cf2f2c56Smiod 0, /* bitpos */
408*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
409*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
410*cf2f2c56Smiod "R_FRV_FUNCDESC_GOTOFFLO", /* name */
411*cf2f2c56Smiod FALSE, /* partial_inplace */
412*cf2f2c56Smiod 0xffff, /* src_mask */
413*cf2f2c56Smiod 0xffff, /* dst_mask */
414*cf2f2c56Smiod FALSE), /* pcrel_offset */
415*cf2f2c56Smiod
416*cf2f2c56Smiod /* A 12-bit signed operand with the GOT offset for the address of
417*cf2f2c56Smiod the symbol. */
418*cf2f2c56Smiod HOWTO (R_FRV_GOTOFF12, /* type */
419*cf2f2c56Smiod 0, /* rightshift */
420*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
421*cf2f2c56Smiod 12, /* bitsize */
422*cf2f2c56Smiod FALSE, /* pc_relative */
423*cf2f2c56Smiod 0, /* bitpos */
424*cf2f2c56Smiod complain_overflow_signed, /* complain_on_overflow */
425*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
426*cf2f2c56Smiod "R_FRV_GOTOFF12", /* name */
427*cf2f2c56Smiod FALSE, /* partial_inplace */
428*cf2f2c56Smiod 0xfff, /* src_mask */
429*cf2f2c56Smiod 0xfff, /* dst_mask */
430*cf2f2c56Smiod FALSE), /* pcrel_offset */
431*cf2f2c56Smiod
432*cf2f2c56Smiod /* The upper 16 bits of the GOT offset for the address of the
433*cf2f2c56Smiod symbol. */
434*cf2f2c56Smiod HOWTO (R_FRV_GOTOFFHI, /* type */
435*cf2f2c56Smiod 0, /* rightshift */
436*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
437*cf2f2c56Smiod 16, /* bitsize */
438*cf2f2c56Smiod FALSE, /* pc_relative */
439*cf2f2c56Smiod 0, /* bitpos */
440*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
441*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
442*cf2f2c56Smiod "R_FRV_GOTOFFHI", /* name */
443*cf2f2c56Smiod FALSE, /* partial_inplace */
444*cf2f2c56Smiod 0xffff, /* src_mask */
445*cf2f2c56Smiod 0xffff, /* dst_mask */
446*cf2f2c56Smiod FALSE), /* pcrel_offset */
447*cf2f2c56Smiod
448*cf2f2c56Smiod /* The lower 16 bits of the GOT offset for the address of the
449*cf2f2c56Smiod symbol. */
450*cf2f2c56Smiod HOWTO (R_FRV_GOTOFFLO, /* type */
451*cf2f2c56Smiod 0, /* rightshift */
452*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
453*cf2f2c56Smiod 16, /* bitsize */
454*cf2f2c56Smiod FALSE, /* pc_relative */
455*cf2f2c56Smiod 0, /* bitpos */
456*cf2f2c56Smiod complain_overflow_dont, /* complain_on_overflow */
457*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
458*cf2f2c56Smiod "R_FRV_GOTOFFLO", /* name */
459*cf2f2c56Smiod FALSE, /* partial_inplace */
460*cf2f2c56Smiod 0xffff, /* src_mask */
461*cf2f2c56Smiod 0xffff, /* dst_mask */
462*cf2f2c56Smiod FALSE), /* pcrel_offset */
463*cf2f2c56Smiod
464d2201f2fSdrahn };
465d2201f2fSdrahn
466d2201f2fSdrahn /* GNU extension to record C++ vtable hierarchy. */
467d2201f2fSdrahn static reloc_howto_type elf32_frv_vtinherit_howto =
468d2201f2fSdrahn HOWTO (R_FRV_GNU_VTINHERIT, /* type */
469d2201f2fSdrahn 0, /* rightshift */
470d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
471d2201f2fSdrahn 0, /* bitsize */
472d2201f2fSdrahn FALSE, /* pc_relative */
473d2201f2fSdrahn 0, /* bitpos */
474d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
475d2201f2fSdrahn NULL, /* special_function */
476d2201f2fSdrahn "R_FRV_GNU_VTINHERIT", /* name */
477d2201f2fSdrahn FALSE, /* partial_inplace */
478d2201f2fSdrahn 0, /* src_mask */
479d2201f2fSdrahn 0, /* dst_mask */
480d2201f2fSdrahn FALSE); /* pcrel_offset */
481d2201f2fSdrahn
482d2201f2fSdrahn /* GNU extension to record C++ vtable member usage. */
483d2201f2fSdrahn static reloc_howto_type elf32_frv_vtentry_howto =
484d2201f2fSdrahn HOWTO (R_FRV_GNU_VTENTRY, /* type */
485d2201f2fSdrahn 0, /* rightshift */
486d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
487d2201f2fSdrahn 0, /* bitsize */
488d2201f2fSdrahn FALSE, /* pc_relative */
489d2201f2fSdrahn 0, /* bitpos */
490d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
491d2201f2fSdrahn _bfd_elf_rel_vtable_reloc_fn, /* special_function */
492d2201f2fSdrahn "R_FRV_GNU_VTENTRY", /* name */
493d2201f2fSdrahn FALSE, /* partial_inplace */
494d2201f2fSdrahn 0, /* src_mask */
495d2201f2fSdrahn 0, /* dst_mask */
496d2201f2fSdrahn FALSE); /* pcrel_offset */
497*cf2f2c56Smiod
498*cf2f2c56Smiod /* The following 3 relocations are REL. The only difference to the
499*cf2f2c56Smiod entries in the table above are that partial_inplace is TRUE. */
500*cf2f2c56Smiod static reloc_howto_type elf32_frv_rel_32_howto =
501*cf2f2c56Smiod HOWTO (R_FRV_32, /* type */
502*cf2f2c56Smiod 0, /* rightshift */
503*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
504*cf2f2c56Smiod 32, /* bitsize */
505*cf2f2c56Smiod FALSE, /* pc_relative */
506*cf2f2c56Smiod 0, /* bitpos */
507*cf2f2c56Smiod complain_overflow_bitfield, /* complain_on_overflow */
508*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
509*cf2f2c56Smiod "R_FRV_32", /* name */
510*cf2f2c56Smiod TRUE, /* partial_inplace */
511*cf2f2c56Smiod 0xffffffff, /* src_mask */
512*cf2f2c56Smiod 0xffffffff, /* dst_mask */
513*cf2f2c56Smiod FALSE); /* pcrel_offset */
514*cf2f2c56Smiod
515*cf2f2c56Smiod static reloc_howto_type elf32_frv_rel_funcdesc_howto =
516*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC, /* type */
517*cf2f2c56Smiod 0, /* rightshift */
518*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
519*cf2f2c56Smiod 32, /* bitsize */
520*cf2f2c56Smiod FALSE, /* pc_relative */
521*cf2f2c56Smiod 0, /* bitpos */
522*cf2f2c56Smiod complain_overflow_bitfield, /* complain_on_overflow */
523*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
524*cf2f2c56Smiod "R_FRV_FUNCDESC", /* name */
525*cf2f2c56Smiod TRUE, /* partial_inplace */
526*cf2f2c56Smiod 0xffffffff, /* src_mask */
527*cf2f2c56Smiod 0xffffffff, /* dst_mask */
528*cf2f2c56Smiod FALSE); /* pcrel_offset */
529*cf2f2c56Smiod
530*cf2f2c56Smiod static reloc_howto_type elf32_frv_rel_funcdesc_value_howto =
531*cf2f2c56Smiod HOWTO (R_FRV_FUNCDESC_VALUE, /* type */
532*cf2f2c56Smiod 0, /* rightshift */
533*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
534*cf2f2c56Smiod 64, /* bitsize */
535*cf2f2c56Smiod FALSE, /* pc_relative */
536*cf2f2c56Smiod 0, /* bitpos */
537*cf2f2c56Smiod complain_overflow_bitfield, /* complain_on_overflow */
538*cf2f2c56Smiod bfd_elf_generic_reloc, /* special_function */
539*cf2f2c56Smiod "R_FRV_FUNCDESC_VALUE", /* name */
540*cf2f2c56Smiod TRUE, /* partial_inplace */
541*cf2f2c56Smiod 0xffffffff, /* src_mask */
542*cf2f2c56Smiod 0xffffffff, /* dst_mask */
543*cf2f2c56Smiod FALSE); /* pcrel_offset */
544*cf2f2c56Smiod
545d2201f2fSdrahn
546d2201f2fSdrahn /* Map BFD reloc types to FRV ELF reloc types. */
547d2201f2fSdrahn #if 0
548d2201f2fSdrahn struct frv_reloc_map
549d2201f2fSdrahn {
550d2201f2fSdrahn unsigned int bfd_reloc_val;
551d2201f2fSdrahn unsigned int frv_reloc_val;
552d2201f2fSdrahn };
553d2201f2fSdrahn
554d2201f2fSdrahn static const struct frv_reloc_map frv_reloc_map [] =
555d2201f2fSdrahn {
556d2201f2fSdrahn { BFD_RELOC_NONE, R_FRV_NONE },
557d2201f2fSdrahn { BFD_RELOC_32, R_FRV_32 },
558d2201f2fSdrahn { BFD_RELOC_FRV_LABEL16, R_FRV_LABEL16 },
559d2201f2fSdrahn { BFD_RELOC_FRV_LABEL24, R_FRV_LABEL24 },
560d2201f2fSdrahn { BFD_RELOC_FRV_LO16, R_FRV_LO16 },
561d2201f2fSdrahn { BFD_RELOC_FRV_HI16, R_FRV_HI16 },
562d2201f2fSdrahn { BFD_RELOC_FRV_GPREL12, R_FRV_GPREL12 },
563d2201f2fSdrahn { BFD_RELOC_FRV_GPRELU12, R_FRV_GPRELU12 },
564d2201f2fSdrahn { BFD_RELOC_FRV_GPREL32, R_FRV_GPREL32 },
565d2201f2fSdrahn { BFD_RELOC_FRV_GPRELHI, R_FRV_GPRELHI },
566d2201f2fSdrahn { BFD_RELOC_FRV_GPRELLO, R_FRV_GPRELLO },
567*cf2f2c56Smiod { BFD_RELOC_FRV_GOT12, R_FRV_GOT12 },
568*cf2f2c56Smiod { BFD_RELOC_FRV_GOTHI, R_FRV_GOTHI },
569*cf2f2c56Smiod { BFD_RELOC_FRV_GOTLO, R_FRV_GOTLO },
570*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC, R_FRV_FUNCDESC },
571*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_GOT12, R_FRV_FUNCDESC_GOT12 },
572*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_GOTHI, R_FRV_FUNCDESC_GOTHI },
573*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_GOTLO, R_FRV_FUNCDESC_GOTLO },
574*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_VALUE, R_FRV_FUNCDESC_VALUE },
575*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_GOTOFF12, R_FRV_FUNCDESC_GOTOFF12 },
576*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, R_FRV_FUNCDESC_GOTOFFHI },
577*cf2f2c56Smiod { BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, R_FRV_FUNCDESC_GOTOFFLO },
578*cf2f2c56Smiod { BFD_RELOC_FRV_GOTOFF12, R_FRV_GOTOFF12 },
579*cf2f2c56Smiod { BFD_RELOC_FRV_GOTOFFHI, R_FRV_GOTOFFHI },
580*cf2f2c56Smiod { BFD_RELOC_FRV_GOTOFFLO, R_FRV_GOTOFFLO },
581d2201f2fSdrahn { BFD_RELOC_VTABLE_INHERIT, R_FRV_GNU_VTINHERIT },
582d2201f2fSdrahn { BFD_RELOC_VTABLE_ENTRY, R_FRV_GNU_VTENTRY },
583d2201f2fSdrahn };
584d2201f2fSdrahn #endif
585d2201f2fSdrahn
586*cf2f2c56Smiod extern const bfd_target bfd_elf32_frvfdpic_vec;
587*cf2f2c56Smiod #define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_frvfdpic_vec)
588*cf2f2c56Smiod
589*cf2f2c56Smiod /* An extension of the elf hash table data structure, containing some
590*cf2f2c56Smiod additional FRV-specific data. */
591*cf2f2c56Smiod struct frvfdpic_elf_link_hash_table
592*cf2f2c56Smiod {
593*cf2f2c56Smiod struct elf_link_hash_table elf;
594*cf2f2c56Smiod
595*cf2f2c56Smiod /* A pointer to the .got section. */
596*cf2f2c56Smiod asection *sgot;
597*cf2f2c56Smiod /* A pointer to the .rel.got section. */
598*cf2f2c56Smiod asection *sgotrel;
599*cf2f2c56Smiod /* A pointer to the .rofixup section. */
600*cf2f2c56Smiod asection *sgotfixup;
601*cf2f2c56Smiod /* A pointer to the .plt section. */
602*cf2f2c56Smiod asection *splt;
603*cf2f2c56Smiod /* A pointer to the .rel.plt section. */
604*cf2f2c56Smiod asection *spltrel;
605*cf2f2c56Smiod /* GOT base offset. */
606*cf2f2c56Smiod bfd_vma got0;
607*cf2f2c56Smiod /* Location of the first non-lazy PLT entry, i.e., the number of
608*cf2f2c56Smiod bytes taken by lazy PLT entries. */
609*cf2f2c56Smiod bfd_vma plt0;
610*cf2f2c56Smiod /* A hash table holding information about which symbols were
611*cf2f2c56Smiod referenced with which PIC-related relocations. */
612*cf2f2c56Smiod struct htab *relocs_info;
613*cf2f2c56Smiod };
614*cf2f2c56Smiod
615*cf2f2c56Smiod /* Get the FRV ELF linker hash table from a link_info structure. */
616*cf2f2c56Smiod
617*cf2f2c56Smiod #define frvfdpic_hash_table(info) \
618*cf2f2c56Smiod ((struct frvfdpic_elf_link_hash_table *) ((info)->hash))
619*cf2f2c56Smiod
620*cf2f2c56Smiod #define frvfdpic_got_section(info) \
621*cf2f2c56Smiod (frvfdpic_hash_table (info)->sgot)
622*cf2f2c56Smiod #define frvfdpic_gotrel_section(info) \
623*cf2f2c56Smiod (frvfdpic_hash_table (info)->sgotrel)
624*cf2f2c56Smiod #define frvfdpic_gotfixup_section(info) \
625*cf2f2c56Smiod (frvfdpic_hash_table (info)->sgotfixup)
626*cf2f2c56Smiod #define frvfdpic_plt_section(info) \
627*cf2f2c56Smiod (frvfdpic_hash_table (info)->splt)
628*cf2f2c56Smiod #define frvfdpic_pltrel_section(info) \
629*cf2f2c56Smiod (frvfdpic_hash_table (info)->spltrel)
630*cf2f2c56Smiod #define frvfdpic_relocs_info(info) \
631*cf2f2c56Smiod (frvfdpic_hash_table (info)->relocs_info)
632*cf2f2c56Smiod #define frvfdpic_got_initial_offset(info) \
633*cf2f2c56Smiod (frvfdpic_hash_table (info)->got0)
634*cf2f2c56Smiod #define frvfdpic_plt_initial_offset(info) \
635*cf2f2c56Smiod (frvfdpic_hash_table (info)->plt0)
636*cf2f2c56Smiod
637*cf2f2c56Smiod /* Create an FRV ELF linker hash table. */
638*cf2f2c56Smiod
639*cf2f2c56Smiod static struct bfd_link_hash_table *
frvfdpic_elf_link_hash_table_create(bfd * abfd)640*cf2f2c56Smiod frvfdpic_elf_link_hash_table_create (bfd *abfd)
641*cf2f2c56Smiod {
642*cf2f2c56Smiod struct frvfdpic_elf_link_hash_table *ret;
643*cf2f2c56Smiod bfd_size_type amt = sizeof (struct frvfdpic_elf_link_hash_table);
644*cf2f2c56Smiod
645*cf2f2c56Smiod ret = bfd_zalloc (abfd, amt);
646*cf2f2c56Smiod if (ret == NULL)
647*cf2f2c56Smiod return NULL;
648*cf2f2c56Smiod
649*cf2f2c56Smiod if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd,
650*cf2f2c56Smiod _bfd_elf_link_hash_newfunc))
651*cf2f2c56Smiod {
652*cf2f2c56Smiod free (ret);
653*cf2f2c56Smiod return NULL;
654*cf2f2c56Smiod }
655*cf2f2c56Smiod
656*cf2f2c56Smiod return &ret->elf.root;
657*cf2f2c56Smiod }
658*cf2f2c56Smiod
659*cf2f2c56Smiod /* Decide whether a reference to a symbol can be resolved locally or
660*cf2f2c56Smiod not. If the symbol is protected, we want the local address, but
661*cf2f2c56Smiod its function descriptor must be assigned by the dynamic linker. */
662*cf2f2c56Smiod #define FRVFDPIC_SYM_LOCAL(INFO, H) \
663*cf2f2c56Smiod (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
664*cf2f2c56Smiod || ! elf_hash_table (INFO)->dynamic_sections_created \
665*cf2f2c56Smiod || (/* The condition below is an ugly hack to get .scommon data to
666*cf2f2c56Smiod be regarded as local. For some reason the
667*cf2f2c56Smiod ELF_LINK_HASH_DEF_REGULAR bit is not set on such common
668*cf2f2c56Smiod symbols, and the SEC_IS_COMMON bit is not set any longer
669*cf2f2c56Smiod when we need to perform this test. Hopefully this
670*cf2f2c56Smiod approximation is good enough. */ \
671*cf2f2c56Smiod ((H)->root.type == bfd_link_hash_defined \
672*cf2f2c56Smiod || (H)->root.type == bfd_link_hash_defweak) \
673*cf2f2c56Smiod && (H)->root.u.def.section->output_section \
674*cf2f2c56Smiod && ((H)->root.u.def.section->flags & SEC_LINKER_CREATED)))
675*cf2f2c56Smiod #define FRVFDPIC_FUNCDESC_LOCAL(INFO, H) \
676*cf2f2c56Smiod ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
677*cf2f2c56Smiod
678*cf2f2c56Smiod /* This structure collects information on what kind of GOT, PLT or
679*cf2f2c56Smiod function descriptors are required by relocations that reference a
680*cf2f2c56Smiod certain symbol. */
681*cf2f2c56Smiod struct frvfdpic_relocs_info
682*cf2f2c56Smiod {
683*cf2f2c56Smiod /* The index of the symbol, as stored in the relocation r_info, if
684*cf2f2c56Smiod we have a local symbol; -1 otherwise. */
685*cf2f2c56Smiod long symndx;
686*cf2f2c56Smiod union
687*cf2f2c56Smiod {
688*cf2f2c56Smiod /* The input bfd in which the symbol is defined, if it's a local
689*cf2f2c56Smiod symbol. */
690*cf2f2c56Smiod bfd *abfd;
691*cf2f2c56Smiod /* If symndx == -1, the hash table entry corresponding to a global
692*cf2f2c56Smiod symbol (even if it turns out to bind locally, in which case it
693*cf2f2c56Smiod should ideally be replaced with section's symndx + addend). */
694*cf2f2c56Smiod struct elf_link_hash_entry *h;
695*cf2f2c56Smiod } d;
696*cf2f2c56Smiod /* The addend of the relocation that references the symbol. */
697*cf2f2c56Smiod bfd_vma addend;
698*cf2f2c56Smiod
699*cf2f2c56Smiod /* The fields above are used to identify an entry. The fields below
700*cf2f2c56Smiod contain information on how an entry is used and, later on, which
701*cf2f2c56Smiod locations it was assigned. */
702*cf2f2c56Smiod /* The following 3 fields record whether the symbol+addend above was
703*cf2f2c56Smiod ever referenced with a GOT relocation. The 12 suffix indicates a
704*cf2f2c56Smiod GOT12 relocation; los is used for GOTLO relocations that are not
705*cf2f2c56Smiod matched by a GOTHI relocation; hilo is used for GOTLO/GOTHI
706*cf2f2c56Smiod pairs. */
707*cf2f2c56Smiod unsigned got12:1;
708*cf2f2c56Smiod unsigned gotlos:1;
709*cf2f2c56Smiod unsigned gothilo:1;
710*cf2f2c56Smiod /* Whether a FUNCDESC relocation references symbol+addend. */
711*cf2f2c56Smiod unsigned fd:1;
712*cf2f2c56Smiod /* Whether a FUNCDESC_GOT relocation references symbol+addend. */
713*cf2f2c56Smiod unsigned fdgot12:1;
714*cf2f2c56Smiod unsigned fdgotlos:1;
715*cf2f2c56Smiod unsigned fdgothilo:1;
716*cf2f2c56Smiod /* Whether a FUNCDESC_GOTOFF relocation references symbol+addend. */
717*cf2f2c56Smiod unsigned fdgoff12:1;
718*cf2f2c56Smiod unsigned fdgofflos:1;
719*cf2f2c56Smiod unsigned fdgoffhilo:1;
720*cf2f2c56Smiod /* Whether symbol+addend is referenced with GOTOFF12, GOTOFFLO or
721*cf2f2c56Smiod GOTOFFHI relocations. The addend doesn't really matter, since we
722*cf2f2c56Smiod envision that this will only be used to check whether the symbol
723*cf2f2c56Smiod is mapped to the same segment as the got. */
724*cf2f2c56Smiod unsigned gotoff:1;
725*cf2f2c56Smiod /* Whether symbol+addend is referenced by a LABEL24 relocation. */
726*cf2f2c56Smiod unsigned call:1;
727*cf2f2c56Smiod /* Whether symbol+addend is referenced by a 32 or FUNCDESC_VALUE
728*cf2f2c56Smiod relocation. */
729*cf2f2c56Smiod unsigned sym:1;
730*cf2f2c56Smiod /* Whether we need a PLT entry for a symbol. Should be implied by
731*cf2f2c56Smiod something like:
732*cf2f2c56Smiod (call && symndx == -1 && ! FRVFDPIC_SYM_LOCAL (info, d.h)) */
733*cf2f2c56Smiod unsigned plt:1;
734*cf2f2c56Smiod /* Whether a function descriptor should be created in this link unit
735*cf2f2c56Smiod for symbol+addend. Should be implied by something like:
736*cf2f2c56Smiod (plt || fdgotoff12 || fdgotofflos || fdgotofflohi
737*cf2f2c56Smiod || ((fd || fdgot12 || fdgotlos || fdgothilo)
738*cf2f2c56Smiod && (symndx != -1 || FRVFDPIC_FUNCDESC_LOCAL (info, d.h)))) */
739*cf2f2c56Smiod unsigned privfd:1;
740*cf2f2c56Smiod /* Whether a lazy PLT entry is needed for this symbol+addend.
741*cf2f2c56Smiod Should be implied by something like:
742*cf2f2c56Smiod (privfd && symndx == -1 && ! FRVFDPIC_SYM_LOCAL (info, d.h)
743*cf2f2c56Smiod && ! (info->flags & DF_BIND_NOW)) */
744*cf2f2c56Smiod unsigned lazyplt:1;
745*cf2f2c56Smiod /* Whether we've already emitted GOT relocations and PLT entries as
746*cf2f2c56Smiod needed for this symbol. */
747*cf2f2c56Smiod unsigned done:1;
748*cf2f2c56Smiod
749*cf2f2c56Smiod /* The number of R_FRV_32, R_FRV_FUNCDESC and R_FRV_FUNCDESC_VALUE
750*cf2f2c56Smiod relocations referencing the symbol. */
751*cf2f2c56Smiod unsigned relocs32, relocsfd, relocsfdv;
752*cf2f2c56Smiod
753*cf2f2c56Smiod /* The number of .rofixups entries and dynamic relocations allocated
754*cf2f2c56Smiod for this symbol, minus any that might have already been used. */
755*cf2f2c56Smiod unsigned fixups, dynrelocs;
756*cf2f2c56Smiod
757*cf2f2c56Smiod /* The offsets of the GOT entries assigned to symbol+addend, to the
758*cf2f2c56Smiod function descriptor's address, and to a function descriptor,
759*cf2f2c56Smiod respectively. Should be zero if unassigned. The offsets are
760*cf2f2c56Smiod counted from the value that will be assigned to the PIC register,
761*cf2f2c56Smiod not from the beginning of the .got section. */
762*cf2f2c56Smiod bfd_signed_vma got_entry, fdgot_entry, fd_entry;
763*cf2f2c56Smiod /* The offsets of the PLT entries assigned to symbol+addend,
764*cf2f2c56Smiod non-lazy and lazy, respectively. If unassigned, should be
765*cf2f2c56Smiod (bfd_vma)-1. */
766*cf2f2c56Smiod bfd_vma plt_entry, lzplt_entry;
767*cf2f2c56Smiod };
768*cf2f2c56Smiod
769*cf2f2c56Smiod /* Compute a hash with the key fields of an frvfdpic_relocs_info entry. */
770*cf2f2c56Smiod static hashval_t
frvfdpic_relocs_info_hash(const void * entry_)771*cf2f2c56Smiod frvfdpic_relocs_info_hash (const void *entry_)
772*cf2f2c56Smiod {
773*cf2f2c56Smiod const struct frvfdpic_relocs_info *entry = entry_;
774*cf2f2c56Smiod
775*cf2f2c56Smiod return (entry->symndx == -1
776*cf2f2c56Smiod ? entry->d.h->root.root.hash
777*cf2f2c56Smiod : entry->symndx + entry->d.abfd->id * 257) + entry->addend;
778*cf2f2c56Smiod }
779*cf2f2c56Smiod
780*cf2f2c56Smiod /* Test whether the key fields of two frvfdpic_relocs_info entries are
781*cf2f2c56Smiod identical. */
782*cf2f2c56Smiod static int
frvfdpic_relocs_info_eq(const void * entry1,const void * entry2)783*cf2f2c56Smiod frvfdpic_relocs_info_eq (const void *entry1, const void *entry2)
784*cf2f2c56Smiod {
785*cf2f2c56Smiod const struct frvfdpic_relocs_info *e1 = entry1;
786*cf2f2c56Smiod const struct frvfdpic_relocs_info *e2 = entry2;
787*cf2f2c56Smiod
788*cf2f2c56Smiod return e1->symndx == e2->symndx && e1->addend == e2->addend
789*cf2f2c56Smiod && (e1->symndx == -1 ? e1->d.h == e2->d.h : e1->d.abfd == e2->d.abfd);
790*cf2f2c56Smiod }
791*cf2f2c56Smiod
792*cf2f2c56Smiod /* Find or create an entry in a hash table HT that matches the key
793*cf2f2c56Smiod fields of the given ENTRY. If it's not found, memory for a new
794*cf2f2c56Smiod entry is allocated in ABFD's obstack. */
795*cf2f2c56Smiod static struct frvfdpic_relocs_info *
frvfdpic_relocs_info_find(struct htab * ht,bfd * abfd,const struct frvfdpic_relocs_info * entry,enum insert_option insert)796*cf2f2c56Smiod frvfdpic_relocs_info_find (struct htab *ht,
797*cf2f2c56Smiod bfd *abfd,
798*cf2f2c56Smiod const struct frvfdpic_relocs_info *entry,
799*cf2f2c56Smiod enum insert_option insert)
800*cf2f2c56Smiod {
801*cf2f2c56Smiod struct frvfdpic_relocs_info **loc =
802*cf2f2c56Smiod (struct frvfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
803*cf2f2c56Smiod
804*cf2f2c56Smiod if (! loc)
805*cf2f2c56Smiod return NULL;
806*cf2f2c56Smiod
807*cf2f2c56Smiod if (*loc)
808*cf2f2c56Smiod return *loc;
809*cf2f2c56Smiod
810*cf2f2c56Smiod *loc = bfd_zalloc (abfd, sizeof (**loc));
811*cf2f2c56Smiod
812*cf2f2c56Smiod if (! *loc)
813*cf2f2c56Smiod return *loc;
814*cf2f2c56Smiod
815*cf2f2c56Smiod (*loc)->symndx = entry->symndx;
816*cf2f2c56Smiod (*loc)->d = entry->d;
817*cf2f2c56Smiod (*loc)->addend = entry->addend;
818*cf2f2c56Smiod (*loc)->plt_entry = (bfd_vma)-1;
819*cf2f2c56Smiod (*loc)->lzplt_entry = (bfd_vma)-1;
820*cf2f2c56Smiod
821*cf2f2c56Smiod return *loc;
822*cf2f2c56Smiod }
823*cf2f2c56Smiod
824*cf2f2c56Smiod /* Obtain the address of the entry in HT associated with H's symbol +
825*cf2f2c56Smiod addend, creating a new entry if none existed. ABFD is only used
826*cf2f2c56Smiod for memory allocation purposes. */
827*cf2f2c56Smiod inline static struct frvfdpic_relocs_info *
frvfdpic_relocs_info_for_global(struct htab * ht,bfd * abfd,struct elf_link_hash_entry * h,bfd_vma addend,enum insert_option insert)828*cf2f2c56Smiod frvfdpic_relocs_info_for_global (struct htab *ht,
829*cf2f2c56Smiod bfd *abfd,
830*cf2f2c56Smiod struct elf_link_hash_entry *h,
831*cf2f2c56Smiod bfd_vma addend,
832*cf2f2c56Smiod enum insert_option insert)
833*cf2f2c56Smiod {
834*cf2f2c56Smiod struct frvfdpic_relocs_info entry;
835*cf2f2c56Smiod
836*cf2f2c56Smiod entry.symndx = -1;
837*cf2f2c56Smiod entry.d.h = h;
838*cf2f2c56Smiod entry.addend = addend;
839*cf2f2c56Smiod
840*cf2f2c56Smiod return frvfdpic_relocs_info_find (ht, abfd, &entry, insert);
841*cf2f2c56Smiod }
842*cf2f2c56Smiod
843*cf2f2c56Smiod /* Obtain the address of the entry in HT associated with the SYMNDXth
844*cf2f2c56Smiod local symbol of the input bfd ABFD, plus the addend, creating a new
845*cf2f2c56Smiod entry if none existed. */
846*cf2f2c56Smiod inline static struct frvfdpic_relocs_info *
frvfdpic_relocs_info_for_local(struct htab * ht,bfd * abfd,long symndx,bfd_vma addend,enum insert_option insert)847*cf2f2c56Smiod frvfdpic_relocs_info_for_local (struct htab *ht,
848*cf2f2c56Smiod bfd *abfd,
849*cf2f2c56Smiod long symndx,
850*cf2f2c56Smiod bfd_vma addend,
851*cf2f2c56Smiod enum insert_option insert)
852*cf2f2c56Smiod {
853*cf2f2c56Smiod struct frvfdpic_relocs_info entry;
854*cf2f2c56Smiod
855*cf2f2c56Smiod entry.symndx = symndx;
856*cf2f2c56Smiod entry.d.abfd = abfd;
857*cf2f2c56Smiod entry.addend = addend;
858*cf2f2c56Smiod
859*cf2f2c56Smiod return frvfdpic_relocs_info_find (ht, abfd, &entry, insert);
860*cf2f2c56Smiod }
861*cf2f2c56Smiod
862*cf2f2c56Smiod /* Merge fields set by check_relocs() of two entries that end up being
863*cf2f2c56Smiod mapped to the same (presumably global) symbol. */
864*cf2f2c56Smiod
865*cf2f2c56Smiod inline static void
frvfdpic_pic_merge_early_relocs_info(struct frvfdpic_relocs_info * e2,struct frvfdpic_relocs_info const * e1)866*cf2f2c56Smiod frvfdpic_pic_merge_early_relocs_info (struct frvfdpic_relocs_info *e2,
867*cf2f2c56Smiod struct frvfdpic_relocs_info const *e1)
868*cf2f2c56Smiod {
869*cf2f2c56Smiod e2->got12 |= e1->got12;
870*cf2f2c56Smiod e2->gotlos |= e1->gotlos;
871*cf2f2c56Smiod e2->gothilo |= e1->gothilo;
872*cf2f2c56Smiod e2->fd |= e1->fd;
873*cf2f2c56Smiod e2->fdgot12 |= e1->fdgot12;
874*cf2f2c56Smiod e2->fdgotlos |= e1->fdgotlos;
875*cf2f2c56Smiod e2->fdgothilo |= e1->fdgothilo;
876*cf2f2c56Smiod e2->fdgoff12 |= e1->fdgoff12;
877*cf2f2c56Smiod e2->fdgofflos |= e1->fdgofflos;
878*cf2f2c56Smiod e2->fdgoffhilo |= e1->fdgoffhilo;
879*cf2f2c56Smiod e2->gotoff |= e1->gotoff;
880*cf2f2c56Smiod e2->call |= e1->call;
881*cf2f2c56Smiod e2->sym |= e1->sym;
882*cf2f2c56Smiod
883*cf2f2c56Smiod #if 0
884*cf2f2c56Smiod /* These are set in _frvfdpic_count_got_plt_entries() or later, and this
885*cf2f2c56Smiod function is only called in _frvfdpic_resolve_final_relocs_info(), that
886*cf2f2c56Smiod runs just before it, so we don't have to worry about the fields
887*cf2f2c56Smiod below. */
888*cf2f2c56Smiod
889*cf2f2c56Smiod e2->plt |= e1->plt;
890*cf2f2c56Smiod e2->privfd |= e1->privfd;
891*cf2f2c56Smiod e2->lazyplt |= e1->lazyplt;
892*cf2f2c56Smiod e2->done |= e1->done;
893*cf2f2c56Smiod
894*cf2f2c56Smiod e2->relocs32 += e1->relocs32;
895*cf2f2c56Smiod e2->relocsfd += e1->relocsfd;
896*cf2f2c56Smiod e2->relocsfdv += e1->relocsfdv;
897*cf2f2c56Smiod e2->fixups += e1->fixups;
898*cf2f2c56Smiod e2->dynrelocs += e1->dynrelocs;
899*cf2f2c56Smiod
900*cf2f2c56Smiod if (abs (e1->got_entry) < abs (e2->got_entry))
901*cf2f2c56Smiod e2->got_entry = e1->got_entry;
902*cf2f2c56Smiod if (abs (e1->fdgot_entry) < abs (e2->fdgot_entry))
903*cf2f2c56Smiod e2->fdgot_entry = e1->fdgot_entry;
904*cf2f2c56Smiod if (abs (e1->fd_entry) < abs (e2->fd_entry))
905*cf2f2c56Smiod e2->fd_entry = e1->fd_entry;
906*cf2f2c56Smiod
907*cf2f2c56Smiod if (e1->plt_entry < e2->plt_entry)
908*cf2f2c56Smiod e2->plt_entry = e1->plt_entry;
909*cf2f2c56Smiod if (e1->lzplt_entry < e2->lzplt_entry)
910*cf2f2c56Smiod e2->lzplt_entry = e1->lzplt_entry;
911*cf2f2c56Smiod #endif
912*cf2f2c56Smiod }
913*cf2f2c56Smiod
914*cf2f2c56Smiod /* Every block of 65535 lazy PLT entries shares a single call to the
915*cf2f2c56Smiod resolver, inserted in the 32768th lazy PLT entry (i.e., entry #
916*cf2f2c56Smiod 32767, counting from 0). All other lazy PLT entries branch to it
917*cf2f2c56Smiod in a single instruction. */
918*cf2f2c56Smiod
919*cf2f2c56Smiod #define FRVFDPIC_LZPLT_BLOCK_SIZE ((bfd_vma) 8 * 65535 + 4)
920*cf2f2c56Smiod #define FRVFDPIC_LZPLT_RESOLV_LOC (8 * 32767)
921*cf2f2c56Smiod
922*cf2f2c56Smiod /* Add a dynamic relocation to the SRELOC section. */
923*cf2f2c56Smiod
924*cf2f2c56Smiod inline static bfd_vma
_frvfdpic_add_dyn_reloc(bfd * output_bfd,asection * sreloc,bfd_vma offset,int reloc_type,long dynindx,bfd_vma addend,struct frvfdpic_relocs_info * entry)925*cf2f2c56Smiod _frvfdpic_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
926*cf2f2c56Smiod int reloc_type, long dynindx, bfd_vma addend,
927*cf2f2c56Smiod struct frvfdpic_relocs_info *entry)
928*cf2f2c56Smiod {
929*cf2f2c56Smiod Elf_Internal_Rela outrel;
930*cf2f2c56Smiod bfd_vma reloc_offset;
931*cf2f2c56Smiod
932*cf2f2c56Smiod outrel.r_offset = offset;
933*cf2f2c56Smiod outrel.r_info = ELF32_R_INFO (dynindx, reloc_type);
934*cf2f2c56Smiod outrel.r_addend = addend;
935*cf2f2c56Smiod
936*cf2f2c56Smiod reloc_offset = sreloc->reloc_count * sizeof (Elf32_External_Rel);
937*cf2f2c56Smiod BFD_ASSERT (reloc_offset < sreloc->_raw_size);
938*cf2f2c56Smiod bfd_elf32_swap_reloc_out (output_bfd, &outrel,
939*cf2f2c56Smiod sreloc->contents + reloc_offset);
940*cf2f2c56Smiod sreloc->reloc_count++;
941*cf2f2c56Smiod
942*cf2f2c56Smiod BFD_ASSERT (entry->dynrelocs > 0);
943*cf2f2c56Smiod entry->dynrelocs--;
944*cf2f2c56Smiod
945*cf2f2c56Smiod return reloc_offset;
946*cf2f2c56Smiod }
947*cf2f2c56Smiod
948*cf2f2c56Smiod /* Add a fixup to the ROFIXUP section. */
949*cf2f2c56Smiod
950*cf2f2c56Smiod static bfd_vma
_frvfdpic_add_rofixup(bfd * output_bfd,asection * rofixup,bfd_vma offset,struct frvfdpic_relocs_info * entry)951*cf2f2c56Smiod _frvfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
952*cf2f2c56Smiod struct frvfdpic_relocs_info *entry)
953*cf2f2c56Smiod {
954*cf2f2c56Smiod bfd_vma fixup_offset;
955*cf2f2c56Smiod
956*cf2f2c56Smiod if (rofixup->flags & SEC_EXCLUDE)
957*cf2f2c56Smiod return -1;
958*cf2f2c56Smiod
959*cf2f2c56Smiod fixup_offset = rofixup->reloc_count * 4;
960*cf2f2c56Smiod if (rofixup->contents)
961*cf2f2c56Smiod {
962*cf2f2c56Smiod BFD_ASSERT (fixup_offset < rofixup->_raw_size);
963*cf2f2c56Smiod bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
964*cf2f2c56Smiod }
965*cf2f2c56Smiod rofixup->reloc_count++;
966*cf2f2c56Smiod
967*cf2f2c56Smiod if (entry)
968*cf2f2c56Smiod {
969*cf2f2c56Smiod BFD_ASSERT (entry->fixups > 0);
970*cf2f2c56Smiod entry->fixups--;
971*cf2f2c56Smiod }
972*cf2f2c56Smiod
973*cf2f2c56Smiod return fixup_offset;
974*cf2f2c56Smiod }
975*cf2f2c56Smiod
976*cf2f2c56Smiod /* Find the segment number in which OSEC, and output section, is
977*cf2f2c56Smiod located. */
978*cf2f2c56Smiod
979*cf2f2c56Smiod static unsigned
_frvfdpic_osec_to_segment(bfd * output_bfd,asection * osec)980*cf2f2c56Smiod _frvfdpic_osec_to_segment (bfd *output_bfd, asection *osec)
981*cf2f2c56Smiod {
982*cf2f2c56Smiod struct elf_segment_map *m;
983*cf2f2c56Smiod Elf_Internal_Phdr *p;
984*cf2f2c56Smiod
985*cf2f2c56Smiod /* Find the segment that contains the output_section. */
986*cf2f2c56Smiod for (m = elf_tdata (output_bfd)->segment_map,
987*cf2f2c56Smiod p = elf_tdata (output_bfd)->phdr;
988*cf2f2c56Smiod m != NULL;
989*cf2f2c56Smiod m = m->next, p++)
990*cf2f2c56Smiod {
991*cf2f2c56Smiod int i;
992*cf2f2c56Smiod
993*cf2f2c56Smiod for (i = m->count - 1; i >= 0; i--)
994*cf2f2c56Smiod if (m->sections[i] == osec)
995*cf2f2c56Smiod break;
996*cf2f2c56Smiod
997*cf2f2c56Smiod if (i >= 0)
998*cf2f2c56Smiod break;
999*cf2f2c56Smiod }
1000*cf2f2c56Smiod
1001*cf2f2c56Smiod return p - elf_tdata (output_bfd)->phdr;
1002*cf2f2c56Smiod }
1003*cf2f2c56Smiod
1004*cf2f2c56Smiod inline static bfd_boolean
_frvfdpic_osec_readonly_p(bfd * output_bfd,asection * osec)1005*cf2f2c56Smiod _frvfdpic_osec_readonly_p (bfd *output_bfd, asection *osec)
1006*cf2f2c56Smiod {
1007*cf2f2c56Smiod unsigned seg = _frvfdpic_osec_to_segment (output_bfd, osec);
1008*cf2f2c56Smiod
1009*cf2f2c56Smiod return ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W);
1010*cf2f2c56Smiod }
1011*cf2f2c56Smiod
1012*cf2f2c56Smiod /* Generate relocations for GOT entries, function descriptors, and
1013*cf2f2c56Smiod code for PLT and lazy PLT entries. */
1014*cf2f2c56Smiod
1015*cf2f2c56Smiod inline static bfd_boolean
_frvfdpic_emit_got_relocs_plt_entries(struct frvfdpic_relocs_info * entry,bfd * output_bfd,struct bfd_link_info * info,asection * sec,Elf_Internal_Sym * sym,bfd_vma addend)1016*cf2f2c56Smiod _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry,
1017*cf2f2c56Smiod bfd *output_bfd,
1018*cf2f2c56Smiod struct bfd_link_info *info,
1019*cf2f2c56Smiod asection *sec,
1020*cf2f2c56Smiod Elf_Internal_Sym *sym,
1021*cf2f2c56Smiod bfd_vma addend)
1022*cf2f2c56Smiod
1023*cf2f2c56Smiod {
1024*cf2f2c56Smiod bfd_vma fd_lazy_rel_offset = (bfd_vma)-1;
1025*cf2f2c56Smiod int dynindx = -1;
1026*cf2f2c56Smiod
1027*cf2f2c56Smiod if (entry->done)
1028*cf2f2c56Smiod return TRUE;
1029*cf2f2c56Smiod entry->done = 1;
1030*cf2f2c56Smiod
1031*cf2f2c56Smiod if (entry->got_entry || entry->fdgot_entry || entry->fd_entry)
1032*cf2f2c56Smiod {
1033*cf2f2c56Smiod /* If the symbol is dynamic, consider it for dynamic
1034*cf2f2c56Smiod relocations, otherwise decay to section + offset. */
1035*cf2f2c56Smiod if (entry->symndx == -1 && entry->d.h->dynindx != -1)
1036*cf2f2c56Smiod dynindx = entry->d.h->dynindx;
1037*cf2f2c56Smiod else
1038*cf2f2c56Smiod {
1039*cf2f2c56Smiod if (sec->output_section
1040*cf2f2c56Smiod && ! bfd_is_abs_section (sec->output_section)
1041*cf2f2c56Smiod && ! bfd_is_und_section (sec->output_section))
1042*cf2f2c56Smiod dynindx = elf_section_data (sec->output_section)->dynindx;
1043*cf2f2c56Smiod else
1044*cf2f2c56Smiod dynindx = 0;
1045*cf2f2c56Smiod }
1046*cf2f2c56Smiod }
1047*cf2f2c56Smiod
1048*cf2f2c56Smiod /* Generate relocation for GOT entry pointing to the symbol. */
1049*cf2f2c56Smiod if (entry->got_entry)
1050*cf2f2c56Smiod {
1051*cf2f2c56Smiod int idx = dynindx;
1052*cf2f2c56Smiod bfd_vma ad = addend;
1053*cf2f2c56Smiod
1054*cf2f2c56Smiod /* If the symbol is dynamic but binds locally, use
1055*cf2f2c56Smiod section+offset. */
1056*cf2f2c56Smiod if (sec && (entry->symndx != -1
1057*cf2f2c56Smiod || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
1058*cf2f2c56Smiod {
1059*cf2f2c56Smiod if (entry->symndx == -1)
1060*cf2f2c56Smiod ad += entry->d.h->root.u.def.value;
1061*cf2f2c56Smiod else
1062*cf2f2c56Smiod ad += sym->st_value;
1063*cf2f2c56Smiod ad += sec->output_offset;
1064*cf2f2c56Smiod if (sec->output_section && elf_section_data (sec->output_section))
1065*cf2f2c56Smiod idx = elf_section_data (sec->output_section)->dynindx;
1066*cf2f2c56Smiod else
1067*cf2f2c56Smiod idx = 0;
1068*cf2f2c56Smiod }
1069*cf2f2c56Smiod
1070*cf2f2c56Smiod /* If we're linking an executable at a fixed address, we can
1071*cf2f2c56Smiod omit the dynamic relocation as long as the symbol is local to
1072*cf2f2c56Smiod this module. */
1073*cf2f2c56Smiod if (info->executable && !info->pie
1074*cf2f2c56Smiod && (entry->symndx != -1
1075*cf2f2c56Smiod || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
1076*cf2f2c56Smiod {
1077*cf2f2c56Smiod if (sec)
1078*cf2f2c56Smiod ad += sec->output_section->vma;
1079*cf2f2c56Smiod if (entry->symndx != -1
1080*cf2f2c56Smiod || entry->d.h->root.type != bfd_link_hash_undefweak)
1081*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd,
1082*cf2f2c56Smiod frvfdpic_gotfixup_section (info),
1083*cf2f2c56Smiod frvfdpic_got_section (info)->output_section
1084*cf2f2c56Smiod ->vma
1085*cf2f2c56Smiod + frvfdpic_got_section (info)->output_offset
1086*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1087*cf2f2c56Smiod + entry->got_entry, entry);
1088*cf2f2c56Smiod }
1089*cf2f2c56Smiod else
1090*cf2f2c56Smiod _frvfdpic_add_dyn_reloc (output_bfd, frvfdpic_gotrel_section (info),
1091*cf2f2c56Smiod _bfd_elf_section_offset
1092*cf2f2c56Smiod (output_bfd, info,
1093*cf2f2c56Smiod frvfdpic_got_section (info),
1094*cf2f2c56Smiod frvfdpic_got_initial_offset (info)
1095*cf2f2c56Smiod + entry->got_entry)
1096*cf2f2c56Smiod + frvfdpic_got_section (info)
1097*cf2f2c56Smiod ->output_section->vma
1098*cf2f2c56Smiod + frvfdpic_got_section (info)->output_offset,
1099*cf2f2c56Smiod R_FRV_32, idx, ad, entry);
1100*cf2f2c56Smiod
1101*cf2f2c56Smiod bfd_put_32 (output_bfd, ad,
1102*cf2f2c56Smiod frvfdpic_got_section (info)->contents
1103*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1104*cf2f2c56Smiod + entry->got_entry);
1105*cf2f2c56Smiod }
1106*cf2f2c56Smiod
1107*cf2f2c56Smiod /* Generate relocation for GOT entry pointing to a canonical
1108*cf2f2c56Smiod function descriptor. */
1109*cf2f2c56Smiod if (entry->fdgot_entry)
1110*cf2f2c56Smiod {
1111*cf2f2c56Smiod int reloc, idx;
1112*cf2f2c56Smiod bfd_vma ad = 0;
1113*cf2f2c56Smiod
1114*cf2f2c56Smiod if (! (entry->symndx == -1
1115*cf2f2c56Smiod && entry->d.h->root.type == bfd_link_hash_undefweak
1116*cf2f2c56Smiod && FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
1117*cf2f2c56Smiod {
1118*cf2f2c56Smiod /* If the symbol is dynamic and there may be dynamic symbol
1119*cf2f2c56Smiod resolution because we are, or are linked with, a shared
1120*cf2f2c56Smiod library, emit a FUNCDESC relocation such that the dynamic
1121*cf2f2c56Smiod linker will allocate the function descriptor. If the
1122*cf2f2c56Smiod symbol needs a non-local function descriptor but binds
1123*cf2f2c56Smiod locally (e.g., its visibility is protected, emit a
1124*cf2f2c56Smiod dynamic relocation decayed to section+offset. */
1125*cf2f2c56Smiod if (entry->symndx == -1
1126*cf2f2c56Smiod && ! FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h)
1127*cf2f2c56Smiod && FRVFDPIC_SYM_LOCAL (info, entry->d.h)
1128*cf2f2c56Smiod && !(info->executable && !info->pie))
1129*cf2f2c56Smiod {
1130*cf2f2c56Smiod reloc = R_FRV_FUNCDESC;
1131*cf2f2c56Smiod idx = elf_section_data (entry->d.h->root.u.def.section
1132*cf2f2c56Smiod ->output_section)->dynindx;
1133*cf2f2c56Smiod ad = entry->d.h->root.u.def.section->output_offset
1134*cf2f2c56Smiod + entry->d.h->root.u.def.value;
1135*cf2f2c56Smiod }
1136*cf2f2c56Smiod else if (entry->symndx == -1
1137*cf2f2c56Smiod && ! FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h))
1138*cf2f2c56Smiod {
1139*cf2f2c56Smiod reloc = R_FRV_FUNCDESC;
1140*cf2f2c56Smiod idx = dynindx;
1141*cf2f2c56Smiod ad = addend;
1142*cf2f2c56Smiod if (ad)
1143*cf2f2c56Smiod return FALSE;
1144*cf2f2c56Smiod }
1145*cf2f2c56Smiod else
1146*cf2f2c56Smiod {
1147*cf2f2c56Smiod /* Otherwise, we know we have a private function descriptor,
1148*cf2f2c56Smiod so reference it directly. */
1149*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
1150*cf2f2c56Smiod BFD_ASSERT (entry->privfd);
1151*cf2f2c56Smiod reloc = R_FRV_32;
1152*cf2f2c56Smiod idx = elf_section_data (frvfdpic_got_section (info)
1153*cf2f2c56Smiod ->output_section)->dynindx;
1154*cf2f2c56Smiod ad = frvfdpic_got_section (info)->output_offset
1155*cf2f2c56Smiod + frvfdpic_got_initial_offset (info) + entry->fd_entry;
1156*cf2f2c56Smiod }
1157*cf2f2c56Smiod
1158*cf2f2c56Smiod /* If there is room for dynamic symbol resolution, emit the
1159*cf2f2c56Smiod dynamic relocation. However, if we're linking an
1160*cf2f2c56Smiod executable at a fixed location, we won't have emitted a
1161*cf2f2c56Smiod dynamic symbol entry for the got section, so idx will be
1162*cf2f2c56Smiod zero, which means we can and should compute the address
1163*cf2f2c56Smiod of the private descriptor ourselves. */
1164*cf2f2c56Smiod if (info->executable && !info->pie
1165*cf2f2c56Smiod && (entry->symndx != -1
1166*cf2f2c56Smiod || FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h)))
1167*cf2f2c56Smiod {
1168*cf2f2c56Smiod ad += frvfdpic_got_section (info)->output_section->vma;
1169*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd,
1170*cf2f2c56Smiod frvfdpic_gotfixup_section (info),
1171*cf2f2c56Smiod frvfdpic_got_section (info)
1172*cf2f2c56Smiod ->output_section->vma
1173*cf2f2c56Smiod + frvfdpic_got_section (info)
1174*cf2f2c56Smiod ->output_offset
1175*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1176*cf2f2c56Smiod + entry->fdgot_entry, entry);
1177*cf2f2c56Smiod }
1178*cf2f2c56Smiod else
1179*cf2f2c56Smiod _frvfdpic_add_dyn_reloc (output_bfd,
1180*cf2f2c56Smiod frvfdpic_gotrel_section (info),
1181*cf2f2c56Smiod _bfd_elf_section_offset
1182*cf2f2c56Smiod (output_bfd, info,
1183*cf2f2c56Smiod frvfdpic_got_section (info),
1184*cf2f2c56Smiod frvfdpic_got_initial_offset (info)
1185*cf2f2c56Smiod + entry->fdgot_entry)
1186*cf2f2c56Smiod + frvfdpic_got_section (info)
1187*cf2f2c56Smiod ->output_section->vma
1188*cf2f2c56Smiod + frvfdpic_got_section (info)
1189*cf2f2c56Smiod ->output_offset,
1190*cf2f2c56Smiod reloc, idx, ad, entry);
1191*cf2f2c56Smiod }
1192*cf2f2c56Smiod
1193*cf2f2c56Smiod bfd_put_32 (output_bfd, ad,
1194*cf2f2c56Smiod frvfdpic_got_section (info)->contents
1195*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1196*cf2f2c56Smiod + entry->fdgot_entry);
1197*cf2f2c56Smiod }
1198*cf2f2c56Smiod
1199*cf2f2c56Smiod /* Generate relocation to fill in a private function descriptor in
1200*cf2f2c56Smiod the GOT. */
1201*cf2f2c56Smiod if (entry->fd_entry)
1202*cf2f2c56Smiod {
1203*cf2f2c56Smiod int idx = dynindx;
1204*cf2f2c56Smiod bfd_vma ad = addend;
1205*cf2f2c56Smiod bfd_vma ofst;
1206*cf2f2c56Smiod long lowword, highword;
1207*cf2f2c56Smiod
1208*cf2f2c56Smiod /* If the symbol is dynamic but binds locally, use
1209*cf2f2c56Smiod section+offset. */
1210*cf2f2c56Smiod if (sec && (entry->symndx != -1
1211*cf2f2c56Smiod || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
1212*cf2f2c56Smiod {
1213*cf2f2c56Smiod if (entry->symndx == -1)
1214*cf2f2c56Smiod ad += entry->d.h->root.u.def.value;
1215*cf2f2c56Smiod else
1216*cf2f2c56Smiod ad += sym->st_value;
1217*cf2f2c56Smiod ad += sec->output_offset;
1218*cf2f2c56Smiod if (sec->output_section && elf_section_data (sec->output_section))
1219*cf2f2c56Smiod idx = elf_section_data (sec->output_section)->dynindx;
1220*cf2f2c56Smiod else
1221*cf2f2c56Smiod idx = 0;
1222*cf2f2c56Smiod }
1223*cf2f2c56Smiod
1224*cf2f2c56Smiod /* If we're linking an executable at a fixed address, we can
1225*cf2f2c56Smiod omit the dynamic relocation as long as the symbol is local to
1226*cf2f2c56Smiod this module. */
1227*cf2f2c56Smiod if (info->executable && !info->pie
1228*cf2f2c56Smiod && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
1229*cf2f2c56Smiod {
1230*cf2f2c56Smiod if (sec)
1231*cf2f2c56Smiod ad += sec->output_section->vma;
1232*cf2f2c56Smiod ofst = 0;
1233*cf2f2c56Smiod if (entry->symndx != -1
1234*cf2f2c56Smiod || entry->d.h->root.type != bfd_link_hash_undefweak)
1235*cf2f2c56Smiod {
1236*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd,
1237*cf2f2c56Smiod frvfdpic_gotfixup_section (info),
1238*cf2f2c56Smiod frvfdpic_got_section (info)
1239*cf2f2c56Smiod ->output_section->vma
1240*cf2f2c56Smiod + frvfdpic_got_section (info)
1241*cf2f2c56Smiod ->output_offset
1242*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1243*cf2f2c56Smiod + entry->fd_entry, entry);
1244*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd,
1245*cf2f2c56Smiod frvfdpic_gotfixup_section (info),
1246*cf2f2c56Smiod frvfdpic_got_section (info)
1247*cf2f2c56Smiod ->output_section->vma
1248*cf2f2c56Smiod + frvfdpic_got_section (info)
1249*cf2f2c56Smiod ->output_offset
1250*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1251*cf2f2c56Smiod + entry->fd_entry + 4, entry);
1252*cf2f2c56Smiod }
1253*cf2f2c56Smiod }
1254*cf2f2c56Smiod else
1255*cf2f2c56Smiod {
1256*cf2f2c56Smiod ofst =
1257*cf2f2c56Smiod _frvfdpic_add_dyn_reloc (output_bfd,
1258*cf2f2c56Smiod entry->lazyplt
1259*cf2f2c56Smiod ? frvfdpic_pltrel_section (info)
1260*cf2f2c56Smiod : frvfdpic_gotrel_section (info),
1261*cf2f2c56Smiod _bfd_elf_section_offset
1262*cf2f2c56Smiod (output_bfd, info,
1263*cf2f2c56Smiod frvfdpic_got_section (info),
1264*cf2f2c56Smiod frvfdpic_got_initial_offset (info)
1265*cf2f2c56Smiod + entry->fd_entry)
1266*cf2f2c56Smiod + frvfdpic_got_section (info)
1267*cf2f2c56Smiod ->output_section->vma
1268*cf2f2c56Smiod + frvfdpic_got_section (info)
1269*cf2f2c56Smiod ->output_offset,
1270*cf2f2c56Smiod R_FRV_FUNCDESC_VALUE, idx, ad, entry);
1271*cf2f2c56Smiod }
1272*cf2f2c56Smiod
1273*cf2f2c56Smiod /* If we've omitted the dynamic relocation, just emit the fixed
1274*cf2f2c56Smiod addresses of the symbol and of the local GOT base offset. */
1275*cf2f2c56Smiod if (info->executable && !info->pie && sec && sec->output_section)
1276*cf2f2c56Smiod {
1277*cf2f2c56Smiod lowword = ad;
1278*cf2f2c56Smiod highword = frvfdpic_got_section (info)->output_section->vma
1279*cf2f2c56Smiod + frvfdpic_got_section (info)->output_offset
1280*cf2f2c56Smiod + frvfdpic_got_initial_offset (info);
1281*cf2f2c56Smiod }
1282*cf2f2c56Smiod else if (entry->lazyplt)
1283*cf2f2c56Smiod {
1284*cf2f2c56Smiod if (ad)
1285*cf2f2c56Smiod return FALSE;
1286*cf2f2c56Smiod
1287*cf2f2c56Smiod fd_lazy_rel_offset = ofst;
1288*cf2f2c56Smiod
1289*cf2f2c56Smiod /* A function descriptor used for lazy or local resolving is
1290*cf2f2c56Smiod initialized such that its high word contains the output
1291*cf2f2c56Smiod section index in which the PLT entries are located, and
1292*cf2f2c56Smiod the low word contains the address of the lazy PLT entry
1293*cf2f2c56Smiod entry point, that must be within the memory region
1294*cf2f2c56Smiod assigned to that section. */
1295*cf2f2c56Smiod lowword = entry->lzplt_entry + 4
1296*cf2f2c56Smiod + frvfdpic_plt_section (info)->output_offset
1297*cf2f2c56Smiod + frvfdpic_plt_section (info)->output_section->vma;
1298*cf2f2c56Smiod highword = _frvfdpic_osec_to_segment
1299*cf2f2c56Smiod (output_bfd, frvfdpic_plt_section (info)->output_section);
1300*cf2f2c56Smiod }
1301*cf2f2c56Smiod else
1302*cf2f2c56Smiod {
1303*cf2f2c56Smiod /* A function descriptor for a local function gets the index
1304*cf2f2c56Smiod of the section. For a non-local function, it's
1305*cf2f2c56Smiod disregarded. */
1306*cf2f2c56Smiod lowword = ad;
1307*cf2f2c56Smiod if (entry->symndx == -1 && entry->d.h->dynindx != -1
1308*cf2f2c56Smiod && entry->d.h->dynindx == idx)
1309*cf2f2c56Smiod highword = 0;
1310*cf2f2c56Smiod else
1311*cf2f2c56Smiod highword = _frvfdpic_osec_to_segment
1312*cf2f2c56Smiod (output_bfd, sec->output_section);
1313*cf2f2c56Smiod }
1314*cf2f2c56Smiod
1315*cf2f2c56Smiod bfd_put_32 (output_bfd, lowword,
1316*cf2f2c56Smiod frvfdpic_got_section (info)->contents
1317*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1318*cf2f2c56Smiod + entry->fd_entry);
1319*cf2f2c56Smiod bfd_put_32 (output_bfd, highword,
1320*cf2f2c56Smiod frvfdpic_got_section (info)->contents
1321*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
1322*cf2f2c56Smiod + entry->fd_entry + 4);
1323*cf2f2c56Smiod }
1324*cf2f2c56Smiod
1325*cf2f2c56Smiod /* Generate code for the PLT entry. */
1326*cf2f2c56Smiod if (entry->plt_entry != (bfd_vma) -1)
1327*cf2f2c56Smiod {
1328*cf2f2c56Smiod bfd_byte *plt_code = frvfdpic_plt_section (info)->contents
1329*cf2f2c56Smiod + entry->plt_entry;
1330*cf2f2c56Smiod
1331*cf2f2c56Smiod BFD_ASSERT (entry->fd_entry);
1332*cf2f2c56Smiod
1333*cf2f2c56Smiod /* Figure out what kind of PLT entry we need, depending on the
1334*cf2f2c56Smiod location of the function descriptor within the GOT. */
1335*cf2f2c56Smiod if (entry->fd_entry >= -(1 << (12 - 1))
1336*cf2f2c56Smiod && entry->fd_entry < (1 << (12 - 1)))
1337*cf2f2c56Smiod {
1338*cf2f2c56Smiod /* lddi @(gr15, fd_entry), gr14 */
1339*cf2f2c56Smiod bfd_put_32 (output_bfd,
1340*cf2f2c56Smiod 0x9cccf000 | (entry->fd_entry & ((1 << 12) - 1)),
1341*cf2f2c56Smiod plt_code);
1342*cf2f2c56Smiod plt_code += 4;
1343*cf2f2c56Smiod }
1344*cf2f2c56Smiod else
1345*cf2f2c56Smiod {
1346*cf2f2c56Smiod if (entry->fd_entry >= -(1 << (16 - 1))
1347*cf2f2c56Smiod && entry->fd_entry < (1 << (16 - 1)))
1348*cf2f2c56Smiod {
1349*cf2f2c56Smiod /* setlos lo(fd_entry), gr14 */
1350*cf2f2c56Smiod bfd_put_32 (output_bfd,
1351*cf2f2c56Smiod 0x9cfc0000
1352*cf2f2c56Smiod | (entry->fd_entry & (((bfd_vma)1 << 16) - 1)),
1353*cf2f2c56Smiod plt_code);
1354*cf2f2c56Smiod plt_code += 4;
1355*cf2f2c56Smiod }
1356*cf2f2c56Smiod else
1357*cf2f2c56Smiod {
1358*cf2f2c56Smiod /* sethi.p hi(fd_entry), gr14
1359*cf2f2c56Smiod setlo lo(fd_entry), gr14 */
1360*cf2f2c56Smiod bfd_put_32 (output_bfd,
1361*cf2f2c56Smiod 0x1cf80000
1362*cf2f2c56Smiod | ((entry->fd_entry >> 16)
1363*cf2f2c56Smiod & (((bfd_vma)1 << 16) - 1)),
1364*cf2f2c56Smiod plt_code);
1365*cf2f2c56Smiod bfd_put_32 (output_bfd,
1366*cf2f2c56Smiod 0x9cf40000
1367*cf2f2c56Smiod | (entry->fd_entry & (((bfd_vma)1 << 16) - 1)),
1368*cf2f2c56Smiod plt_code);
1369*cf2f2c56Smiod plt_code += 8;
1370*cf2f2c56Smiod }
1371*cf2f2c56Smiod /* ldd @(gr14,gr15),gr14 */
1372*cf2f2c56Smiod bfd_put_32 (output_bfd, 0x9c08e14f, plt_code);
1373*cf2f2c56Smiod plt_code += 4;
1374*cf2f2c56Smiod }
1375*cf2f2c56Smiod /* jmpl @(gr14,gr0) */
1376*cf2f2c56Smiod bfd_put_32 (output_bfd, 0x8030e000, plt_code);
1377*cf2f2c56Smiod }
1378*cf2f2c56Smiod
1379*cf2f2c56Smiod /* Generate code for the lazy PLT entry. */
1380*cf2f2c56Smiod if (entry->lzplt_entry != (bfd_vma) -1)
1381*cf2f2c56Smiod {
1382*cf2f2c56Smiod bfd_byte *lzplt_code = frvfdpic_plt_section (info)->contents
1383*cf2f2c56Smiod + entry->lzplt_entry;
1384*cf2f2c56Smiod bfd_vma resolverStub_addr;
1385*cf2f2c56Smiod
1386*cf2f2c56Smiod bfd_put_32 (output_bfd, fd_lazy_rel_offset, lzplt_code);
1387*cf2f2c56Smiod lzplt_code += 4;
1388*cf2f2c56Smiod
1389*cf2f2c56Smiod resolverStub_addr = entry->lzplt_entry / FRVFDPIC_LZPLT_BLOCK_SIZE
1390*cf2f2c56Smiod * FRVFDPIC_LZPLT_BLOCK_SIZE + FRVFDPIC_LZPLT_RESOLV_LOC;
1391*cf2f2c56Smiod if (resolverStub_addr >= frvfdpic_plt_initial_offset (info))
1392*cf2f2c56Smiod resolverStub_addr = frvfdpic_plt_initial_offset (info) - 12;
1393*cf2f2c56Smiod
1394*cf2f2c56Smiod if (entry->lzplt_entry == resolverStub_addr)
1395*cf2f2c56Smiod {
1396*cf2f2c56Smiod /* This is a lazy PLT entry that includes a resolver call. */
1397*cf2f2c56Smiod /* ldd @(gr15,gr0), gr4
1398*cf2f2c56Smiod jmpl @(gr4,gr0) */
1399*cf2f2c56Smiod bfd_put_32 (output_bfd, 0x8808f140, lzplt_code);
1400*cf2f2c56Smiod bfd_put_32 (output_bfd, 0x80304000, lzplt_code + 4);
1401*cf2f2c56Smiod }
1402*cf2f2c56Smiod else
1403*cf2f2c56Smiod {
1404*cf2f2c56Smiod /* bra resolverStub */
1405*cf2f2c56Smiod bfd_put_32 (output_bfd,
1406*cf2f2c56Smiod 0xc01a0000
1407*cf2f2c56Smiod | (((resolverStub_addr - entry->lzplt_entry)
1408*cf2f2c56Smiod / 4) & (((bfd_vma)1 << 16) - 1)),
1409*cf2f2c56Smiod lzplt_code);
1410*cf2f2c56Smiod }
1411*cf2f2c56Smiod }
1412*cf2f2c56Smiod
1413*cf2f2c56Smiod return TRUE;
1414*cf2f2c56Smiod }
1415*cf2f2c56Smiod
1416d2201f2fSdrahn /* Handle an FRV small data reloc. */
1417d2201f2fSdrahn
1418d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_gprel12(info,input_bfd,input_section,relocation,contents,value)1419d2201f2fSdrahn elf32_frv_relocate_gprel12 (info, input_bfd, input_section, relocation,
1420d2201f2fSdrahn contents, value)
1421d2201f2fSdrahn struct bfd_link_info *info;
1422d2201f2fSdrahn bfd *input_bfd;
1423d2201f2fSdrahn asection *input_section;
1424d2201f2fSdrahn Elf_Internal_Rela *relocation;
1425d2201f2fSdrahn bfd_byte *contents;
1426d2201f2fSdrahn bfd_vma value;
1427d2201f2fSdrahn {
1428d2201f2fSdrahn bfd_vma insn;
1429d2201f2fSdrahn bfd_vma gp;
1430d2201f2fSdrahn struct bfd_link_hash_entry *h;
1431d2201f2fSdrahn
1432d2201f2fSdrahn h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
1433d2201f2fSdrahn
1434d2201f2fSdrahn gp = (h->u.def.value
1435d2201f2fSdrahn + h->u.def.section->output_section->vma
1436d2201f2fSdrahn + h->u.def.section->output_offset);
1437d2201f2fSdrahn
1438d2201f2fSdrahn value -= input_section->output_section->vma;
1439d2201f2fSdrahn value -= (gp - input_section->output_section->vma);
1440d2201f2fSdrahn
1441d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
1442d2201f2fSdrahn
1443d2201f2fSdrahn value += relocation->r_addend;
1444d2201f2fSdrahn
1445d2201f2fSdrahn if ((long) value > 0x7ff || (long) value < -0x800)
1446d2201f2fSdrahn return bfd_reloc_overflow;
1447d2201f2fSdrahn
1448d2201f2fSdrahn bfd_put_32 (input_bfd,
1449d2201f2fSdrahn (insn & 0xfffff000) | (value & 0xfff),
1450d2201f2fSdrahn contents + relocation->r_offset);
1451d2201f2fSdrahn
1452d2201f2fSdrahn return bfd_reloc_ok;
1453d2201f2fSdrahn }
1454d2201f2fSdrahn
1455d2201f2fSdrahn /* Handle an FRV small data reloc. for the u12 field. */
1456d2201f2fSdrahn
1457d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_gprelu12(info,input_bfd,input_section,relocation,contents,value)1458d2201f2fSdrahn elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, relocation,
1459d2201f2fSdrahn contents, value)
1460d2201f2fSdrahn struct bfd_link_info *info;
1461d2201f2fSdrahn bfd *input_bfd;
1462d2201f2fSdrahn asection *input_section;
1463d2201f2fSdrahn Elf_Internal_Rela *relocation;
1464d2201f2fSdrahn bfd_byte *contents;
1465d2201f2fSdrahn bfd_vma value;
1466d2201f2fSdrahn {
1467d2201f2fSdrahn bfd_vma insn;
1468d2201f2fSdrahn bfd_vma gp;
1469d2201f2fSdrahn struct bfd_link_hash_entry *h;
1470d2201f2fSdrahn bfd_vma mask;
1471d2201f2fSdrahn
1472d2201f2fSdrahn h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
1473d2201f2fSdrahn
1474d2201f2fSdrahn gp = (h->u.def.value
1475d2201f2fSdrahn + h->u.def.section->output_section->vma
1476d2201f2fSdrahn + h->u.def.section->output_offset);
1477d2201f2fSdrahn
1478d2201f2fSdrahn value -= input_section->output_section->vma;
1479d2201f2fSdrahn value -= (gp - input_section->output_section->vma);
1480d2201f2fSdrahn
1481d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
1482d2201f2fSdrahn
1483d2201f2fSdrahn value += relocation->r_addend;
1484d2201f2fSdrahn
1485d2201f2fSdrahn if ((long) value > 0x7ff || (long) value < -0x800)
1486d2201f2fSdrahn return bfd_reloc_overflow;
1487d2201f2fSdrahn
1488d2201f2fSdrahn /* The high 6 bits go into bits 17-12. The low 6 bits go into bits 5-0. */
1489d2201f2fSdrahn mask = 0x3f03f;
1490d2201f2fSdrahn insn = (insn & ~mask) | ((value & 0xfc0) << 12) | (value & 0x3f);
1491d2201f2fSdrahn
1492d2201f2fSdrahn bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
1493d2201f2fSdrahn
1494d2201f2fSdrahn return bfd_reloc_ok;
1495d2201f2fSdrahn }
1496d2201f2fSdrahn
1497d2201f2fSdrahn /* Handle an FRV ELF HI16 reloc. */
1498d2201f2fSdrahn
1499d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_hi16(input_bfd,relhi,contents,value)1500d2201f2fSdrahn elf32_frv_relocate_hi16 (input_bfd, relhi, contents, value)
1501d2201f2fSdrahn bfd *input_bfd;
1502d2201f2fSdrahn Elf_Internal_Rela *relhi;
1503d2201f2fSdrahn bfd_byte *contents;
1504d2201f2fSdrahn bfd_vma value;
1505d2201f2fSdrahn {
1506d2201f2fSdrahn bfd_vma insn;
1507d2201f2fSdrahn
1508d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
1509d2201f2fSdrahn
1510d2201f2fSdrahn value += relhi->r_addend;
1511d2201f2fSdrahn value = ((value >> 16) & 0xffff);
1512d2201f2fSdrahn
1513d2201f2fSdrahn insn = (insn & 0xffff0000) | value;
1514d2201f2fSdrahn
1515d2201f2fSdrahn if ((long) value > 0xffff || (long) value < -0x10000)
1516d2201f2fSdrahn return bfd_reloc_overflow;
1517d2201f2fSdrahn
1518d2201f2fSdrahn bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
1519d2201f2fSdrahn return bfd_reloc_ok;
1520d2201f2fSdrahn
1521d2201f2fSdrahn }
1522d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_lo16(input_bfd,rello,contents,value)1523d2201f2fSdrahn elf32_frv_relocate_lo16 (input_bfd, rello, contents, value)
1524d2201f2fSdrahn bfd *input_bfd;
1525d2201f2fSdrahn Elf_Internal_Rela *rello;
1526d2201f2fSdrahn bfd_byte *contents;
1527d2201f2fSdrahn bfd_vma value;
1528d2201f2fSdrahn {
1529d2201f2fSdrahn bfd_vma insn;
1530d2201f2fSdrahn
1531d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
1532d2201f2fSdrahn
1533d2201f2fSdrahn value += rello->r_addend;
1534d2201f2fSdrahn value = value & 0xffff;
1535d2201f2fSdrahn
1536d2201f2fSdrahn insn = (insn & 0xffff0000) | value;
1537d2201f2fSdrahn
1538d2201f2fSdrahn if ((long) value > 0xffff || (long) value < -0x10000)
1539d2201f2fSdrahn return bfd_reloc_overflow;
1540d2201f2fSdrahn
1541d2201f2fSdrahn bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
1542d2201f2fSdrahn return bfd_reloc_ok;
1543d2201f2fSdrahn }
1544d2201f2fSdrahn
1545d2201f2fSdrahn /* Perform the relocation for the CALL label24 instruction. */
1546d2201f2fSdrahn
1547d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_label24(input_bfd,input_section,rello,contents,value)1548d2201f2fSdrahn elf32_frv_relocate_label24 (input_bfd, input_section, rello, contents, value)
1549d2201f2fSdrahn bfd *input_bfd;
1550d2201f2fSdrahn asection *input_section;
1551d2201f2fSdrahn Elf_Internal_Rela *rello;
1552d2201f2fSdrahn bfd_byte *contents;
1553d2201f2fSdrahn bfd_vma value;
1554d2201f2fSdrahn {
1555d2201f2fSdrahn bfd_vma insn;
1556d2201f2fSdrahn bfd_vma label6;
1557d2201f2fSdrahn bfd_vma label18;
1558d2201f2fSdrahn
1559d2201f2fSdrahn /* The format for the call instruction is:
1560d2201f2fSdrahn
1561d2201f2fSdrahn 0 000000 0001111 000000000000000000
1562d2201f2fSdrahn label6 opcode label18
1563d2201f2fSdrahn
1564d2201f2fSdrahn The branch calculation is: pc + (4*label24)
1565d2201f2fSdrahn where label24 is the concatenation of label6 and label18. */
1566d2201f2fSdrahn
1567d2201f2fSdrahn /* Grab the instruction. */
1568d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
1569d2201f2fSdrahn
1570d2201f2fSdrahn value -= input_section->output_section->vma + input_section->output_offset;
1571d2201f2fSdrahn value -= rello->r_offset;
1572d2201f2fSdrahn value += rello->r_addend;
1573d2201f2fSdrahn
1574d2201f2fSdrahn value = value >> 2;
1575d2201f2fSdrahn
1576d2201f2fSdrahn label6 = value & 0xfc0000;
1577d2201f2fSdrahn label6 = label6 << 7;
1578d2201f2fSdrahn
1579d2201f2fSdrahn label18 = value & 0x3ffff;
1580d2201f2fSdrahn
1581d2201f2fSdrahn insn = insn & 0x803c0000;
1582d2201f2fSdrahn insn = insn | label6;
1583d2201f2fSdrahn insn = insn | label18;
1584d2201f2fSdrahn
1585d2201f2fSdrahn bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
1586d2201f2fSdrahn
1587d2201f2fSdrahn return bfd_reloc_ok;
1588d2201f2fSdrahn }
1589d2201f2fSdrahn
1590d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_gprelhi(info,input_bfd,input_section,relocation,contents,value)1591d2201f2fSdrahn elf32_frv_relocate_gprelhi (info, input_bfd, input_section, relocation,
1592d2201f2fSdrahn contents, value)
1593d2201f2fSdrahn struct bfd_link_info *info;
1594d2201f2fSdrahn bfd *input_bfd;
1595d2201f2fSdrahn asection *input_section;
1596d2201f2fSdrahn Elf_Internal_Rela *relocation;
1597d2201f2fSdrahn bfd_byte *contents;
1598d2201f2fSdrahn bfd_vma value;
1599d2201f2fSdrahn {
1600d2201f2fSdrahn bfd_vma insn;
1601d2201f2fSdrahn bfd_vma gp;
1602d2201f2fSdrahn struct bfd_link_hash_entry *h;
1603d2201f2fSdrahn
1604d2201f2fSdrahn h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
1605d2201f2fSdrahn
1606d2201f2fSdrahn gp = (h->u.def.value
1607d2201f2fSdrahn + h->u.def.section->output_section->vma
1608d2201f2fSdrahn + h->u.def.section->output_offset);
1609d2201f2fSdrahn
1610d2201f2fSdrahn value -= input_section->output_section->vma;
1611d2201f2fSdrahn value -= (gp - input_section->output_section->vma);
1612d2201f2fSdrahn value += relocation->r_addend;
1613d2201f2fSdrahn value = ((value >> 16) & 0xffff);
1614d2201f2fSdrahn
1615d2201f2fSdrahn if ((long) value > 0xffff || (long) value < -0x10000)
1616d2201f2fSdrahn return bfd_reloc_overflow;
1617d2201f2fSdrahn
1618d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
1619d2201f2fSdrahn insn = (insn & 0xffff0000) | value;
1620d2201f2fSdrahn
1621d2201f2fSdrahn bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
1622d2201f2fSdrahn return bfd_reloc_ok;
1623d2201f2fSdrahn }
1624d2201f2fSdrahn
1625d2201f2fSdrahn static bfd_reloc_status_type
elf32_frv_relocate_gprello(info,input_bfd,input_section,relocation,contents,value)1626d2201f2fSdrahn elf32_frv_relocate_gprello (info, input_bfd, input_section, relocation,
1627d2201f2fSdrahn contents, value)
1628d2201f2fSdrahn struct bfd_link_info *info;
1629d2201f2fSdrahn bfd *input_bfd;
1630d2201f2fSdrahn asection *input_section;
1631d2201f2fSdrahn Elf_Internal_Rela *relocation;
1632d2201f2fSdrahn bfd_byte *contents;
1633d2201f2fSdrahn bfd_vma value;
1634d2201f2fSdrahn {
1635d2201f2fSdrahn bfd_vma insn;
1636d2201f2fSdrahn bfd_vma gp;
1637d2201f2fSdrahn struct bfd_link_hash_entry *h;
1638d2201f2fSdrahn
1639d2201f2fSdrahn h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
1640d2201f2fSdrahn
1641d2201f2fSdrahn gp = (h->u.def.value
1642d2201f2fSdrahn + h->u.def.section->output_section->vma
1643d2201f2fSdrahn + h->u.def.section->output_offset);
1644d2201f2fSdrahn
1645d2201f2fSdrahn value -= input_section->output_section->vma;
1646d2201f2fSdrahn value -= (gp - input_section->output_section->vma);
1647d2201f2fSdrahn value += relocation->r_addend;
1648d2201f2fSdrahn value = value & 0xffff;
1649d2201f2fSdrahn
1650d2201f2fSdrahn if ((long) value > 0xffff || (long) value < -0x10000)
1651d2201f2fSdrahn return bfd_reloc_overflow;
1652d2201f2fSdrahn
1653d2201f2fSdrahn insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
1654d2201f2fSdrahn insn = (insn & 0xffff0000) | value;
1655d2201f2fSdrahn
1656d2201f2fSdrahn bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
1657d2201f2fSdrahn
1658d2201f2fSdrahn return bfd_reloc_ok;
1659d2201f2fSdrahn }
1660d2201f2fSdrahn
1661d2201f2fSdrahn static reloc_howto_type *
frv_reloc_type_lookup(abfd,code)1662d2201f2fSdrahn frv_reloc_type_lookup (abfd, code)
1663d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
1664d2201f2fSdrahn bfd_reloc_code_real_type code;
1665d2201f2fSdrahn {
1666d2201f2fSdrahn switch (code)
1667d2201f2fSdrahn {
1668d2201f2fSdrahn default:
1669d2201f2fSdrahn break;
1670d2201f2fSdrahn
1671d2201f2fSdrahn case BFD_RELOC_NONE:
1672d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_NONE];
1673d2201f2fSdrahn
1674d2201f2fSdrahn case BFD_RELOC_32:
1675*cf2f2c56Smiod if (elf_elfheader (abfd)->e_type == ET_EXEC
1676*cf2f2c56Smiod || elf_elfheader (abfd)->e_type == ET_DYN)
1677*cf2f2c56Smiod return &elf32_frv_rel_32_howto;
1678*cf2f2c56Smiod /* Fall through. */
1679d2201f2fSdrahn case BFD_RELOC_CTOR:
1680d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_32];
1681d2201f2fSdrahn
1682d2201f2fSdrahn case BFD_RELOC_FRV_LABEL16:
1683d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_LABEL16];
1684d2201f2fSdrahn
1685d2201f2fSdrahn case BFD_RELOC_FRV_LABEL24:
1686d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_LABEL24];
1687d2201f2fSdrahn
1688d2201f2fSdrahn case BFD_RELOC_FRV_LO16:
1689d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_LO16];
1690d2201f2fSdrahn
1691d2201f2fSdrahn case BFD_RELOC_FRV_HI16:
1692d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_HI16];
1693d2201f2fSdrahn
1694d2201f2fSdrahn case BFD_RELOC_FRV_GPREL12:
1695d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_GPREL12];
1696d2201f2fSdrahn
1697d2201f2fSdrahn case BFD_RELOC_FRV_GPRELU12:
1698d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_GPRELU12];
1699d2201f2fSdrahn
1700d2201f2fSdrahn case BFD_RELOC_FRV_GPREL32:
1701d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_GPREL32];
1702d2201f2fSdrahn
1703d2201f2fSdrahn case BFD_RELOC_FRV_GPRELHI:
1704d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_GPRELHI];
1705d2201f2fSdrahn
1706d2201f2fSdrahn case BFD_RELOC_FRV_GPRELLO:
1707d2201f2fSdrahn return &elf32_frv_howto_table[ (int) R_FRV_GPRELLO];
1708d2201f2fSdrahn
1709*cf2f2c56Smiod case BFD_RELOC_FRV_GOT12:
1710*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_GOT12];
1711*cf2f2c56Smiod
1712*cf2f2c56Smiod case BFD_RELOC_FRV_GOTHI:
1713*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_GOTHI];
1714*cf2f2c56Smiod
1715*cf2f2c56Smiod case BFD_RELOC_FRV_GOTLO:
1716*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_GOTLO];
1717*cf2f2c56Smiod
1718*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC:
1719*cf2f2c56Smiod if (elf_elfheader (abfd)->e_type == ET_EXEC
1720*cf2f2c56Smiod || elf_elfheader (abfd)->e_type == ET_DYN)
1721*cf2f2c56Smiod return &elf32_frv_rel_funcdesc_howto;
1722*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC];
1723*cf2f2c56Smiod
1724*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_GOT12:
1725*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_GOT12];
1726*cf2f2c56Smiod
1727*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_GOTHI:
1728*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_GOTHI];
1729*cf2f2c56Smiod
1730*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_GOTLO:
1731*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_GOTLO];
1732*cf2f2c56Smiod
1733*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_VALUE:
1734*cf2f2c56Smiod if (elf_elfheader (abfd)->e_type == ET_EXEC
1735*cf2f2c56Smiod || elf_elfheader (abfd)->e_type == ET_DYN)
1736*cf2f2c56Smiod return &elf32_frv_rel_funcdesc_value_howto;
1737*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_VALUE];
1738*cf2f2c56Smiod
1739*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1740*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_GOTOFF12];
1741*cf2f2c56Smiod
1742*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1743*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_GOTOFFHI];
1744*cf2f2c56Smiod
1745*cf2f2c56Smiod case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1746*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_FUNCDESC_GOTOFFLO];
1747*cf2f2c56Smiod
1748*cf2f2c56Smiod case BFD_RELOC_FRV_GOTOFF12:
1749*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_GOTOFF12];
1750*cf2f2c56Smiod
1751*cf2f2c56Smiod case BFD_RELOC_FRV_GOTOFFHI:
1752*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_GOTOFFHI];
1753*cf2f2c56Smiod
1754*cf2f2c56Smiod case BFD_RELOC_FRV_GOTOFFLO:
1755*cf2f2c56Smiod return &elf32_frv_howto_table[ (int) R_FRV_GOTOFFLO];
1756*cf2f2c56Smiod
1757d2201f2fSdrahn case BFD_RELOC_VTABLE_INHERIT:
1758d2201f2fSdrahn return &elf32_frv_vtinherit_howto;
1759d2201f2fSdrahn
1760d2201f2fSdrahn case BFD_RELOC_VTABLE_ENTRY:
1761d2201f2fSdrahn return &elf32_frv_vtentry_howto;
1762d2201f2fSdrahn }
1763d2201f2fSdrahn
1764d2201f2fSdrahn return NULL;
1765d2201f2fSdrahn }
1766d2201f2fSdrahn
1767d2201f2fSdrahn /* Set the howto pointer for an FRV ELF reloc. */
1768d2201f2fSdrahn
1769d2201f2fSdrahn static void
frv_info_to_howto_rela(abfd,cache_ptr,dst)1770d2201f2fSdrahn frv_info_to_howto_rela (abfd, cache_ptr, dst)
1771d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
1772d2201f2fSdrahn arelent *cache_ptr;
1773d2201f2fSdrahn Elf_Internal_Rela *dst;
1774d2201f2fSdrahn {
1775d2201f2fSdrahn unsigned int r_type;
1776d2201f2fSdrahn
1777d2201f2fSdrahn r_type = ELF32_R_TYPE (dst->r_info);
1778d2201f2fSdrahn switch (r_type)
1779d2201f2fSdrahn {
1780d2201f2fSdrahn case R_FRV_GNU_VTINHERIT:
1781d2201f2fSdrahn cache_ptr->howto = &elf32_frv_vtinherit_howto;
1782d2201f2fSdrahn break;
1783d2201f2fSdrahn
1784d2201f2fSdrahn case R_FRV_GNU_VTENTRY:
1785d2201f2fSdrahn cache_ptr->howto = &elf32_frv_vtentry_howto;
1786d2201f2fSdrahn break;
1787d2201f2fSdrahn
1788d2201f2fSdrahn default:
1789d2201f2fSdrahn cache_ptr->howto = & elf32_frv_howto_table [r_type];
1790d2201f2fSdrahn break;
1791d2201f2fSdrahn }
1792d2201f2fSdrahn }
1793*cf2f2c56Smiod
1794*cf2f2c56Smiod /* Set the howto pointer for an FRV ELF REL reloc. */
1795*cf2f2c56Smiod static void
frvfdpic_info_to_howto_rel(bfd * abfd ATTRIBUTE_UNUSED,arelent * cache_ptr,Elf_Internal_Rela * dst)1796*cf2f2c56Smiod frvfdpic_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
1797*cf2f2c56Smiod arelent *cache_ptr, Elf_Internal_Rela *dst)
1798*cf2f2c56Smiod {
1799*cf2f2c56Smiod unsigned int r_type;
1800*cf2f2c56Smiod
1801*cf2f2c56Smiod r_type = ELF32_R_TYPE (dst->r_info);
1802*cf2f2c56Smiod switch (r_type)
1803*cf2f2c56Smiod {
1804*cf2f2c56Smiod case R_FRV_32:
1805*cf2f2c56Smiod cache_ptr->howto = &elf32_frv_rel_32_howto;
1806*cf2f2c56Smiod break;
1807*cf2f2c56Smiod
1808*cf2f2c56Smiod case R_FRV_FUNCDESC:
1809*cf2f2c56Smiod cache_ptr->howto = &elf32_frv_rel_funcdesc_howto;
1810*cf2f2c56Smiod break;
1811*cf2f2c56Smiod
1812*cf2f2c56Smiod case R_FRV_FUNCDESC_VALUE:
1813*cf2f2c56Smiod cache_ptr->howto = &elf32_frv_rel_funcdesc_value_howto;
1814*cf2f2c56Smiod break;
1815*cf2f2c56Smiod
1816*cf2f2c56Smiod default:
1817*cf2f2c56Smiod cache_ptr->howto = NULL;
1818*cf2f2c56Smiod break;
1819*cf2f2c56Smiod }
1820*cf2f2c56Smiod }
1821d2201f2fSdrahn
1822d2201f2fSdrahn /* Perform a single relocation. By default we use the standard BFD
1823d2201f2fSdrahn routines, but a few relocs, we have to do them ourselves. */
1824d2201f2fSdrahn
1825d2201f2fSdrahn static bfd_reloc_status_type
frv_final_link_relocate(howto,input_bfd,input_section,contents,rel,relocation)1826d2201f2fSdrahn frv_final_link_relocate (howto, input_bfd, input_section, contents, rel,
1827d2201f2fSdrahn relocation)
1828d2201f2fSdrahn reloc_howto_type *howto;
1829d2201f2fSdrahn bfd *input_bfd;
1830d2201f2fSdrahn asection *input_section;
1831d2201f2fSdrahn bfd_byte *contents;
1832d2201f2fSdrahn Elf_Internal_Rela *rel;
1833d2201f2fSdrahn bfd_vma relocation;
1834d2201f2fSdrahn {
1835d2201f2fSdrahn return _bfd_final_link_relocate (howto, input_bfd, input_section,
1836d2201f2fSdrahn contents, rel->r_offset, relocation,
1837d2201f2fSdrahn rel->r_addend);
1838d2201f2fSdrahn }
1839d2201f2fSdrahn
1840d2201f2fSdrahn
1841d2201f2fSdrahn /* Relocate an FRV ELF section.
1842d2201f2fSdrahn
1843d2201f2fSdrahn The RELOCATE_SECTION function is called by the new ELF backend linker
1844d2201f2fSdrahn to handle the relocations for a section.
1845d2201f2fSdrahn
1846d2201f2fSdrahn The relocs are always passed as Rela structures; if the section
1847d2201f2fSdrahn actually uses Rel structures, the r_addend field will always be
1848d2201f2fSdrahn zero.
1849d2201f2fSdrahn
1850d2201f2fSdrahn This function is responsible for adjusting the section contents as
1851*cf2f2c56Smiod necessary, and (if using Rela relocs and generating a relocatable
1852d2201f2fSdrahn output file) adjusting the reloc addend as necessary.
1853d2201f2fSdrahn
1854d2201f2fSdrahn This function does not have to worry about setting the reloc
1855d2201f2fSdrahn address or the reloc symbol index.
1856d2201f2fSdrahn
1857d2201f2fSdrahn LOCAL_SYMS is a pointer to the swapped in local symbols.
1858d2201f2fSdrahn
1859d2201f2fSdrahn LOCAL_SECTIONS is an array giving the section in the input file
1860d2201f2fSdrahn corresponding to the st_shndx field of each local symbol.
1861d2201f2fSdrahn
1862d2201f2fSdrahn The global hash table entry for the global symbols can be found
1863d2201f2fSdrahn via elf_sym_hashes (input_bfd).
1864d2201f2fSdrahn
1865*cf2f2c56Smiod When generating relocatable output, this function must handle
1866d2201f2fSdrahn STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1867d2201f2fSdrahn going to be the section symbol corresponding to the output
1868d2201f2fSdrahn section, which means that the addend must be adjusted
1869d2201f2fSdrahn accordingly. */
1870d2201f2fSdrahn
1871d2201f2fSdrahn static bfd_boolean
elf32_frv_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,local_syms,local_sections)1872d2201f2fSdrahn elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
1873d2201f2fSdrahn contents, relocs, local_syms, local_sections)
1874d2201f2fSdrahn bfd *output_bfd ATTRIBUTE_UNUSED;
1875d2201f2fSdrahn struct bfd_link_info *info;
1876d2201f2fSdrahn bfd *input_bfd;
1877d2201f2fSdrahn asection *input_section;
1878d2201f2fSdrahn bfd_byte *contents;
1879d2201f2fSdrahn Elf_Internal_Rela *relocs;
1880d2201f2fSdrahn Elf_Internal_Sym *local_syms;
1881d2201f2fSdrahn asection **local_sections;
1882d2201f2fSdrahn {
1883d2201f2fSdrahn Elf_Internal_Shdr *symtab_hdr;
1884d2201f2fSdrahn struct elf_link_hash_entry **sym_hashes;
1885d2201f2fSdrahn Elf_Internal_Rela *rel;
1886d2201f2fSdrahn Elf_Internal_Rela *relend;
1887*cf2f2c56Smiod unsigned isec_segment, got_segment, plt_segment, gprel_segment,
1888*cf2f2c56Smiod check_segment[2];
1889*cf2f2c56Smiod int silence_segment_error = !(info->shared || info->pie);
1890d2201f2fSdrahn
1891*cf2f2c56Smiod if (info->relocatable)
1892d2201f2fSdrahn return TRUE;
1893d2201f2fSdrahn
1894d2201f2fSdrahn symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1895d2201f2fSdrahn sym_hashes = elf_sym_hashes (input_bfd);
1896d2201f2fSdrahn relend = relocs + input_section->reloc_count;
1897d2201f2fSdrahn
1898*cf2f2c56Smiod isec_segment = _frvfdpic_osec_to_segment (output_bfd,
1899*cf2f2c56Smiod input_section->output_section);
1900*cf2f2c56Smiod if (IS_FDPIC (output_bfd) && frvfdpic_got_section (info))
1901*cf2f2c56Smiod got_segment = _frvfdpic_osec_to_segment (output_bfd,
1902*cf2f2c56Smiod frvfdpic_got_section (info)
1903*cf2f2c56Smiod ->output_section);
1904*cf2f2c56Smiod else
1905*cf2f2c56Smiod got_segment = -1;
1906*cf2f2c56Smiod if (IS_FDPIC (output_bfd) && frvfdpic_gotfixup_section (info))
1907*cf2f2c56Smiod gprel_segment = _frvfdpic_osec_to_segment (output_bfd,
1908*cf2f2c56Smiod frvfdpic_gotfixup_section (info)
1909*cf2f2c56Smiod ->output_section);
1910*cf2f2c56Smiod else
1911*cf2f2c56Smiod gprel_segment = -1;
1912*cf2f2c56Smiod if (IS_FDPIC (output_bfd) && elf_hash_table (info)->dynamic_sections_created)
1913*cf2f2c56Smiod plt_segment = _frvfdpic_osec_to_segment (output_bfd,
1914*cf2f2c56Smiod frvfdpic_plt_section (info)
1915*cf2f2c56Smiod ->output_section);
1916*cf2f2c56Smiod else
1917*cf2f2c56Smiod plt_segment = -1;
1918*cf2f2c56Smiod
1919d2201f2fSdrahn for (rel = relocs; rel < relend; rel ++)
1920d2201f2fSdrahn {
1921d2201f2fSdrahn reloc_howto_type *howto;
1922d2201f2fSdrahn unsigned long r_symndx;
1923d2201f2fSdrahn Elf_Internal_Sym *sym;
1924d2201f2fSdrahn asection *sec;
1925d2201f2fSdrahn struct elf_link_hash_entry *h;
1926d2201f2fSdrahn bfd_vma relocation;
1927d2201f2fSdrahn bfd_reloc_status_type r;
1928d2201f2fSdrahn const char * name = NULL;
1929d2201f2fSdrahn int r_type;
1930*cf2f2c56Smiod asection *osec;
1931*cf2f2c56Smiod struct frvfdpic_relocs_info *picrel;
1932*cf2f2c56Smiod bfd_vma orig_addend = rel->r_addend;
1933d2201f2fSdrahn
1934d2201f2fSdrahn r_type = ELF32_R_TYPE (rel->r_info);
1935d2201f2fSdrahn
1936d2201f2fSdrahn if ( r_type == R_FRV_GNU_VTINHERIT
1937d2201f2fSdrahn || r_type == R_FRV_GNU_VTENTRY)
1938d2201f2fSdrahn continue;
1939d2201f2fSdrahn
1940d2201f2fSdrahn /* This is a final link. */
1941d2201f2fSdrahn r_symndx = ELF32_R_SYM (rel->r_info);
1942d2201f2fSdrahn howto = elf32_frv_howto_table + ELF32_R_TYPE (rel->r_info);
1943d2201f2fSdrahn h = NULL;
1944d2201f2fSdrahn sym = NULL;
1945d2201f2fSdrahn sec = NULL;
1946d2201f2fSdrahn
1947d2201f2fSdrahn if (r_symndx < symtab_hdr->sh_info)
1948d2201f2fSdrahn {
1949d2201f2fSdrahn sym = local_syms + r_symndx;
1950*cf2f2c56Smiod osec = sec = local_sections [r_symndx];
1951*cf2f2c56Smiod relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1952d2201f2fSdrahn
1953d2201f2fSdrahn name = bfd_elf_string_from_elf_section
1954d2201f2fSdrahn (input_bfd, symtab_hdr->sh_link, sym->st_name);
1955d2201f2fSdrahn name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1956d2201f2fSdrahn }
1957d2201f2fSdrahn else
1958d2201f2fSdrahn {
1959d2201f2fSdrahn h = sym_hashes [r_symndx - symtab_hdr->sh_info];
1960d2201f2fSdrahn
1961d2201f2fSdrahn while (h->root.type == bfd_link_hash_indirect
1962d2201f2fSdrahn || h->root.type == bfd_link_hash_warning)
1963d2201f2fSdrahn h = (struct elf_link_hash_entry *) h->root.u.i.link;
1964d2201f2fSdrahn
1965d2201f2fSdrahn name = h->root.root.string;
1966d2201f2fSdrahn
1967*cf2f2c56Smiod if ((h->root.type == bfd_link_hash_defined
1968*cf2f2c56Smiod || h->root.type == bfd_link_hash_defweak)
1969*cf2f2c56Smiod && ! FRVFDPIC_SYM_LOCAL (info, h))
1970*cf2f2c56Smiod {
1971*cf2f2c56Smiod sec = NULL;
1972*cf2f2c56Smiod relocation = 0;
1973*cf2f2c56Smiod }
1974*cf2f2c56Smiod else
1975d2201f2fSdrahn if (h->root.type == bfd_link_hash_defined
1976d2201f2fSdrahn || h->root.type == bfd_link_hash_defweak)
1977d2201f2fSdrahn {
1978d2201f2fSdrahn sec = h->root.u.def.section;
1979d2201f2fSdrahn relocation = (h->root.u.def.value
1980d2201f2fSdrahn + sec->output_section->vma
1981d2201f2fSdrahn + sec->output_offset);
1982d2201f2fSdrahn }
1983d2201f2fSdrahn else if (h->root.type == bfd_link_hash_undefweak)
1984d2201f2fSdrahn {
1985d2201f2fSdrahn relocation = 0;
1986d2201f2fSdrahn }
1987*cf2f2c56Smiod else if (info->unresolved_syms_in_objects == RM_IGNORE
1988*cf2f2c56Smiod && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
1989*cf2f2c56Smiod relocation = 0;
1990d2201f2fSdrahn else
1991d2201f2fSdrahn {
1992d2201f2fSdrahn if (! ((*info->callbacks->undefined_symbol)
1993d2201f2fSdrahn (info, h->root.root.string, input_bfd,
1994*cf2f2c56Smiod input_section, rel->r_offset,
1995*cf2f2c56Smiod (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
1996*cf2f2c56Smiod || ELF_ST_VISIBILITY (h->other)))))
1997d2201f2fSdrahn return FALSE;
1998d2201f2fSdrahn relocation = 0;
1999d2201f2fSdrahn }
2000*cf2f2c56Smiod osec = sec;
2001*cf2f2c56Smiod }
2002*cf2f2c56Smiod
2003*cf2f2c56Smiod switch (r_type)
2004*cf2f2c56Smiod {
2005*cf2f2c56Smiod case R_FRV_LABEL24:
2006*cf2f2c56Smiod case R_FRV_32:
2007*cf2f2c56Smiod if (! IS_FDPIC (output_bfd))
2008*cf2f2c56Smiod goto non_fdpic;
2009*cf2f2c56Smiod
2010*cf2f2c56Smiod case R_FRV_GOT12:
2011*cf2f2c56Smiod case R_FRV_GOTHI:
2012*cf2f2c56Smiod case R_FRV_GOTLO:
2013*cf2f2c56Smiod case R_FRV_FUNCDESC_GOT12:
2014*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTHI:
2015*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTLO:
2016*cf2f2c56Smiod case R_FRV_GOTOFF12:
2017*cf2f2c56Smiod case R_FRV_GOTOFFHI:
2018*cf2f2c56Smiod case R_FRV_GOTOFFLO:
2019*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFF12:
2020*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFHI:
2021*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFLO:
2022*cf2f2c56Smiod case R_FRV_FUNCDESC:
2023*cf2f2c56Smiod case R_FRV_FUNCDESC_VALUE:
2024*cf2f2c56Smiod if (h != NULL)
2025*cf2f2c56Smiod picrel = frvfdpic_relocs_info_for_global (frvfdpic_relocs_info
2026*cf2f2c56Smiod (info), input_bfd, h,
2027*cf2f2c56Smiod orig_addend, INSERT);
2028*cf2f2c56Smiod else
2029*cf2f2c56Smiod /* In order to find the entry we created before, we must
2030*cf2f2c56Smiod use the original addend, not the one that may have been
2031*cf2f2c56Smiod modified by _bfd_elf_rela_local_sym(). */
2032*cf2f2c56Smiod picrel = frvfdpic_relocs_info_for_local (frvfdpic_relocs_info
2033*cf2f2c56Smiod (info), input_bfd, r_symndx,
2034*cf2f2c56Smiod orig_addend, INSERT);
2035*cf2f2c56Smiod if (! picrel)
2036*cf2f2c56Smiod return FALSE;
2037*cf2f2c56Smiod
2038*cf2f2c56Smiod if (!_frvfdpic_emit_got_relocs_plt_entries (picrel, output_bfd, info,
2039*cf2f2c56Smiod osec, sym,
2040*cf2f2c56Smiod rel->r_addend))
2041*cf2f2c56Smiod {
2042*cf2f2c56Smiod (*_bfd_error_handler)
2043*cf2f2c56Smiod (_("%s: relocation at `%s+0x%x' references symbol `%s' with nonzero addend"),
2044*cf2f2c56Smiod bfd_archive_filename (input_bfd), input_section->name,
2045*cf2f2c56Smiod rel->r_offset, name);
2046*cf2f2c56Smiod return FALSE;
2047*cf2f2c56Smiod
2048*cf2f2c56Smiod }
2049*cf2f2c56Smiod
2050*cf2f2c56Smiod break;
2051*cf2f2c56Smiod
2052*cf2f2c56Smiod default:
2053*cf2f2c56Smiod non_fdpic:
2054*cf2f2c56Smiod picrel = NULL;
2055*cf2f2c56Smiod if (h && ! FRVFDPIC_SYM_LOCAL (info, h))
2056*cf2f2c56Smiod {
2057*cf2f2c56Smiod info->callbacks->warning
2058*cf2f2c56Smiod (info, _("relocation references symbol not defined in the module"),
2059*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2060*cf2f2c56Smiod return FALSE;
2061*cf2f2c56Smiod }
2062*cf2f2c56Smiod break;
2063*cf2f2c56Smiod }
2064*cf2f2c56Smiod
2065*cf2f2c56Smiod switch (r_type)
2066*cf2f2c56Smiod {
2067*cf2f2c56Smiod case R_FRV_LABEL24:
2068*cf2f2c56Smiod check_segment[0] = isec_segment;
2069*cf2f2c56Smiod if (! IS_FDPIC (output_bfd))
2070*cf2f2c56Smiod check_segment[1] = isec_segment;
2071*cf2f2c56Smiod else if (picrel->plt)
2072*cf2f2c56Smiod {
2073*cf2f2c56Smiod relocation = frvfdpic_plt_section (info)->output_section->vma
2074*cf2f2c56Smiod + frvfdpic_plt_section (info)->output_offset
2075*cf2f2c56Smiod + picrel->plt_entry;
2076*cf2f2c56Smiod check_segment[1] = plt_segment;
2077*cf2f2c56Smiod }
2078*cf2f2c56Smiod /* We don't want to warn on calls to undefined weak symbols,
2079*cf2f2c56Smiod as calls to them must be protected by non-NULL tests
2080*cf2f2c56Smiod anyway, and unprotected calls would invoke undefined
2081*cf2f2c56Smiod behavior. */
2082*cf2f2c56Smiod else if (picrel->symndx == -1
2083*cf2f2c56Smiod && picrel->d.h->root.type == bfd_link_hash_undefweak)
2084*cf2f2c56Smiod check_segment[1] = check_segment[0];
2085*cf2f2c56Smiod else
2086*cf2f2c56Smiod check_segment[1] = sec
2087*cf2f2c56Smiod ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
2088*cf2f2c56Smiod : (unsigned)-1;
2089*cf2f2c56Smiod break;
2090*cf2f2c56Smiod
2091*cf2f2c56Smiod case R_FRV_GOT12:
2092*cf2f2c56Smiod case R_FRV_GOTHI:
2093*cf2f2c56Smiod case R_FRV_GOTLO:
2094*cf2f2c56Smiod relocation = picrel->got_entry;
2095*cf2f2c56Smiod check_segment[0] = check_segment[1] = got_segment;
2096*cf2f2c56Smiod break;
2097*cf2f2c56Smiod
2098*cf2f2c56Smiod case R_FRV_FUNCDESC_GOT12:
2099*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTHI:
2100*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTLO:
2101*cf2f2c56Smiod relocation = picrel->fdgot_entry;
2102*cf2f2c56Smiod check_segment[0] = check_segment[1] = got_segment;
2103*cf2f2c56Smiod break;
2104*cf2f2c56Smiod
2105*cf2f2c56Smiod case R_FRV_GOTOFFHI:
2106*cf2f2c56Smiod case R_FRV_GOTOFF12:
2107*cf2f2c56Smiod case R_FRV_GOTOFFLO:
2108*cf2f2c56Smiod relocation -= frvfdpic_got_section (info)->output_section->vma
2109*cf2f2c56Smiod + frvfdpic_got_section (info)->output_offset
2110*cf2f2c56Smiod + frvfdpic_got_initial_offset (info);
2111*cf2f2c56Smiod check_segment[0] = got_segment;
2112*cf2f2c56Smiod check_segment[1] = sec
2113*cf2f2c56Smiod ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
2114*cf2f2c56Smiod : (unsigned)-1;
2115*cf2f2c56Smiod break;
2116*cf2f2c56Smiod
2117*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFF12:
2118*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFHI:
2119*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFLO:
2120*cf2f2c56Smiod relocation = picrel->fd_entry;
2121*cf2f2c56Smiod check_segment[0] = check_segment[1] = got_segment;
2122*cf2f2c56Smiod break;
2123*cf2f2c56Smiod
2124*cf2f2c56Smiod case R_FRV_FUNCDESC:
2125*cf2f2c56Smiod {
2126*cf2f2c56Smiod int dynindx;
2127*cf2f2c56Smiod bfd_vma addend = rel->r_addend;
2128*cf2f2c56Smiod
2129*cf2f2c56Smiod if (! (h && h->root.type == bfd_link_hash_undefweak
2130*cf2f2c56Smiod && FRVFDPIC_SYM_LOCAL (info, h)))
2131*cf2f2c56Smiod {
2132*cf2f2c56Smiod /* If the symbol is dynamic and there may be dynamic
2133*cf2f2c56Smiod symbol resolution because we are or are linked with a
2134*cf2f2c56Smiod shared library, emit a FUNCDESC relocation such that
2135*cf2f2c56Smiod the dynamic linker will allocate the function
2136*cf2f2c56Smiod descriptor. If the symbol needs a non-local function
2137*cf2f2c56Smiod descriptor but binds locally (e.g., its visibility is
2138*cf2f2c56Smiod protected, emit a dynamic relocation decayed to
2139*cf2f2c56Smiod section+offset. */
2140*cf2f2c56Smiod if (h && ! FRVFDPIC_FUNCDESC_LOCAL (info, h)
2141*cf2f2c56Smiod && FRVFDPIC_SYM_LOCAL (info, h)
2142*cf2f2c56Smiod && !(info->executable && !info->pie))
2143*cf2f2c56Smiod {
2144*cf2f2c56Smiod dynindx = elf_section_data (h->root.u.def.section
2145*cf2f2c56Smiod ->output_section)->dynindx;
2146*cf2f2c56Smiod addend += h->root.u.def.section->output_offset
2147*cf2f2c56Smiod + h->root.u.def.value;
2148*cf2f2c56Smiod }
2149*cf2f2c56Smiod else if (h && ! FRVFDPIC_FUNCDESC_LOCAL (info, h))
2150*cf2f2c56Smiod {
2151*cf2f2c56Smiod if (addend)
2152*cf2f2c56Smiod {
2153*cf2f2c56Smiod info->callbacks->warning
2154*cf2f2c56Smiod (info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"),
2155*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2156*cf2f2c56Smiod return FALSE;
2157*cf2f2c56Smiod }
2158*cf2f2c56Smiod dynindx = h->dynindx;
2159*cf2f2c56Smiod }
2160*cf2f2c56Smiod else
2161*cf2f2c56Smiod {
2162*cf2f2c56Smiod /* Otherwise, we know we have a private function
2163*cf2f2c56Smiod descriptor, so reference it directly. */
2164*cf2f2c56Smiod BFD_ASSERT (picrel->privfd);
2165*cf2f2c56Smiod r_type = R_FRV_32;
2166*cf2f2c56Smiod dynindx = elf_section_data (frvfdpic_got_section (info)
2167*cf2f2c56Smiod ->output_section)->dynindx;
2168*cf2f2c56Smiod addend = frvfdpic_got_section (info)->output_offset
2169*cf2f2c56Smiod + frvfdpic_got_initial_offset (info)
2170*cf2f2c56Smiod + picrel->fd_entry;
2171*cf2f2c56Smiod }
2172*cf2f2c56Smiod
2173*cf2f2c56Smiod /* If there is room for dynamic symbol resolution, emit
2174*cf2f2c56Smiod the dynamic relocation. However, if we're linking an
2175*cf2f2c56Smiod executable at a fixed location, we won't have emitted a
2176*cf2f2c56Smiod dynamic symbol entry for the got section, so idx will
2177*cf2f2c56Smiod be zero, which means we can and should compute the
2178*cf2f2c56Smiod address of the private descriptor ourselves. */
2179*cf2f2c56Smiod if (info->executable && !info->pie
2180*cf2f2c56Smiod && (!h || FRVFDPIC_FUNCDESC_LOCAL (info, h)))
2181*cf2f2c56Smiod {
2182*cf2f2c56Smiod addend += frvfdpic_got_section (info)->output_section->vma;
2183*cf2f2c56Smiod if ((bfd_get_section_flags (output_bfd,
2184*cf2f2c56Smiod input_section->output_section)
2185*cf2f2c56Smiod & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
2186*cf2f2c56Smiod {
2187*cf2f2c56Smiod if (_frvfdpic_osec_readonly_p (output_bfd,
2188*cf2f2c56Smiod input_section
2189*cf2f2c56Smiod ->output_section))
2190*cf2f2c56Smiod {
2191*cf2f2c56Smiod info->callbacks->warning
2192*cf2f2c56Smiod (info,
2193*cf2f2c56Smiod _("cannot emit fixups in read-only section"),
2194*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2195*cf2f2c56Smiod return FALSE;
2196*cf2f2c56Smiod }
2197*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd,
2198*cf2f2c56Smiod frvfdpic_gotfixup_section
2199*cf2f2c56Smiod (info),
2200*cf2f2c56Smiod _bfd_elf_section_offset
2201*cf2f2c56Smiod (output_bfd, info,
2202*cf2f2c56Smiod input_section, rel->r_offset)
2203*cf2f2c56Smiod + input_section
2204*cf2f2c56Smiod ->output_section->vma
2205*cf2f2c56Smiod + input_section->output_offset,
2206*cf2f2c56Smiod picrel);
2207*cf2f2c56Smiod }
2208*cf2f2c56Smiod }
2209*cf2f2c56Smiod else if ((bfd_get_section_flags (output_bfd,
2210*cf2f2c56Smiod input_section->output_section)
2211*cf2f2c56Smiod & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
2212*cf2f2c56Smiod {
2213*cf2f2c56Smiod if (_frvfdpic_osec_readonly_p (output_bfd,
2214*cf2f2c56Smiod input_section
2215*cf2f2c56Smiod ->output_section))
2216*cf2f2c56Smiod {
2217*cf2f2c56Smiod info->callbacks->warning
2218*cf2f2c56Smiod (info,
2219*cf2f2c56Smiod _("cannot emit dynamic relocations in read-only section"),
2220*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2221*cf2f2c56Smiod return FALSE;
2222*cf2f2c56Smiod }
2223*cf2f2c56Smiod _frvfdpic_add_dyn_reloc (output_bfd,
2224*cf2f2c56Smiod frvfdpic_gotrel_section (info),
2225*cf2f2c56Smiod _bfd_elf_section_offset
2226*cf2f2c56Smiod (output_bfd, info,
2227*cf2f2c56Smiod input_section, rel->r_offset)
2228*cf2f2c56Smiod + input_section
2229*cf2f2c56Smiod ->output_section->vma
2230*cf2f2c56Smiod + input_section->output_offset,
2231*cf2f2c56Smiod r_type, dynindx, addend, picrel);
2232*cf2f2c56Smiod }
2233*cf2f2c56Smiod else
2234*cf2f2c56Smiod addend += frvfdpic_got_section (info)->output_section->vma;
2235*cf2f2c56Smiod }
2236*cf2f2c56Smiod
2237*cf2f2c56Smiod /* We want the addend in-place because dynamic
2238*cf2f2c56Smiod relocations are REL. Setting relocation to it should
2239*cf2f2c56Smiod arrange for it to be installed. */
2240*cf2f2c56Smiod relocation = addend - rel->r_addend;
2241*cf2f2c56Smiod }
2242*cf2f2c56Smiod check_segment[0] = check_segment[1] = got_segment;
2243*cf2f2c56Smiod break;
2244*cf2f2c56Smiod
2245*cf2f2c56Smiod case R_FRV_32:
2246*cf2f2c56Smiod if (! IS_FDPIC (output_bfd))
2247*cf2f2c56Smiod {
2248*cf2f2c56Smiod check_segment[0] = check_segment[1] = -1;
2249*cf2f2c56Smiod break;
2250*cf2f2c56Smiod }
2251*cf2f2c56Smiod /* Fall through. */
2252*cf2f2c56Smiod case R_FRV_FUNCDESC_VALUE:
2253*cf2f2c56Smiod {
2254*cf2f2c56Smiod int dynindx;
2255*cf2f2c56Smiod bfd_vma addend = rel->r_addend;
2256*cf2f2c56Smiod
2257*cf2f2c56Smiod /* If the symbol is dynamic but binds locally, use
2258*cf2f2c56Smiod section+offset. */
2259*cf2f2c56Smiod if (h && ! FRVFDPIC_SYM_LOCAL (info, h))
2260*cf2f2c56Smiod {
2261*cf2f2c56Smiod if (addend && r_type == R_FRV_FUNCDESC_VALUE)
2262*cf2f2c56Smiod {
2263*cf2f2c56Smiod info->callbacks->warning
2264*cf2f2c56Smiod (info, _("R_FRV_FUNCDESC_VALUE references dynamic symbol with nonzero addend"),
2265*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2266*cf2f2c56Smiod return FALSE;
2267*cf2f2c56Smiod }
2268*cf2f2c56Smiod dynindx = h->dynindx;
2269*cf2f2c56Smiod }
2270*cf2f2c56Smiod else
2271*cf2f2c56Smiod {
2272*cf2f2c56Smiod if (h)
2273*cf2f2c56Smiod addend += h->root.u.def.value;
2274*cf2f2c56Smiod else
2275*cf2f2c56Smiod addend += sym->st_value;
2276*cf2f2c56Smiod if (osec)
2277*cf2f2c56Smiod addend += osec->output_offset;
2278*cf2f2c56Smiod if (osec && osec->output_section
2279*cf2f2c56Smiod && ! bfd_is_abs_section (osec->output_section)
2280*cf2f2c56Smiod && ! bfd_is_und_section (osec->output_section))
2281*cf2f2c56Smiod dynindx = elf_section_data (osec->output_section)->dynindx;
2282*cf2f2c56Smiod else
2283*cf2f2c56Smiod dynindx = 0;
2284*cf2f2c56Smiod }
2285*cf2f2c56Smiod
2286*cf2f2c56Smiod /* If we're linking an executable at a fixed address, we
2287*cf2f2c56Smiod can omit the dynamic relocation as long as the symbol
2288*cf2f2c56Smiod is defined in the current link unit (which is implied
2289*cf2f2c56Smiod by its output section not being NULL). */
2290*cf2f2c56Smiod if (info->executable && !info->pie
2291*cf2f2c56Smiod && (!h || FRVFDPIC_SYM_LOCAL (info, h)))
2292*cf2f2c56Smiod {
2293*cf2f2c56Smiod if (osec)
2294*cf2f2c56Smiod addend += osec->output_section->vma;
2295*cf2f2c56Smiod if (IS_FDPIC (input_bfd)
2296*cf2f2c56Smiod && (bfd_get_section_flags (output_bfd,
2297*cf2f2c56Smiod input_section->output_section)
2298*cf2f2c56Smiod & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
2299*cf2f2c56Smiod {
2300*cf2f2c56Smiod if (_frvfdpic_osec_readonly_p (output_bfd,
2301*cf2f2c56Smiod input_section
2302*cf2f2c56Smiod ->output_section))
2303*cf2f2c56Smiod {
2304*cf2f2c56Smiod info->callbacks->warning
2305*cf2f2c56Smiod (info,
2306*cf2f2c56Smiod _("cannot emit fixups in read-only section"),
2307*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2308*cf2f2c56Smiod return FALSE;
2309*cf2f2c56Smiod }
2310*cf2f2c56Smiod if (!h || h->root.type != bfd_link_hash_undefweak)
2311*cf2f2c56Smiod {
2312*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd,
2313*cf2f2c56Smiod frvfdpic_gotfixup_section
2314*cf2f2c56Smiod (info),
2315*cf2f2c56Smiod _bfd_elf_section_offset
2316*cf2f2c56Smiod (output_bfd, info,
2317*cf2f2c56Smiod input_section, rel->r_offset)
2318*cf2f2c56Smiod + input_section
2319*cf2f2c56Smiod ->output_section->vma
2320*cf2f2c56Smiod + input_section->output_offset,
2321*cf2f2c56Smiod picrel);
2322*cf2f2c56Smiod if (r_type == R_FRV_FUNCDESC_VALUE)
2323*cf2f2c56Smiod _frvfdpic_add_rofixup
2324*cf2f2c56Smiod (output_bfd,
2325*cf2f2c56Smiod frvfdpic_gotfixup_section (info),
2326*cf2f2c56Smiod _bfd_elf_section_offset
2327*cf2f2c56Smiod (output_bfd, info,
2328*cf2f2c56Smiod input_section, rel->r_offset)
2329*cf2f2c56Smiod + input_section->output_section->vma
2330*cf2f2c56Smiod + input_section->output_offset + 4, picrel);
2331*cf2f2c56Smiod }
2332*cf2f2c56Smiod }
2333*cf2f2c56Smiod }
2334*cf2f2c56Smiod else
2335*cf2f2c56Smiod {
2336*cf2f2c56Smiod if ((bfd_get_section_flags (output_bfd,
2337*cf2f2c56Smiod input_section->output_section)
2338*cf2f2c56Smiod & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
2339*cf2f2c56Smiod {
2340*cf2f2c56Smiod if (_frvfdpic_osec_readonly_p (output_bfd,
2341*cf2f2c56Smiod input_section
2342*cf2f2c56Smiod ->output_section))
2343*cf2f2c56Smiod {
2344*cf2f2c56Smiod info->callbacks->warning
2345*cf2f2c56Smiod (info,
2346*cf2f2c56Smiod _("cannot emit dynamic relocations in read-only section"),
2347*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2348*cf2f2c56Smiod return FALSE;
2349*cf2f2c56Smiod }
2350*cf2f2c56Smiod _frvfdpic_add_dyn_reloc (output_bfd,
2351*cf2f2c56Smiod frvfdpic_gotrel_section (info),
2352*cf2f2c56Smiod _bfd_elf_section_offset
2353*cf2f2c56Smiod (output_bfd, info,
2354*cf2f2c56Smiod input_section, rel->r_offset)
2355*cf2f2c56Smiod + input_section
2356*cf2f2c56Smiod ->output_section->vma
2357*cf2f2c56Smiod + input_section->output_offset,
2358*cf2f2c56Smiod r_type, dynindx, addend, picrel);
2359*cf2f2c56Smiod }
2360*cf2f2c56Smiod else if (osec)
2361*cf2f2c56Smiod addend += osec->output_section->vma;
2362*cf2f2c56Smiod /* We want the addend in-place because dynamic
2363*cf2f2c56Smiod relocations are REL. Setting relocation to it
2364*cf2f2c56Smiod should arrange for it to be installed. */
2365*cf2f2c56Smiod relocation = addend - rel->r_addend;
2366*cf2f2c56Smiod }
2367*cf2f2c56Smiod
2368*cf2f2c56Smiod if (r_type == R_FRV_FUNCDESC_VALUE)
2369*cf2f2c56Smiod {
2370*cf2f2c56Smiod /* If we've omitted the dynamic relocation, just emit
2371*cf2f2c56Smiod the fixed addresses of the symbol and of the local
2372*cf2f2c56Smiod GOT base offset. */
2373*cf2f2c56Smiod if (info->executable && !info->pie
2374*cf2f2c56Smiod && (!h || FRVFDPIC_SYM_LOCAL (info, h)))
2375*cf2f2c56Smiod bfd_put_32 (output_bfd,
2376*cf2f2c56Smiod frvfdpic_got_section (info)->output_section->vma
2377*cf2f2c56Smiod + frvfdpic_got_section (info)->output_offset
2378*cf2f2c56Smiod + frvfdpic_got_initial_offset (info),
2379*cf2f2c56Smiod contents + rel->r_offset + 4);
2380*cf2f2c56Smiod else
2381*cf2f2c56Smiod /* A function descriptor used for lazy or local
2382*cf2f2c56Smiod resolving is initialized such that its high word
2383*cf2f2c56Smiod contains the output section index in which the
2384*cf2f2c56Smiod PLT entries are located, and the low word
2385*cf2f2c56Smiod contains the offset of the lazy PLT entry entry
2386*cf2f2c56Smiod point into that section. */
2387*cf2f2c56Smiod bfd_put_32 (output_bfd,
2388*cf2f2c56Smiod h && ! FRVFDPIC_SYM_LOCAL (info, h)
2389*cf2f2c56Smiod ? 0
2390*cf2f2c56Smiod : _frvfdpic_osec_to_segment (output_bfd,
2391*cf2f2c56Smiod sec
2392*cf2f2c56Smiod ->output_section),
2393*cf2f2c56Smiod contents + rel->r_offset + 4);
2394*cf2f2c56Smiod }
2395*cf2f2c56Smiod }
2396*cf2f2c56Smiod check_segment[0] = check_segment[1] = got_segment;
2397*cf2f2c56Smiod break;
2398*cf2f2c56Smiod
2399*cf2f2c56Smiod case R_FRV_GPREL12:
2400*cf2f2c56Smiod case R_FRV_GPRELU12:
2401*cf2f2c56Smiod case R_FRV_GPREL32:
2402*cf2f2c56Smiod case R_FRV_GPRELHI:
2403*cf2f2c56Smiod case R_FRV_GPRELLO:
2404*cf2f2c56Smiod check_segment[0] = gprel_segment;
2405*cf2f2c56Smiod check_segment[1] = sec
2406*cf2f2c56Smiod ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
2407*cf2f2c56Smiod : (unsigned)-1;
2408*cf2f2c56Smiod break;
2409*cf2f2c56Smiod
2410*cf2f2c56Smiod default:
2411*cf2f2c56Smiod check_segment[0] = isec_segment;
2412*cf2f2c56Smiod check_segment[1] = sec
2413*cf2f2c56Smiod ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
2414*cf2f2c56Smiod : (unsigned)-1;
2415*cf2f2c56Smiod break;
2416*cf2f2c56Smiod }
2417*cf2f2c56Smiod
2418*cf2f2c56Smiod if (check_segment[0] != check_segment[1] && IS_FDPIC (output_bfd))
2419*cf2f2c56Smiod {
2420*cf2f2c56Smiod #if 1 /* If you take this out, remove the #error from fdpic-static-6.d
2421*cf2f2c56Smiod in the ld testsuite. */
2422*cf2f2c56Smiod /* This helps catch problems in GCC while we can't do more
2423*cf2f2c56Smiod than static linking. The idea is to test whether the
2424*cf2f2c56Smiod input file basename is crt0.o only once. */
2425*cf2f2c56Smiod if (silence_segment_error == 1)
2426*cf2f2c56Smiod silence_segment_error =
2427*cf2f2c56Smiod (strlen (input_bfd->filename) == 6
2428*cf2f2c56Smiod && strcmp (input_bfd->filename, "crt0.o") == 0)
2429*cf2f2c56Smiod || (strlen (input_bfd->filename) > 6
2430*cf2f2c56Smiod && strcmp (input_bfd->filename
2431*cf2f2c56Smiod + strlen (input_bfd->filename) - 7,
2432*cf2f2c56Smiod "/crt0.o") == 0)
2433*cf2f2c56Smiod ? -1 : 0;
2434*cf2f2c56Smiod #endif
2435*cf2f2c56Smiod if (!silence_segment_error
2436*cf2f2c56Smiod /* We don't want duplicate errors for undefined
2437*cf2f2c56Smiod symbols. */
2438*cf2f2c56Smiod && !(picrel && picrel->symndx == -1
2439*cf2f2c56Smiod && picrel->d.h->root.type == bfd_link_hash_undefined))
2440*cf2f2c56Smiod info->callbacks->warning
2441*cf2f2c56Smiod (info,
2442*cf2f2c56Smiod (info->shared || info->pie)
2443*cf2f2c56Smiod ? _("relocations between different segments are not supported")
2444*cf2f2c56Smiod : _("warning: relocation references a different segment"),
2445*cf2f2c56Smiod name, input_bfd, input_section, rel->r_offset);
2446*cf2f2c56Smiod if (!silence_segment_error && (info->shared || info->pie))
2447*cf2f2c56Smiod return FALSE;
2448*cf2f2c56Smiod elf_elfheader (output_bfd)->e_flags |= EF_FRV_PIC;
2449*cf2f2c56Smiod }
2450*cf2f2c56Smiod
2451*cf2f2c56Smiod switch (r_type)
2452*cf2f2c56Smiod {
2453*cf2f2c56Smiod case R_FRV_GOTOFFHI:
2454*cf2f2c56Smiod /* We need the addend to be applied before we shift the
2455*cf2f2c56Smiod value right. */
2456*cf2f2c56Smiod relocation += rel->r_addend;
2457*cf2f2c56Smiod /* Fall through. */
2458*cf2f2c56Smiod case R_FRV_GOTHI:
2459*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTHI:
2460*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFHI:
2461*cf2f2c56Smiod relocation >>= 16;
2462*cf2f2c56Smiod /* Fall through. */
2463*cf2f2c56Smiod
2464*cf2f2c56Smiod case R_FRV_GOTLO:
2465*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTLO:
2466*cf2f2c56Smiod case R_FRV_GOTOFFLO:
2467*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFLO:
2468*cf2f2c56Smiod relocation &= 0xffff;
2469*cf2f2c56Smiod break;
2470*cf2f2c56Smiod
2471*cf2f2c56Smiod default:
2472*cf2f2c56Smiod break;
2473*cf2f2c56Smiod }
2474*cf2f2c56Smiod
2475*cf2f2c56Smiod switch (r_type)
2476*cf2f2c56Smiod {
2477*cf2f2c56Smiod case R_FRV_LABEL24:
2478*cf2f2c56Smiod if (! IS_FDPIC (output_bfd) || ! picrel->plt)
2479*cf2f2c56Smiod break;
2480*cf2f2c56Smiod /* Fall through. */
2481*cf2f2c56Smiod
2482*cf2f2c56Smiod /* When referencing a GOT entry, a function descriptor or a
2483*cf2f2c56Smiod PLT, we don't want the addend to apply to the reference,
2484*cf2f2c56Smiod but rather to the referenced symbol. The actual entry
2485*cf2f2c56Smiod will have already been created taking the addend into
2486*cf2f2c56Smiod account, so cancel it out here. */
2487*cf2f2c56Smiod case R_FRV_GOT12:
2488*cf2f2c56Smiod case R_FRV_GOTHI:
2489*cf2f2c56Smiod case R_FRV_GOTLO:
2490*cf2f2c56Smiod case R_FRV_FUNCDESC_GOT12:
2491*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTHI:
2492*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTLO:
2493*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFF12:
2494*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFHI:
2495*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFLO:
2496*cf2f2c56Smiod /* Note that we only want GOTOFFHI, not GOTOFFLO or GOTOFF12
2497*cf2f2c56Smiod here, since we do want to apply the addend to the others.
2498*cf2f2c56Smiod Note that we've applied the addend to GOTOFFHI before we
2499*cf2f2c56Smiod shifted it right. */
2500*cf2f2c56Smiod case R_FRV_GOTOFFHI:
2501*cf2f2c56Smiod relocation -= rel->r_addend;
2502*cf2f2c56Smiod break;
2503*cf2f2c56Smiod
2504*cf2f2c56Smiod default:
2505*cf2f2c56Smiod break;
2506d2201f2fSdrahn }
2507d2201f2fSdrahn
2508d2201f2fSdrahn if (r_type == R_FRV_HI16)
2509d2201f2fSdrahn r = elf32_frv_relocate_hi16 (input_bfd, rel, contents, relocation);
2510d2201f2fSdrahn
2511d2201f2fSdrahn else if (r_type == R_FRV_LO16)
2512d2201f2fSdrahn r = elf32_frv_relocate_lo16 (input_bfd, rel, contents, relocation);
2513d2201f2fSdrahn
2514d2201f2fSdrahn else if (r_type == R_FRV_LABEL24)
2515d2201f2fSdrahn r = elf32_frv_relocate_label24 (input_bfd, input_section, rel,
2516d2201f2fSdrahn contents, relocation);
2517d2201f2fSdrahn
2518d2201f2fSdrahn else if (r_type == R_FRV_GPREL12)
2519d2201f2fSdrahn r = elf32_frv_relocate_gprel12 (info, input_bfd, input_section, rel,
2520d2201f2fSdrahn contents, relocation);
2521d2201f2fSdrahn
2522d2201f2fSdrahn else if (r_type == R_FRV_GPRELU12)
2523d2201f2fSdrahn r = elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, rel,
2524d2201f2fSdrahn contents, relocation);
2525d2201f2fSdrahn
2526d2201f2fSdrahn else if (r_type == R_FRV_GPRELLO)
2527d2201f2fSdrahn r = elf32_frv_relocate_gprello (info, input_bfd, input_section, rel,
2528d2201f2fSdrahn contents, relocation);
2529d2201f2fSdrahn
2530d2201f2fSdrahn else if (r_type == R_FRV_GPRELHI)
2531d2201f2fSdrahn r = elf32_frv_relocate_gprelhi (info, input_bfd, input_section, rel,
2532d2201f2fSdrahn contents, relocation);
2533d2201f2fSdrahn
2534d2201f2fSdrahn else
2535d2201f2fSdrahn r = frv_final_link_relocate (howto, input_bfd, input_section, contents,
2536d2201f2fSdrahn rel, relocation);
2537d2201f2fSdrahn
2538d2201f2fSdrahn if (r != bfd_reloc_ok)
2539d2201f2fSdrahn {
2540d2201f2fSdrahn const char * msg = (const char *) NULL;
2541d2201f2fSdrahn
2542d2201f2fSdrahn switch (r)
2543d2201f2fSdrahn {
2544d2201f2fSdrahn case bfd_reloc_overflow:
2545d2201f2fSdrahn r = info->callbacks->reloc_overflow
2546d2201f2fSdrahn (info, name, howto->name, (bfd_vma) 0,
2547d2201f2fSdrahn input_bfd, input_section, rel->r_offset);
2548d2201f2fSdrahn break;
2549d2201f2fSdrahn
2550d2201f2fSdrahn case bfd_reloc_undefined:
2551d2201f2fSdrahn r = info->callbacks->undefined_symbol
2552d2201f2fSdrahn (info, name, input_bfd, input_section, rel->r_offset, TRUE);
2553d2201f2fSdrahn break;
2554d2201f2fSdrahn
2555d2201f2fSdrahn case bfd_reloc_outofrange:
2556d2201f2fSdrahn msg = _("internal error: out of range error");
2557d2201f2fSdrahn break;
2558d2201f2fSdrahn
2559d2201f2fSdrahn case bfd_reloc_notsupported:
2560d2201f2fSdrahn msg = _("internal error: unsupported relocation error");
2561d2201f2fSdrahn break;
2562d2201f2fSdrahn
2563d2201f2fSdrahn case bfd_reloc_dangerous:
2564d2201f2fSdrahn msg = _("internal error: dangerous relocation");
2565d2201f2fSdrahn break;
2566d2201f2fSdrahn
2567d2201f2fSdrahn default:
2568d2201f2fSdrahn msg = _("internal error: unknown error");
2569d2201f2fSdrahn break;
2570d2201f2fSdrahn }
2571d2201f2fSdrahn
2572d2201f2fSdrahn if (msg)
2573d2201f2fSdrahn r = info->callbacks->warning
2574d2201f2fSdrahn (info, msg, name, input_bfd, input_section, rel->r_offset);
2575d2201f2fSdrahn
2576d2201f2fSdrahn if (! r)
2577d2201f2fSdrahn return FALSE;
2578d2201f2fSdrahn }
2579d2201f2fSdrahn }
2580d2201f2fSdrahn
2581d2201f2fSdrahn return TRUE;
2582d2201f2fSdrahn }
2583d2201f2fSdrahn
2584d2201f2fSdrahn /* Return the section that should be marked against GC for a given
2585d2201f2fSdrahn relocation. */
2586d2201f2fSdrahn
2587d2201f2fSdrahn static asection *
elf32_frv_gc_mark_hook(sec,info,rel,h,sym)2588d2201f2fSdrahn elf32_frv_gc_mark_hook (sec, info, rel, h, sym)
2589d2201f2fSdrahn asection *sec;
2590d2201f2fSdrahn struct bfd_link_info *info ATTRIBUTE_UNUSED;
2591d2201f2fSdrahn Elf_Internal_Rela *rel;
2592d2201f2fSdrahn struct elf_link_hash_entry *h;
2593d2201f2fSdrahn Elf_Internal_Sym *sym;
2594d2201f2fSdrahn {
2595d2201f2fSdrahn if (h != NULL)
2596d2201f2fSdrahn {
2597d2201f2fSdrahn switch (ELF32_R_TYPE (rel->r_info))
2598d2201f2fSdrahn {
2599d2201f2fSdrahn case R_FRV_GNU_VTINHERIT:
2600d2201f2fSdrahn case R_FRV_GNU_VTENTRY:
2601d2201f2fSdrahn break;
2602d2201f2fSdrahn
2603d2201f2fSdrahn default:
2604d2201f2fSdrahn switch (h->root.type)
2605d2201f2fSdrahn {
2606d2201f2fSdrahn default:
2607d2201f2fSdrahn break;
2608d2201f2fSdrahn
2609d2201f2fSdrahn case bfd_link_hash_defined:
2610d2201f2fSdrahn case bfd_link_hash_defweak:
2611d2201f2fSdrahn return h->root.u.def.section;
2612d2201f2fSdrahn
2613d2201f2fSdrahn case bfd_link_hash_common:
2614d2201f2fSdrahn return h->root.u.c.p->section;
2615d2201f2fSdrahn }
2616d2201f2fSdrahn }
2617d2201f2fSdrahn }
2618d2201f2fSdrahn else
2619d2201f2fSdrahn return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
2620d2201f2fSdrahn
2621d2201f2fSdrahn return NULL;
2622d2201f2fSdrahn }
2623d2201f2fSdrahn
2624d2201f2fSdrahn /* Update the got entry reference counts for the section being removed. */
2625d2201f2fSdrahn
2626d2201f2fSdrahn static bfd_boolean
elf32_frv_gc_sweep_hook(abfd,info,sec,relocs)2627d2201f2fSdrahn elf32_frv_gc_sweep_hook (abfd, info, sec, relocs)
2628d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
2629d2201f2fSdrahn struct bfd_link_info *info ATTRIBUTE_UNUSED;
2630d2201f2fSdrahn asection *sec ATTRIBUTE_UNUSED;
2631d2201f2fSdrahn const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
2632d2201f2fSdrahn {
2633d2201f2fSdrahn return TRUE;
2634d2201f2fSdrahn }
2635d2201f2fSdrahn
2636d2201f2fSdrahn
2637d2201f2fSdrahn /* Hook called by the linker routine which adds symbols from an object
2638d2201f2fSdrahn file. We use it to put .comm items in .scomm, and not .comm. */
2639d2201f2fSdrahn
2640d2201f2fSdrahn static bfd_boolean
elf32_frv_add_symbol_hook(abfd,info,sym,namep,flagsp,secp,valp)2641d2201f2fSdrahn elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
2642d2201f2fSdrahn bfd *abfd;
2643d2201f2fSdrahn struct bfd_link_info *info;
2644*cf2f2c56Smiod Elf_Internal_Sym *sym;
2645d2201f2fSdrahn const char **namep ATTRIBUTE_UNUSED;
2646d2201f2fSdrahn flagword *flagsp ATTRIBUTE_UNUSED;
2647d2201f2fSdrahn asection **secp;
2648d2201f2fSdrahn bfd_vma *valp;
2649d2201f2fSdrahn {
2650d2201f2fSdrahn if (sym->st_shndx == SHN_COMMON
2651*cf2f2c56Smiod && !info->relocatable
2652d2201f2fSdrahn && (int)sym->st_size <= (int)bfd_get_gp_size (abfd))
2653d2201f2fSdrahn {
2654d2201f2fSdrahn /* Common symbols less than or equal to -G nn bytes are
2655d2201f2fSdrahn automatically put into .sbss. */
2656d2201f2fSdrahn
2657d2201f2fSdrahn asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
2658d2201f2fSdrahn
2659d2201f2fSdrahn if (scomm == NULL)
2660d2201f2fSdrahn {
2661d2201f2fSdrahn scomm = bfd_make_section (abfd, ".scommon");
2662d2201f2fSdrahn if (scomm == NULL
2663d2201f2fSdrahn || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
2664d2201f2fSdrahn | SEC_IS_COMMON
2665d2201f2fSdrahn | SEC_LINKER_CREATED)))
2666d2201f2fSdrahn return FALSE;
2667d2201f2fSdrahn }
2668d2201f2fSdrahn
2669d2201f2fSdrahn *secp = scomm;
2670d2201f2fSdrahn *valp = sym->st_size;
2671d2201f2fSdrahn }
2672d2201f2fSdrahn
2673d2201f2fSdrahn return TRUE;
2674d2201f2fSdrahn }
2675*cf2f2c56Smiod
2676*cf2f2c56Smiod /* Create a .got section, as well as its additional info field. This
2677*cf2f2c56Smiod is almost entirely copied from
2678*cf2f2c56Smiod elflink.c:_bfd_elf_create_got_section(). */
2679*cf2f2c56Smiod
2680*cf2f2c56Smiod static bfd_boolean
_frv_create_got_section(bfd * abfd,struct bfd_link_info * info)2681*cf2f2c56Smiod _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
2682*cf2f2c56Smiod {
2683*cf2f2c56Smiod flagword flags;
2684*cf2f2c56Smiod asection *s;
2685*cf2f2c56Smiod struct elf_link_hash_entry *h;
2686*cf2f2c56Smiod struct bfd_link_hash_entry *bh;
2687*cf2f2c56Smiod const struct elf_backend_data *bed = get_elf_backend_data (abfd);
2688*cf2f2c56Smiod int ptralign;
2689*cf2f2c56Smiod int offset;
2690*cf2f2c56Smiod
2691*cf2f2c56Smiod /* This function may be called more than once. */
2692*cf2f2c56Smiod s = bfd_get_section_by_name (abfd, ".got");
2693*cf2f2c56Smiod if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
2694*cf2f2c56Smiod return TRUE;
2695*cf2f2c56Smiod
2696*cf2f2c56Smiod /* Machine specific: although pointers are 32-bits wide, we want the
2697*cf2f2c56Smiod GOT to be aligned to a 64-bit boundary, such that function
2698*cf2f2c56Smiod descriptors in it can be accessed with 64-bit loads and
2699*cf2f2c56Smiod stores. */
2700*cf2f2c56Smiod ptralign = 3;
2701*cf2f2c56Smiod
2702*cf2f2c56Smiod flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
2703*cf2f2c56Smiod | SEC_LINKER_CREATED);
2704*cf2f2c56Smiod
2705*cf2f2c56Smiod s = bfd_make_section (abfd, ".got");
2706*cf2f2c56Smiod if (s == NULL
2707*cf2f2c56Smiod || !bfd_set_section_flags (abfd, s, flags)
2708*cf2f2c56Smiod || !bfd_set_section_alignment (abfd, s, ptralign))
2709*cf2f2c56Smiod return FALSE;
2710*cf2f2c56Smiod
2711*cf2f2c56Smiod if (bed->want_got_plt)
2712*cf2f2c56Smiod {
2713*cf2f2c56Smiod s = bfd_make_section (abfd, ".got.plt");
2714*cf2f2c56Smiod if (s == NULL
2715*cf2f2c56Smiod || !bfd_set_section_flags (abfd, s, flags)
2716*cf2f2c56Smiod || !bfd_set_section_alignment (abfd, s, ptralign))
2717*cf2f2c56Smiod return FALSE;
2718*cf2f2c56Smiod }
2719*cf2f2c56Smiod
2720*cf2f2c56Smiod if (bed->want_got_sym)
2721*cf2f2c56Smiod {
2722*cf2f2c56Smiod /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
2723*cf2f2c56Smiod (or .got.plt) section. We don't do this in the linker script
2724*cf2f2c56Smiod because we don't want to define the symbol if we are not creating
2725*cf2f2c56Smiod a global offset table. */
2726*cf2f2c56Smiod bh = NULL;
2727*cf2f2c56Smiod if (!(_bfd_generic_link_add_one_symbol
2728*cf2f2c56Smiod (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
2729*cf2f2c56Smiod bed->got_symbol_offset, (const char *) NULL, FALSE,
2730*cf2f2c56Smiod bed->collect, &bh)))
2731*cf2f2c56Smiod return FALSE;
2732*cf2f2c56Smiod h = (struct elf_link_hash_entry *) bh;
2733*cf2f2c56Smiod h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
2734*cf2f2c56Smiod h->type = STT_OBJECT;
2735*cf2f2c56Smiod
2736*cf2f2c56Smiod /* Machine-specific: we want the symbol for executables as
2737*cf2f2c56Smiod well. */
2738*cf2f2c56Smiod if (! bfd_elf_link_record_dynamic_symbol (info, h))
2739*cf2f2c56Smiod return FALSE;
2740*cf2f2c56Smiod
2741*cf2f2c56Smiod elf_hash_table (info)->hgot = h;
2742*cf2f2c56Smiod }
2743*cf2f2c56Smiod
2744*cf2f2c56Smiod /* The first bit of the global offset table is the header. */
2745*cf2f2c56Smiod s->_raw_size += bed->got_header_size + bed->got_symbol_offset;
2746*cf2f2c56Smiod
2747*cf2f2c56Smiod /* This is the machine-specific part. Create and initialize section
2748*cf2f2c56Smiod data for the got. */
2749*cf2f2c56Smiod if (IS_FDPIC (abfd))
2750*cf2f2c56Smiod {
2751*cf2f2c56Smiod frvfdpic_got_section (info) = s;
2752*cf2f2c56Smiod frvfdpic_relocs_info (info) = htab_try_create (1, frvfdpic_relocs_info_hash,
2753*cf2f2c56Smiod frvfdpic_relocs_info_eq,
2754*cf2f2c56Smiod (htab_del) NULL);
2755*cf2f2c56Smiod if (! frvfdpic_relocs_info (info))
2756*cf2f2c56Smiod return FALSE;
2757*cf2f2c56Smiod
2758*cf2f2c56Smiod s = bfd_make_section (abfd, ".rel.got");
2759*cf2f2c56Smiod if (s == NULL
2760*cf2f2c56Smiod || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY))
2761*cf2f2c56Smiod || ! bfd_set_section_alignment (abfd, s, 2))
2762*cf2f2c56Smiod return FALSE;
2763*cf2f2c56Smiod
2764*cf2f2c56Smiod frvfdpic_gotrel_section (info) = s;
2765*cf2f2c56Smiod
2766*cf2f2c56Smiod /* Machine-specific. */
2767*cf2f2c56Smiod s = bfd_make_section (abfd, ".rofixup");
2768*cf2f2c56Smiod if (s == NULL
2769*cf2f2c56Smiod || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY))
2770*cf2f2c56Smiod || ! bfd_set_section_alignment (abfd, s, 2))
2771*cf2f2c56Smiod return FALSE;
2772*cf2f2c56Smiod
2773*cf2f2c56Smiod frvfdpic_gotfixup_section (info) = s;
2774*cf2f2c56Smiod offset = -2048;
2775*cf2f2c56Smiod flags = BSF_GLOBAL;
2776*cf2f2c56Smiod }
2777*cf2f2c56Smiod else
2778*cf2f2c56Smiod {
2779*cf2f2c56Smiod offset = 2048;
2780*cf2f2c56Smiod flags = BSF_GLOBAL | BSF_WEAK;
2781*cf2f2c56Smiod }
2782*cf2f2c56Smiod
2783*cf2f2c56Smiod /* Define _gp in .rofixup, for FDPIC, or .got otherwise. If it
2784*cf2f2c56Smiod turns out that we're linking with a different linker script, the
2785*cf2f2c56Smiod linker script will override it. */
2786*cf2f2c56Smiod bh = NULL;
2787*cf2f2c56Smiod if (!(_bfd_generic_link_add_one_symbol
2788*cf2f2c56Smiod (info, abfd, "_gp", flags, s, offset, (const char *) NULL, FALSE,
2789*cf2f2c56Smiod bed->collect, &bh)))
2790*cf2f2c56Smiod return FALSE;
2791*cf2f2c56Smiod h = (struct elf_link_hash_entry *) bh;
2792*cf2f2c56Smiod h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
2793*cf2f2c56Smiod h->type = STT_OBJECT;
2794*cf2f2c56Smiod
2795*cf2f2c56Smiod /* Machine-specific: we want the symbol for executables as well. */
2796*cf2f2c56Smiod if (IS_FDPIC (abfd) && ! bfd_elf_link_record_dynamic_symbol (info, h))
2797*cf2f2c56Smiod return FALSE;
2798*cf2f2c56Smiod
2799*cf2f2c56Smiod return TRUE;
2800*cf2f2c56Smiod }
2801*cf2f2c56Smiod
2802*cf2f2c56Smiod /* Make sure the got and plt sections exist, and that our pointers in
2803*cf2f2c56Smiod the link hash table point to them. */
2804*cf2f2c56Smiod
2805*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_create_dynamic_sections(bfd * abfd,struct bfd_link_info * info)2806*cf2f2c56Smiod elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
2807*cf2f2c56Smiod {
2808*cf2f2c56Smiod /* This is mostly copied from
2809*cf2f2c56Smiod elflink.c:_bfd_elf_create_dynamic_sections(). */
2810*cf2f2c56Smiod flagword flags, pltflags;
2811*cf2f2c56Smiod asection *s;
2812*cf2f2c56Smiod const struct elf_backend_data *bed = get_elf_backend_data (abfd);
2813*cf2f2c56Smiod
2814*cf2f2c56Smiod /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
2815*cf2f2c56Smiod .rel[a].bss sections. */
2816*cf2f2c56Smiod
2817*cf2f2c56Smiod flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
2818*cf2f2c56Smiod | SEC_LINKER_CREATED);
2819*cf2f2c56Smiod
2820*cf2f2c56Smiod pltflags = flags;
2821*cf2f2c56Smiod pltflags |= SEC_CODE;
2822*cf2f2c56Smiod if (bed->plt_not_loaded)
2823*cf2f2c56Smiod pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
2824*cf2f2c56Smiod if (bed->plt_readonly)
2825*cf2f2c56Smiod pltflags |= SEC_READONLY;
2826*cf2f2c56Smiod
2827*cf2f2c56Smiod s = bfd_make_section (abfd, ".plt");
2828*cf2f2c56Smiod if (s == NULL
2829*cf2f2c56Smiod || ! bfd_set_section_flags (abfd, s, pltflags)
2830*cf2f2c56Smiod || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
2831*cf2f2c56Smiod return FALSE;
2832*cf2f2c56Smiod /* FRV-specific: remember it. */
2833*cf2f2c56Smiod frvfdpic_plt_section (info) = s;
2834*cf2f2c56Smiod
2835*cf2f2c56Smiod if (bed->want_plt_sym)
2836*cf2f2c56Smiod {
2837*cf2f2c56Smiod /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
2838*cf2f2c56Smiod .plt section. */
2839*cf2f2c56Smiod struct elf_link_hash_entry *h;
2840*cf2f2c56Smiod struct bfd_link_hash_entry *bh = NULL;
2841*cf2f2c56Smiod
2842*cf2f2c56Smiod if (! (_bfd_generic_link_add_one_symbol
2843*cf2f2c56Smiod (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 0, NULL,
2844*cf2f2c56Smiod FALSE, get_elf_backend_data (abfd)->collect, &bh)))
2845*cf2f2c56Smiod return FALSE;
2846*cf2f2c56Smiod h = (struct elf_link_hash_entry *) bh;
2847*cf2f2c56Smiod h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
2848*cf2f2c56Smiod h->type = STT_OBJECT;
2849*cf2f2c56Smiod
2850*cf2f2c56Smiod if (! info->executable
2851*cf2f2c56Smiod && ! bfd_elf_link_record_dynamic_symbol (info, h))
2852*cf2f2c56Smiod return FALSE;
2853*cf2f2c56Smiod }
2854*cf2f2c56Smiod
2855*cf2f2c56Smiod /* FRV-specific: we want rel relocations for the plt. */
2856*cf2f2c56Smiod s = bfd_make_section (abfd, ".rel.plt");
2857*cf2f2c56Smiod if (s == NULL
2858*cf2f2c56Smiod || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
2859*cf2f2c56Smiod || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
2860*cf2f2c56Smiod return FALSE;
2861*cf2f2c56Smiod /* FRV-specific: remember it. */
2862*cf2f2c56Smiod frvfdpic_pltrel_section (info) = s;
2863*cf2f2c56Smiod
2864*cf2f2c56Smiod /* FRV-specific: we want to create the GOT in the FRV way. */
2865*cf2f2c56Smiod if (! _frv_create_got_section (abfd, info))
2866*cf2f2c56Smiod return FALSE;
2867*cf2f2c56Smiod
2868*cf2f2c56Smiod /* FRV-specific: make sure we created everything we wanted. */
2869*cf2f2c56Smiod BFD_ASSERT (frvfdpic_got_section (info) && frvfdpic_gotrel_section (info)
2870*cf2f2c56Smiod && frvfdpic_gotfixup_section (info)
2871*cf2f2c56Smiod && frvfdpic_plt_section (info)
2872*cf2f2c56Smiod && frvfdpic_pltrel_section (info));
2873*cf2f2c56Smiod
2874*cf2f2c56Smiod if (bed->want_dynbss)
2875*cf2f2c56Smiod {
2876*cf2f2c56Smiod /* The .dynbss section is a place to put symbols which are defined
2877*cf2f2c56Smiod by dynamic objects, are referenced by regular objects, and are
2878*cf2f2c56Smiod not functions. We must allocate space for them in the process
2879*cf2f2c56Smiod image and use a R_*_COPY reloc to tell the dynamic linker to
2880*cf2f2c56Smiod initialize them at run time. The linker script puts the .dynbss
2881*cf2f2c56Smiod section into the .bss section of the final image. */
2882*cf2f2c56Smiod s = bfd_make_section (abfd, ".dynbss");
2883*cf2f2c56Smiod if (s == NULL
2884*cf2f2c56Smiod || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED))
2885*cf2f2c56Smiod return FALSE;
2886*cf2f2c56Smiod
2887*cf2f2c56Smiod /* The .rel[a].bss section holds copy relocs. This section is not
2888*cf2f2c56Smiod normally needed. We need to create it here, though, so that the
2889*cf2f2c56Smiod linker will map it to an output section. We can't just create it
2890*cf2f2c56Smiod only if we need it, because we will not know whether we need it
2891*cf2f2c56Smiod until we have seen all the input files, and the first time the
2892*cf2f2c56Smiod main linker code calls BFD after examining all the input files
2893*cf2f2c56Smiod (size_dynamic_sections) the input sections have already been
2894*cf2f2c56Smiod mapped to the output sections. If the section turns out not to
2895*cf2f2c56Smiod be needed, we can discard it later. We will never need this
2896*cf2f2c56Smiod section when generating a shared object, since they do not use
2897*cf2f2c56Smiod copy relocs. */
2898*cf2f2c56Smiod if (! info->shared)
2899*cf2f2c56Smiod {
2900*cf2f2c56Smiod s = bfd_make_section (abfd,
2901*cf2f2c56Smiod (bed->default_use_rela_p
2902*cf2f2c56Smiod ? ".rela.bss" : ".rel.bss"));
2903*cf2f2c56Smiod if (s == NULL
2904*cf2f2c56Smiod || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
2905*cf2f2c56Smiod || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
2906*cf2f2c56Smiod return FALSE;
2907*cf2f2c56Smiod }
2908*cf2f2c56Smiod }
2909*cf2f2c56Smiod
2910*cf2f2c56Smiod return TRUE;
2911*cf2f2c56Smiod }
2912*cf2f2c56Smiod
2913*cf2f2c56Smiod /* The name of the dynamic interpreter. This is put in the .interp
2914*cf2f2c56Smiod section. */
2915*cf2f2c56Smiod
2916*cf2f2c56Smiod #define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
2917*cf2f2c56Smiod
2918*cf2f2c56Smiod #define DEFAULT_STACK_SIZE 0x20000
2919*cf2f2c56Smiod
2920*cf2f2c56Smiod /* This structure is used to collect the number of entries present in
2921*cf2f2c56Smiod each addressable range of the got. */
2922*cf2f2c56Smiod struct _frvfdpic_dynamic_got_info
2923*cf2f2c56Smiod {
2924*cf2f2c56Smiod /* Several bits of information about the current link. */
2925*cf2f2c56Smiod struct bfd_link_info *info;
2926*cf2f2c56Smiod /* Total size needed for GOT entries within the 12-, 16- or 32-bit
2927*cf2f2c56Smiod ranges. */
2928*cf2f2c56Smiod bfd_vma got12, gotlos, gothilo;
2929*cf2f2c56Smiod /* Total size needed for function descriptor entries within the 12-,
2930*cf2f2c56Smiod 16- or 32-bit ranges. */
2931*cf2f2c56Smiod bfd_vma fd12, fdlos, fdhilo;
2932*cf2f2c56Smiod /* Total size needed function descriptor entries referenced in PLT
2933*cf2f2c56Smiod entries, that would be profitable to place in offsets close to
2934*cf2f2c56Smiod the PIC register. */
2935*cf2f2c56Smiod bfd_vma fdplt;
2936*cf2f2c56Smiod /* Total size needed by lazy PLT entries. */
2937*cf2f2c56Smiod bfd_vma lzplt;
2938*cf2f2c56Smiod /* Number of relocations carried over from input object files. */
2939*cf2f2c56Smiod unsigned long relocs;
2940*cf2f2c56Smiod /* Number of fixups introduced by relocations in input object files. */
2941*cf2f2c56Smiod unsigned long fixups;
2942*cf2f2c56Smiod };
2943*cf2f2c56Smiod
2944*cf2f2c56Smiod /* Compute the total GOT size required by each symbol in each range.
2945*cf2f2c56Smiod Symbols may require up to 4 words in the GOT: an entry pointing to
2946*cf2f2c56Smiod the symbol, an entry pointing to its function descriptor, and a
2947*cf2f2c56Smiod private function descriptors taking two words. */
2948*cf2f2c56Smiod
2949*cf2f2c56Smiod static int
_frvfdpic_count_got_plt_entries(void ** entryp,void * dinfo_)2950*cf2f2c56Smiod _frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
2951*cf2f2c56Smiod {
2952*cf2f2c56Smiod struct frvfdpic_relocs_info *entry = *entryp;
2953*cf2f2c56Smiod struct _frvfdpic_dynamic_got_info *dinfo = dinfo_;
2954*cf2f2c56Smiod unsigned relocs = 0, fixups = 0;
2955*cf2f2c56Smiod
2956*cf2f2c56Smiod /* Allocate space for a GOT entry pointing to the symbol. */
2957*cf2f2c56Smiod if (entry->got12)
2958*cf2f2c56Smiod dinfo->got12 += 4;
2959*cf2f2c56Smiod else if (entry->gotlos)
2960*cf2f2c56Smiod dinfo->gotlos += 4;
2961*cf2f2c56Smiod else if (entry->gothilo)
2962*cf2f2c56Smiod dinfo->gothilo += 4;
2963*cf2f2c56Smiod else
2964*cf2f2c56Smiod entry->relocs32--;
2965*cf2f2c56Smiod entry->relocs32++;
2966*cf2f2c56Smiod
2967*cf2f2c56Smiod /* Allocate space for a GOT entry pointing to the function
2968*cf2f2c56Smiod descriptor. */
2969*cf2f2c56Smiod if (entry->fdgot12)
2970*cf2f2c56Smiod dinfo->got12 += 4;
2971*cf2f2c56Smiod else if (entry->fdgotlos)
2972*cf2f2c56Smiod dinfo->gotlos += 4;
2973*cf2f2c56Smiod else if (entry->fdgothilo)
2974*cf2f2c56Smiod dinfo->gothilo += 4;
2975*cf2f2c56Smiod else
2976*cf2f2c56Smiod entry->relocsfd--;
2977*cf2f2c56Smiod entry->relocsfd++;
2978*cf2f2c56Smiod
2979*cf2f2c56Smiod /* Decide whether we need a PLT entry, a function descriptor in the
2980*cf2f2c56Smiod GOT, and a lazy PLT entry for this symbol. */
2981*cf2f2c56Smiod entry->plt = entry->call
2982*cf2f2c56Smiod && entry->symndx == -1 && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
2983*cf2f2c56Smiod && elf_hash_table (dinfo->info)->dynamic_sections_created;
2984*cf2f2c56Smiod entry->privfd = entry->plt
2985*cf2f2c56Smiod || entry->fdgoff12 || entry->fdgofflos || entry->fdgoffhilo
2986*cf2f2c56Smiod || ((entry->fd || entry->fdgot12 || entry->fdgotlos || entry->fdgothilo)
2987*cf2f2c56Smiod && (entry->symndx != -1
2988*cf2f2c56Smiod || FRVFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h)));
2989*cf2f2c56Smiod entry->lazyplt = entry->privfd
2990*cf2f2c56Smiod && entry->symndx == -1 && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
2991*cf2f2c56Smiod && ! (dinfo->info->flags & DF_BIND_NOW)
2992*cf2f2c56Smiod && elf_hash_table (dinfo->info)->dynamic_sections_created;
2993*cf2f2c56Smiod
2994*cf2f2c56Smiod /* Allocate space for a function descriptor. */
2995*cf2f2c56Smiod if (entry->fdgoff12)
2996*cf2f2c56Smiod dinfo->fd12 += 8;
2997*cf2f2c56Smiod else if (entry->fdgofflos)
2998*cf2f2c56Smiod dinfo->fdlos += 8;
2999*cf2f2c56Smiod else if (entry->privfd && entry->plt)
3000*cf2f2c56Smiod dinfo->fdplt += 8;
3001*cf2f2c56Smiod else if (entry->privfd)
3002*cf2f2c56Smiod dinfo->fdhilo += 8;
3003*cf2f2c56Smiod else
3004*cf2f2c56Smiod entry->relocsfdv--;
3005*cf2f2c56Smiod entry->relocsfdv++;
3006*cf2f2c56Smiod
3007*cf2f2c56Smiod if (entry->lazyplt)
3008*cf2f2c56Smiod dinfo->lzplt += 8;
3009*cf2f2c56Smiod
3010*cf2f2c56Smiod if (!dinfo->info->executable || dinfo->info->pie)
3011*cf2f2c56Smiod relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
3012*cf2f2c56Smiod else
3013*cf2f2c56Smiod {
3014*cf2f2c56Smiod if (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h))
3015*cf2f2c56Smiod {
3016*cf2f2c56Smiod if (entry->symndx != -1
3017*cf2f2c56Smiod || entry->d.h->root.type != bfd_link_hash_undefweak)
3018*cf2f2c56Smiod fixups += entry->relocs32 + 2 * entry->relocsfdv;
3019*cf2f2c56Smiod }
3020*cf2f2c56Smiod else
3021*cf2f2c56Smiod relocs += entry->relocs32 + entry->relocsfdv;
3022*cf2f2c56Smiod
3023*cf2f2c56Smiod if (entry->symndx != -1
3024*cf2f2c56Smiod || FRVFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
3025*cf2f2c56Smiod {
3026*cf2f2c56Smiod if (entry->symndx != -1
3027*cf2f2c56Smiod || entry->d.h->root.type != bfd_link_hash_undefweak)
3028*cf2f2c56Smiod fixups += entry->relocsfd;
3029*cf2f2c56Smiod }
3030*cf2f2c56Smiod else
3031*cf2f2c56Smiod relocs += entry->relocsfd;
3032*cf2f2c56Smiod }
3033*cf2f2c56Smiod
3034*cf2f2c56Smiod entry->dynrelocs += relocs;
3035*cf2f2c56Smiod entry->fixups += fixups;
3036*cf2f2c56Smiod dinfo->relocs += relocs;
3037*cf2f2c56Smiod dinfo->fixups += fixups;
3038*cf2f2c56Smiod
3039*cf2f2c56Smiod return 1;
3040*cf2f2c56Smiod }
3041*cf2f2c56Smiod
3042*cf2f2c56Smiod /* This structure is used to assign offsets to got entries, function
3043*cf2f2c56Smiod descriptors, plt entries and lazy plt entries. */
3044*cf2f2c56Smiod
3045*cf2f2c56Smiod struct _frvfdpic_dynamic_got_plt_info
3046*cf2f2c56Smiod {
3047*cf2f2c56Smiod /* Summary information collected with _frvfdpic_count_got_plt_entries. */
3048*cf2f2c56Smiod struct _frvfdpic_dynamic_got_info g;
3049*cf2f2c56Smiod
3050*cf2f2c56Smiod /* For each addressable range, we record a MAX (positive) and MIN
3051*cf2f2c56Smiod (negative) value. CUR is used to assign got entries, and it's
3052*cf2f2c56Smiod incremented from an initial positive value to MAX, then from MIN
3053*cf2f2c56Smiod to FDCUR (unless FDCUR wraps around first). FDCUR is used to
3054*cf2f2c56Smiod assign function descriptors, and it's decreased from an initial
3055*cf2f2c56Smiod non-positive value to MIN, then from MAX down to CUR (unless CUR
3056*cf2f2c56Smiod wraps around first). All of MIN, MAX, CUR and FDCUR always point
3057*cf2f2c56Smiod to even words. ODD, if non-zero, indicates an odd word to be
3058*cf2f2c56Smiod used for the next got entry, otherwise CUR is used and
3059*cf2f2c56Smiod incremented by a pair of words, wrapping around when it reaches
3060*cf2f2c56Smiod MAX. FDCUR is decremented (and wrapped) before the next function
3061*cf2f2c56Smiod descriptor is chosen. FDPLT indicates the number of remaining
3062*cf2f2c56Smiod slots that can be used for function descriptors used only by PLT
3063*cf2f2c56Smiod entries. */
3064*cf2f2c56Smiod struct _frvfdpic_dynamic_got_alloc_data
3065*cf2f2c56Smiod {
3066*cf2f2c56Smiod bfd_signed_vma max, cur, odd, fdcur, min;
3067*cf2f2c56Smiod bfd_vma fdplt;
3068*cf2f2c56Smiod } got12, gotlos, gothilo;
3069*cf2f2c56Smiod };
3070*cf2f2c56Smiod
3071*cf2f2c56Smiod /* Determine the positive and negative ranges to be used by each
3072*cf2f2c56Smiod offset range in the GOT. FDCUR and CUR, that must be aligned to a
3073*cf2f2c56Smiod double-word boundary, are the minimum (negative) and maximum
3074*cf2f2c56Smiod (positive) GOT offsets already used by previous ranges, except for
3075*cf2f2c56Smiod an ODD entry that may have been left behind. GOT and FD indicate
3076*cf2f2c56Smiod the size of GOT entries and function descriptors that must be
3077*cf2f2c56Smiod placed within the range from -WRAP to WRAP. If there's room left,
3078*cf2f2c56Smiod up to FDPLT bytes should be reserved for additional function
3079*cf2f2c56Smiod descriptors. */
3080*cf2f2c56Smiod
3081*cf2f2c56Smiod inline static bfd_signed_vma
_frvfdpic_compute_got_alloc_data(struct _frvfdpic_dynamic_got_alloc_data * gad,bfd_signed_vma fdcur,bfd_signed_vma odd,bfd_signed_vma cur,bfd_vma got,bfd_vma fd,bfd_vma fdplt,bfd_vma wrap)3082*cf2f2c56Smiod _frvfdpic_compute_got_alloc_data (struct _frvfdpic_dynamic_got_alloc_data *gad,
3083*cf2f2c56Smiod bfd_signed_vma fdcur,
3084*cf2f2c56Smiod bfd_signed_vma odd,
3085*cf2f2c56Smiod bfd_signed_vma cur,
3086*cf2f2c56Smiod bfd_vma got,
3087*cf2f2c56Smiod bfd_vma fd,
3088*cf2f2c56Smiod bfd_vma fdplt,
3089*cf2f2c56Smiod bfd_vma wrap)
3090*cf2f2c56Smiod {
3091*cf2f2c56Smiod bfd_signed_vma wrapmin = -wrap;
3092*cf2f2c56Smiod
3093*cf2f2c56Smiod /* Start at the given initial points. */
3094*cf2f2c56Smiod gad->fdcur = fdcur;
3095*cf2f2c56Smiod gad->cur = cur;
3096*cf2f2c56Smiod
3097*cf2f2c56Smiod /* If we had an incoming odd word and we have any got entries that
3098*cf2f2c56Smiod are going to use it, consume it, otherwise leave gad->odd at
3099*cf2f2c56Smiod zero. We might force gad->odd to zero and return the incoming
3100*cf2f2c56Smiod odd such that it is used by the next range, but then GOT entries
3101*cf2f2c56Smiod might appear to be out of order and we wouldn't be able to
3102*cf2f2c56Smiod shorten the GOT by one word if it turns out to end with an
3103*cf2f2c56Smiod unpaired GOT entry. */
3104*cf2f2c56Smiod if (odd && got)
3105*cf2f2c56Smiod {
3106*cf2f2c56Smiod gad->odd = odd;
3107*cf2f2c56Smiod got -= 4;
3108*cf2f2c56Smiod odd = 0;
3109*cf2f2c56Smiod }
3110*cf2f2c56Smiod else
3111*cf2f2c56Smiod gad->odd = 0;
3112*cf2f2c56Smiod
3113*cf2f2c56Smiod /* If we're left with an unpaired GOT entry, compute its location
3114*cf2f2c56Smiod such that we can return it. Otherwise, if got doesn't require an
3115*cf2f2c56Smiod odd number of words here, either odd was already zero in the
3116*cf2f2c56Smiod block above, or it was set to zero because got was non-zero, or
3117*cf2f2c56Smiod got was already zero. In the latter case, we want the value of
3118*cf2f2c56Smiod odd to carry over to the return statement, so we don't want to
3119*cf2f2c56Smiod reset odd unless the condition below is true. */
3120*cf2f2c56Smiod if (got & 4)
3121*cf2f2c56Smiod {
3122*cf2f2c56Smiod odd = cur + got;
3123*cf2f2c56Smiod got += 4;
3124*cf2f2c56Smiod }
3125*cf2f2c56Smiod
3126*cf2f2c56Smiod /* Compute the tentative boundaries of this range. */
3127*cf2f2c56Smiod gad->max = cur + got;
3128*cf2f2c56Smiod gad->min = fdcur - fd;
3129*cf2f2c56Smiod gad->fdplt = 0;
3130*cf2f2c56Smiod
3131*cf2f2c56Smiod /* If function descriptors took too much space, wrap some of them
3132*cf2f2c56Smiod around. */
3133*cf2f2c56Smiod if (gad->min < wrapmin)
3134*cf2f2c56Smiod {
3135*cf2f2c56Smiod gad->max += wrapmin - gad->min;
3136*cf2f2c56Smiod gad->min = wrapmin;
3137*cf2f2c56Smiod }
3138*cf2f2c56Smiod /* If there is space left and we have function descriptors
3139*cf2f2c56Smiod referenced in PLT entries that could take advantage of shorter
3140*cf2f2c56Smiod offsets, place them here. */
3141*cf2f2c56Smiod else if (fdplt && gad->min > wrapmin)
3142*cf2f2c56Smiod {
3143*cf2f2c56Smiod bfd_vma fds;
3144*cf2f2c56Smiod if ((bfd_vma) (gad->min - wrapmin) < fdplt)
3145*cf2f2c56Smiod fds = gad->min - wrapmin;
3146*cf2f2c56Smiod else
3147*cf2f2c56Smiod fds = fdplt;
3148*cf2f2c56Smiod
3149*cf2f2c56Smiod fdplt -= fds;
3150*cf2f2c56Smiod gad->min -= fds;
3151*cf2f2c56Smiod gad->fdplt += fds;
3152*cf2f2c56Smiod }
3153*cf2f2c56Smiod
3154*cf2f2c56Smiod /* If GOT entries took too much space, wrap some of them around.
3155*cf2f2c56Smiod This may well cause gad->min to become lower than wrapmin. This
3156*cf2f2c56Smiod will cause a relocation overflow later on, so we don't have to
3157*cf2f2c56Smiod report it here . */
3158*cf2f2c56Smiod if ((bfd_vma) gad->max > wrap)
3159*cf2f2c56Smiod {
3160*cf2f2c56Smiod gad->min -= gad->max - wrap;
3161*cf2f2c56Smiod gad->max = wrap;
3162*cf2f2c56Smiod }
3163*cf2f2c56Smiod /* If there is more space left, try to place some more function
3164*cf2f2c56Smiod descriptors for PLT entries. */
3165*cf2f2c56Smiod else if (fdplt && (bfd_vma) gad->max < wrap)
3166*cf2f2c56Smiod {
3167*cf2f2c56Smiod bfd_vma fds;
3168*cf2f2c56Smiod if ((bfd_vma) (wrap - gad->max) < fdplt)
3169*cf2f2c56Smiod fds = wrap - gad->max;
3170*cf2f2c56Smiod else
3171*cf2f2c56Smiod fds = fdplt;
3172*cf2f2c56Smiod
3173*cf2f2c56Smiod fdplt -= fds;
3174*cf2f2c56Smiod gad->max += fds;
3175*cf2f2c56Smiod gad->fdplt += fds;
3176*cf2f2c56Smiod }
3177*cf2f2c56Smiod
3178*cf2f2c56Smiod /* If odd was initially computed as an offset past the wrap point,
3179*cf2f2c56Smiod wrap it around. */
3180*cf2f2c56Smiod if (odd > gad->max)
3181*cf2f2c56Smiod odd = gad->min + odd - gad->max;
3182*cf2f2c56Smiod
3183*cf2f2c56Smiod /* _frvfdpic_get_got_entry() below will always wrap gad->cur if needed
3184*cf2f2c56Smiod before returning, so do it here too. This guarantees that,
3185*cf2f2c56Smiod should cur and fdcur meet at the wrap point, they'll both be
3186*cf2f2c56Smiod equal to min. */
3187*cf2f2c56Smiod if (gad->cur == gad->max)
3188*cf2f2c56Smiod gad->cur = gad->min;
3189*cf2f2c56Smiod
3190*cf2f2c56Smiod return odd;
3191*cf2f2c56Smiod }
3192*cf2f2c56Smiod
3193*cf2f2c56Smiod /* Compute the location of the next GOT entry, given the allocation
3194*cf2f2c56Smiod data for a range. */
3195*cf2f2c56Smiod
3196*cf2f2c56Smiod inline static bfd_signed_vma
_frvfdpic_get_got_entry(struct _frvfdpic_dynamic_got_alloc_data * gad)3197*cf2f2c56Smiod _frvfdpic_get_got_entry (struct _frvfdpic_dynamic_got_alloc_data *gad)
3198*cf2f2c56Smiod {
3199*cf2f2c56Smiod bfd_signed_vma ret;
3200*cf2f2c56Smiod
3201*cf2f2c56Smiod if (gad->odd)
3202*cf2f2c56Smiod {
3203*cf2f2c56Smiod /* If there was an odd word left behind, use it. */
3204*cf2f2c56Smiod ret = gad->odd;
3205*cf2f2c56Smiod gad->odd = 0;
3206*cf2f2c56Smiod }
3207*cf2f2c56Smiod else
3208*cf2f2c56Smiod {
3209*cf2f2c56Smiod /* Otherwise, use the word pointed to by cur, reserve the next
3210*cf2f2c56Smiod as an odd word, and skip to the next pair of words, possibly
3211*cf2f2c56Smiod wrapping around. */
3212*cf2f2c56Smiod ret = gad->cur;
3213*cf2f2c56Smiod gad->odd = gad->cur + 4;
3214*cf2f2c56Smiod gad->cur += 8;
3215*cf2f2c56Smiod if (gad->cur == gad->max)
3216*cf2f2c56Smiod gad->cur = gad->min;
3217*cf2f2c56Smiod }
3218*cf2f2c56Smiod
3219*cf2f2c56Smiod return ret;
3220*cf2f2c56Smiod }
3221*cf2f2c56Smiod
3222*cf2f2c56Smiod /* Compute the location of the next function descriptor entry in the
3223*cf2f2c56Smiod GOT, given the allocation data for a range. */
3224*cf2f2c56Smiod
3225*cf2f2c56Smiod inline static bfd_signed_vma
_frvfdpic_get_fd_entry(struct _frvfdpic_dynamic_got_alloc_data * gad)3226*cf2f2c56Smiod _frvfdpic_get_fd_entry (struct _frvfdpic_dynamic_got_alloc_data *gad)
3227*cf2f2c56Smiod {
3228*cf2f2c56Smiod /* If we're at the bottom, wrap around, and only then allocate the
3229*cf2f2c56Smiod next pair of words. */
3230*cf2f2c56Smiod if (gad->fdcur == gad->min)
3231*cf2f2c56Smiod gad->fdcur = gad->max;
3232*cf2f2c56Smiod return gad->fdcur -= 8;
3233*cf2f2c56Smiod }
3234*cf2f2c56Smiod
3235*cf2f2c56Smiod /* Assign GOT offsets for every GOT entry and function descriptor.
3236*cf2f2c56Smiod Doing everything in a single pass is tricky. */
3237*cf2f2c56Smiod
3238*cf2f2c56Smiod static int
_frvfdpic_assign_got_entries(void ** entryp,void * info_)3239*cf2f2c56Smiod _frvfdpic_assign_got_entries (void **entryp, void *info_)
3240*cf2f2c56Smiod {
3241*cf2f2c56Smiod struct frvfdpic_relocs_info *entry = *entryp;
3242*cf2f2c56Smiod struct _frvfdpic_dynamic_got_plt_info *dinfo = info_;
3243*cf2f2c56Smiod
3244*cf2f2c56Smiod if (entry->got12)
3245*cf2f2c56Smiod entry->got_entry = _frvfdpic_get_got_entry (&dinfo->got12);
3246*cf2f2c56Smiod else if (entry->gotlos)
3247*cf2f2c56Smiod entry->got_entry = _frvfdpic_get_got_entry (&dinfo->gotlos);
3248*cf2f2c56Smiod else if (entry->gothilo)
3249*cf2f2c56Smiod entry->got_entry = _frvfdpic_get_got_entry (&dinfo->gothilo);
3250*cf2f2c56Smiod
3251*cf2f2c56Smiod if (entry->fdgot12)
3252*cf2f2c56Smiod entry->fdgot_entry = _frvfdpic_get_got_entry (&dinfo->got12);
3253*cf2f2c56Smiod else if (entry->fdgotlos)
3254*cf2f2c56Smiod entry->fdgot_entry = _frvfdpic_get_got_entry (&dinfo->gotlos);
3255*cf2f2c56Smiod else if (entry->fdgothilo)
3256*cf2f2c56Smiod entry->fdgot_entry = _frvfdpic_get_got_entry (&dinfo->gothilo);
3257*cf2f2c56Smiod
3258*cf2f2c56Smiod if (entry->fdgoff12)
3259*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->got12);
3260*cf2f2c56Smiod else if (entry->plt && dinfo->got12.fdplt)
3261*cf2f2c56Smiod {
3262*cf2f2c56Smiod dinfo->got12.fdplt -= 8;
3263*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->got12);
3264*cf2f2c56Smiod }
3265*cf2f2c56Smiod else if (entry->fdgofflos)
3266*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gotlos);
3267*cf2f2c56Smiod else if (entry->plt && dinfo->gotlos.fdplt)
3268*cf2f2c56Smiod {
3269*cf2f2c56Smiod dinfo->gotlos.fdplt -= 8;
3270*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gotlos);
3271*cf2f2c56Smiod }
3272*cf2f2c56Smiod else if (entry->plt)
3273*cf2f2c56Smiod {
3274*cf2f2c56Smiod dinfo->gothilo.fdplt -= 8;
3275*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
3276*cf2f2c56Smiod }
3277*cf2f2c56Smiod else if (entry->privfd)
3278*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
3279*cf2f2c56Smiod
3280*cf2f2c56Smiod return 1;
3281*cf2f2c56Smiod }
3282*cf2f2c56Smiod
3283*cf2f2c56Smiod /* Assign GOT offsets to private function descriptors used by PLT
3284*cf2f2c56Smiod entries (or referenced by 32-bit offsets), as well as PLT entries
3285*cf2f2c56Smiod and lazy PLT entries. */
3286*cf2f2c56Smiod
3287*cf2f2c56Smiod static int
_frvfdpic_assign_plt_entries(void ** entryp,void * info_)3288*cf2f2c56Smiod _frvfdpic_assign_plt_entries (void **entryp, void *info_)
3289*cf2f2c56Smiod {
3290*cf2f2c56Smiod struct frvfdpic_relocs_info *entry = *entryp;
3291*cf2f2c56Smiod struct _frvfdpic_dynamic_got_plt_info *dinfo = info_;
3292*cf2f2c56Smiod
3293*cf2f2c56Smiod /* If this symbol requires a local function descriptor, allocate
3294*cf2f2c56Smiod one. */
3295*cf2f2c56Smiod if (entry->privfd && entry->fd_entry == 0)
3296*cf2f2c56Smiod {
3297*cf2f2c56Smiod if (dinfo->got12.fdplt)
3298*cf2f2c56Smiod {
3299*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->got12);
3300*cf2f2c56Smiod dinfo->got12.fdplt -= 8;
3301*cf2f2c56Smiod }
3302*cf2f2c56Smiod else if (dinfo->gotlos.fdplt)
3303*cf2f2c56Smiod {
3304*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gotlos);
3305*cf2f2c56Smiod dinfo->gotlos.fdplt -= 8;
3306*cf2f2c56Smiod }
3307*cf2f2c56Smiod else
3308*cf2f2c56Smiod {
3309*cf2f2c56Smiod BFD_ASSERT (dinfo->gothilo.fdplt)
3310*cf2f2c56Smiod entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
3311*cf2f2c56Smiod dinfo->gothilo.fdplt -= 8;
3312*cf2f2c56Smiod }
3313*cf2f2c56Smiod }
3314*cf2f2c56Smiod
3315*cf2f2c56Smiod if (entry->plt)
3316*cf2f2c56Smiod {
3317*cf2f2c56Smiod int size;
3318*cf2f2c56Smiod
3319*cf2f2c56Smiod /* We use the section's raw size to mark the location of the
3320*cf2f2c56Smiod next PLT entry. */
3321*cf2f2c56Smiod entry->plt_entry = frvfdpic_plt_section (dinfo->g.info)->_raw_size;
3322*cf2f2c56Smiod
3323*cf2f2c56Smiod /* Figure out the length of this PLT entry based on the
3324*cf2f2c56Smiod addressing mode we need to reach the function descriptor. */
3325*cf2f2c56Smiod BFD_ASSERT (entry->fd_entry);
3326*cf2f2c56Smiod if (entry->fd_entry >= -(1 << (12 - 1))
3327*cf2f2c56Smiod && entry->fd_entry < (1 << (12 - 1)))
3328*cf2f2c56Smiod size = 8;
3329*cf2f2c56Smiod else if (entry->fd_entry >= -(1 << (16 - 1))
3330*cf2f2c56Smiod && entry->fd_entry < (1 << (16 - 1)))
3331*cf2f2c56Smiod size = 12;
3332*cf2f2c56Smiod else
3333*cf2f2c56Smiod size = 16;
3334*cf2f2c56Smiod
3335*cf2f2c56Smiod frvfdpic_plt_section (dinfo->g.info)->_raw_size += size;
3336*cf2f2c56Smiod }
3337*cf2f2c56Smiod
3338*cf2f2c56Smiod if (entry->lazyplt)
3339*cf2f2c56Smiod {
3340*cf2f2c56Smiod entry->lzplt_entry = dinfo->g.lzplt;
3341*cf2f2c56Smiod dinfo->g.lzplt += 8;
3342*cf2f2c56Smiod /* If this entry is the one that gets the resolver stub, account
3343*cf2f2c56Smiod for the additional instruction. */
3344*cf2f2c56Smiod if (entry->lzplt_entry % FRVFDPIC_LZPLT_BLOCK_SIZE
3345*cf2f2c56Smiod == FRVFDPIC_LZPLT_RESOLV_LOC)
3346*cf2f2c56Smiod dinfo->g.lzplt += 4;
3347*cf2f2c56Smiod }
3348*cf2f2c56Smiod
3349*cf2f2c56Smiod return 1;
3350*cf2f2c56Smiod }
3351*cf2f2c56Smiod
3352*cf2f2c56Smiod /* Follow indirect and warning hash entries so that each got entry
3353*cf2f2c56Smiod points to the final symbol definition. P must point to a pointer
3354*cf2f2c56Smiod to the hash table we're traversing. Since this traversal may
3355*cf2f2c56Smiod modify the hash table, we set this pointer to NULL to indicate
3356*cf2f2c56Smiod we've made a potentially-destructive change to the hash table, so
3357*cf2f2c56Smiod the traversal must be restarted. */
3358*cf2f2c56Smiod static int
_frvfdpic_resolve_final_relocs_info(void ** entryp,void * p)3359*cf2f2c56Smiod _frvfdpic_resolve_final_relocs_info (void **entryp, void *p)
3360*cf2f2c56Smiod {
3361*cf2f2c56Smiod struct frvfdpic_relocs_info *entry = *entryp;
3362*cf2f2c56Smiod htab_t *htab = p;
3363*cf2f2c56Smiod
3364*cf2f2c56Smiod if (entry->symndx == -1)
3365*cf2f2c56Smiod {
3366*cf2f2c56Smiod struct elf_link_hash_entry *h = entry->d.h;
3367*cf2f2c56Smiod struct frvfdpic_relocs_info *oentry;
3368*cf2f2c56Smiod
3369*cf2f2c56Smiod while (h->root.type == bfd_link_hash_indirect
3370*cf2f2c56Smiod || h->root.type == bfd_link_hash_warning)
3371*cf2f2c56Smiod h = (struct elf_link_hash_entry *)h->root.u.i.link;
3372*cf2f2c56Smiod
3373*cf2f2c56Smiod if (entry->d.h == h)
3374*cf2f2c56Smiod return 1;
3375*cf2f2c56Smiod
3376*cf2f2c56Smiod oentry = frvfdpic_relocs_info_for_global (*htab, 0, h, entry->addend,
3377*cf2f2c56Smiod NO_INSERT);
3378*cf2f2c56Smiod
3379*cf2f2c56Smiod if (oentry)
3380*cf2f2c56Smiod {
3381*cf2f2c56Smiod /* Merge the two entries. */
3382*cf2f2c56Smiod frvfdpic_pic_merge_early_relocs_info (oentry, entry);
3383*cf2f2c56Smiod htab_clear_slot (*htab, entryp);
3384*cf2f2c56Smiod return 1;
3385*cf2f2c56Smiod }
3386*cf2f2c56Smiod
3387*cf2f2c56Smiod entry->d.h = h;
3388*cf2f2c56Smiod
3389*cf2f2c56Smiod /* If we can't find this entry with the new bfd hash, re-insert
3390*cf2f2c56Smiod it, and get the traversal restarted. */
3391*cf2f2c56Smiod if (! htab_find (*htab, entry))
3392*cf2f2c56Smiod {
3393*cf2f2c56Smiod htab_clear_slot (*htab, entryp);
3394*cf2f2c56Smiod entryp = htab_find_slot (*htab, entry, INSERT);
3395*cf2f2c56Smiod if (! *entryp)
3396*cf2f2c56Smiod *entryp = entry;
3397*cf2f2c56Smiod /* Abort the traversal, since the whole table may have
3398*cf2f2c56Smiod moved, and leave it up to the parent to restart the
3399*cf2f2c56Smiod process. */
3400*cf2f2c56Smiod *(htab_t *)p = NULL;
3401*cf2f2c56Smiod return 0;
3402*cf2f2c56Smiod }
3403*cf2f2c56Smiod }
3404*cf2f2c56Smiod
3405*cf2f2c56Smiod return 1;
3406*cf2f2c56Smiod }
3407*cf2f2c56Smiod
3408*cf2f2c56Smiod /* Set the sizes of the dynamic sections. */
3409*cf2f2c56Smiod
3410*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_size_dynamic_sections(bfd * output_bfd,struct bfd_link_info * info)3411*cf2f2c56Smiod elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
3412*cf2f2c56Smiod struct bfd_link_info *info)
3413*cf2f2c56Smiod {
3414*cf2f2c56Smiod bfd *dynobj;
3415*cf2f2c56Smiod asection *s;
3416*cf2f2c56Smiod struct _frvfdpic_dynamic_got_plt_info gpinfo;
3417*cf2f2c56Smiod bfd_signed_vma odd;
3418*cf2f2c56Smiod bfd_vma limit;
3419*cf2f2c56Smiod
3420*cf2f2c56Smiod dynobj = elf_hash_table (info)->dynobj;
3421*cf2f2c56Smiod BFD_ASSERT (dynobj != NULL);
3422*cf2f2c56Smiod
3423*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3424*cf2f2c56Smiod {
3425*cf2f2c56Smiod /* Set the contents of the .interp section to the interpreter. */
3426*cf2f2c56Smiod if (info->executable)
3427*cf2f2c56Smiod {
3428*cf2f2c56Smiod s = bfd_get_section_by_name (dynobj, ".interp");
3429*cf2f2c56Smiod BFD_ASSERT (s != NULL);
3430*cf2f2c56Smiod s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
3431*cf2f2c56Smiod s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
3432*cf2f2c56Smiod }
3433*cf2f2c56Smiod }
3434*cf2f2c56Smiod
3435*cf2f2c56Smiod memset (&gpinfo, 0, sizeof (gpinfo));
3436*cf2f2c56Smiod gpinfo.g.info = info;
3437*cf2f2c56Smiod
3438*cf2f2c56Smiod for (;;)
3439*cf2f2c56Smiod {
3440*cf2f2c56Smiod htab_t relocs = frvfdpic_relocs_info (info);
3441*cf2f2c56Smiod
3442*cf2f2c56Smiod htab_traverse (relocs, _frvfdpic_resolve_final_relocs_info, &relocs);
3443*cf2f2c56Smiod
3444*cf2f2c56Smiod if (relocs == frvfdpic_relocs_info (info))
3445*cf2f2c56Smiod break;
3446*cf2f2c56Smiod }
3447*cf2f2c56Smiod
3448*cf2f2c56Smiod htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_count_got_plt_entries,
3449*cf2f2c56Smiod &gpinfo.g);
3450*cf2f2c56Smiod
3451*cf2f2c56Smiod odd = 12;
3452*cf2f2c56Smiod /* Compute the total size taken by entries in the 12-bit and 16-bit
3453*cf2f2c56Smiod ranges, to tell how many PLT function descriptors we can bring
3454*cf2f2c56Smiod into the 12-bit range without causing the 16-bit range to
3455*cf2f2c56Smiod overflow. */
3456*cf2f2c56Smiod limit = odd + gpinfo.g.got12 + gpinfo.g.gotlos
3457*cf2f2c56Smiod + gpinfo.g.fd12 + gpinfo.g.fdlos;
3458*cf2f2c56Smiod if (limit < (bfd_vma)1 << 16)
3459*cf2f2c56Smiod limit = ((bfd_vma)1 << 16) - limit;
3460*cf2f2c56Smiod else
3461*cf2f2c56Smiod limit = 0;
3462*cf2f2c56Smiod if (gpinfo.g.fdplt < limit)
3463*cf2f2c56Smiod limit = gpinfo.g.fdplt;
3464*cf2f2c56Smiod
3465*cf2f2c56Smiod /* Determine the ranges of GOT offsets that we can use for each
3466*cf2f2c56Smiod range of addressing modes. */
3467*cf2f2c56Smiod odd = _frvfdpic_compute_got_alloc_data (&gpinfo.got12,
3468*cf2f2c56Smiod 0,
3469*cf2f2c56Smiod odd,
3470*cf2f2c56Smiod 16,
3471*cf2f2c56Smiod gpinfo.g.got12,
3472*cf2f2c56Smiod gpinfo.g.fd12,
3473*cf2f2c56Smiod limit,
3474*cf2f2c56Smiod (bfd_vma)1 << (12-1));
3475*cf2f2c56Smiod odd = _frvfdpic_compute_got_alloc_data (&gpinfo.gotlos,
3476*cf2f2c56Smiod gpinfo.got12.min,
3477*cf2f2c56Smiod odd,
3478*cf2f2c56Smiod gpinfo.got12.max,
3479*cf2f2c56Smiod gpinfo.g.gotlos,
3480*cf2f2c56Smiod gpinfo.g.fdlos,
3481*cf2f2c56Smiod gpinfo.g.fdplt - gpinfo.got12.fdplt,
3482*cf2f2c56Smiod (bfd_vma)1 << (16-1));
3483*cf2f2c56Smiod odd = _frvfdpic_compute_got_alloc_data (&gpinfo.gothilo,
3484*cf2f2c56Smiod gpinfo.gotlos.min,
3485*cf2f2c56Smiod odd,
3486*cf2f2c56Smiod gpinfo.gotlos.max,
3487*cf2f2c56Smiod gpinfo.g.gothilo,
3488*cf2f2c56Smiod gpinfo.g.fdhilo,
3489*cf2f2c56Smiod gpinfo.g.fdplt - gpinfo.got12.fdplt
3490*cf2f2c56Smiod - gpinfo.gotlos.fdplt,
3491*cf2f2c56Smiod (bfd_vma)1 << (32-1));
3492*cf2f2c56Smiod
3493*cf2f2c56Smiod /* Now assign (most) GOT offsets. */
3494*cf2f2c56Smiod htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_assign_got_entries,
3495*cf2f2c56Smiod &gpinfo);
3496*cf2f2c56Smiod
3497*cf2f2c56Smiod frvfdpic_got_section (info)->_raw_size = gpinfo.gothilo.max
3498*cf2f2c56Smiod - gpinfo.gothilo.min
3499*cf2f2c56Smiod /* If an odd word is the last word of the GOT, we don't need this
3500*cf2f2c56Smiod word to be part of the GOT. */
3501*cf2f2c56Smiod - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
3502*cf2f2c56Smiod if (frvfdpic_got_section (info)->_raw_size == 0)
3503*cf2f2c56Smiod frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
3504*cf2f2c56Smiod else if (frvfdpic_got_section (info)->_raw_size == 12
3505*cf2f2c56Smiod && ! elf_hash_table (info)->dynamic_sections_created)
3506*cf2f2c56Smiod {
3507*cf2f2c56Smiod frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
3508*cf2f2c56Smiod frvfdpic_got_section (info)->_raw_size = 0;
3509*cf2f2c56Smiod }
3510*cf2f2c56Smiod else
3511*cf2f2c56Smiod {
3512*cf2f2c56Smiod frvfdpic_got_section (info)->contents =
3513*cf2f2c56Smiod (bfd_byte *) bfd_zalloc (dynobj,
3514*cf2f2c56Smiod frvfdpic_got_section (info)->_raw_size);
3515*cf2f2c56Smiod if (frvfdpic_got_section (info)->contents == NULL)
3516*cf2f2c56Smiod return FALSE;
3517*cf2f2c56Smiod }
3518*cf2f2c56Smiod
3519*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3520*cf2f2c56Smiod /* Subtract the number of lzplt entries, since those will generate
3521*cf2f2c56Smiod relocations in the pltrel section. */
3522*cf2f2c56Smiod frvfdpic_gotrel_section (info)->_raw_size =
3523*cf2f2c56Smiod (gpinfo.g.relocs - gpinfo.g.lzplt / 8)
3524*cf2f2c56Smiod * get_elf_backend_data (output_bfd)->s->sizeof_rel;
3525*cf2f2c56Smiod else
3526*cf2f2c56Smiod BFD_ASSERT (gpinfo.g.relocs == 0);
3527*cf2f2c56Smiod if (frvfdpic_gotrel_section (info)->_raw_size == 0)
3528*cf2f2c56Smiod frvfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
3529*cf2f2c56Smiod else
3530*cf2f2c56Smiod {
3531*cf2f2c56Smiod frvfdpic_gotrel_section (info)->contents =
3532*cf2f2c56Smiod (bfd_byte *) bfd_zalloc (dynobj,
3533*cf2f2c56Smiod frvfdpic_gotrel_section (info)->_raw_size);
3534*cf2f2c56Smiod if (frvfdpic_gotrel_section (info)->contents == NULL)
3535*cf2f2c56Smiod return FALSE;
3536*cf2f2c56Smiod }
3537*cf2f2c56Smiod
3538*cf2f2c56Smiod frvfdpic_gotfixup_section (info)->_raw_size = (gpinfo.g.fixups + 1) * 4;
3539*cf2f2c56Smiod if (frvfdpic_gotfixup_section (info)->_raw_size == 0)
3540*cf2f2c56Smiod frvfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
3541*cf2f2c56Smiod else
3542*cf2f2c56Smiod {
3543*cf2f2c56Smiod frvfdpic_gotfixup_section (info)->contents =
3544*cf2f2c56Smiod (bfd_byte *) bfd_zalloc (dynobj,
3545*cf2f2c56Smiod frvfdpic_gotfixup_section (info)->_raw_size);
3546*cf2f2c56Smiod if (frvfdpic_gotfixup_section (info)->contents == NULL)
3547*cf2f2c56Smiod return FALSE;
3548*cf2f2c56Smiod }
3549*cf2f2c56Smiod
3550*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3551*cf2f2c56Smiod {
3552*cf2f2c56Smiod frvfdpic_pltrel_section (info)->_raw_size =
3553*cf2f2c56Smiod gpinfo.g.lzplt / 8 * get_elf_backend_data (output_bfd)->s->sizeof_rel;
3554*cf2f2c56Smiod if (frvfdpic_pltrel_section (info)->_raw_size == 0)
3555*cf2f2c56Smiod frvfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
3556*cf2f2c56Smiod else
3557*cf2f2c56Smiod {
3558*cf2f2c56Smiod frvfdpic_pltrel_section (info)->contents =
3559*cf2f2c56Smiod (bfd_byte *) bfd_zalloc (dynobj,
3560*cf2f2c56Smiod frvfdpic_pltrel_section (info)
3561*cf2f2c56Smiod ->_raw_size);
3562*cf2f2c56Smiod if (frvfdpic_pltrel_section (info)->contents == NULL)
3563*cf2f2c56Smiod return FALSE;
3564*cf2f2c56Smiod }
3565*cf2f2c56Smiod }
3566*cf2f2c56Smiod
3567*cf2f2c56Smiod /* Add 4 bytes for every block of at most 65535 lazy PLT entries,
3568*cf2f2c56Smiod such that there's room for the additional instruction needed to
3569*cf2f2c56Smiod call the resolver. Since _frvfdpic_assign_got_entries didn't
3570*cf2f2c56Smiod account for them, our block size is 4 bytes smaller than the real
3571*cf2f2c56Smiod block size. */
3572*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3573*cf2f2c56Smiod {
3574*cf2f2c56Smiod frvfdpic_plt_section (info)->_raw_size = gpinfo.g.lzplt
3575*cf2f2c56Smiod + ((gpinfo.g.lzplt + (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) - 8)
3576*cf2f2c56Smiod / (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) * 4);
3577*cf2f2c56Smiod }
3578*cf2f2c56Smiod
3579*cf2f2c56Smiod /* Reset it, such that _frvfdpic_assign_plt_entries() can use it to
3580*cf2f2c56Smiod actually assign lazy PLT entries addresses. */
3581*cf2f2c56Smiod gpinfo.g.lzplt = 0;
3582*cf2f2c56Smiod
3583*cf2f2c56Smiod /* Save information that we're going to need to generate GOT and PLT
3584*cf2f2c56Smiod entries. */
3585*cf2f2c56Smiod frvfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
3586*cf2f2c56Smiod
3587*cf2f2c56Smiod if (get_elf_backend_data (output_bfd)->want_got_sym)
3588*cf2f2c56Smiod elf_hash_table (info)->hgot->root.u.def.value
3589*cf2f2c56Smiod += frvfdpic_got_initial_offset (info);
3590*cf2f2c56Smiod
3591*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3592*cf2f2c56Smiod frvfdpic_plt_initial_offset (info) =
3593*cf2f2c56Smiod frvfdpic_plt_section (info)->_raw_size;
3594*cf2f2c56Smiod
3595*cf2f2c56Smiod htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_assign_plt_entries,
3596*cf2f2c56Smiod &gpinfo);
3597*cf2f2c56Smiod
3598*cf2f2c56Smiod /* Allocate the PLT section contents only after
3599*cf2f2c56Smiod _frvfdpic_assign_plt_entries has a chance to add the size of the
3600*cf2f2c56Smiod non-lazy PLT entries. */
3601*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3602*cf2f2c56Smiod {
3603*cf2f2c56Smiod if (frvfdpic_plt_section (info)->_raw_size == 0)
3604*cf2f2c56Smiod frvfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
3605*cf2f2c56Smiod else
3606*cf2f2c56Smiod {
3607*cf2f2c56Smiod frvfdpic_plt_section (info)->contents =
3608*cf2f2c56Smiod (bfd_byte *) bfd_zalloc (dynobj,
3609*cf2f2c56Smiod frvfdpic_plt_section (info)->_raw_size);
3610*cf2f2c56Smiod if (frvfdpic_plt_section (info)->contents == NULL)
3611*cf2f2c56Smiod return FALSE;
3612*cf2f2c56Smiod }
3613*cf2f2c56Smiod }
3614*cf2f2c56Smiod
3615*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3616*cf2f2c56Smiod {
3617*cf2f2c56Smiod if (frvfdpic_got_section (info)->_raw_size)
3618*cf2f2c56Smiod if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0))
3619*cf2f2c56Smiod return FALSE;
3620*cf2f2c56Smiod
3621*cf2f2c56Smiod if (frvfdpic_pltrel_section (info)->_raw_size)
3622*cf2f2c56Smiod if (!_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
3623*cf2f2c56Smiod || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_REL)
3624*cf2f2c56Smiod || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
3625*cf2f2c56Smiod return FALSE;
3626*cf2f2c56Smiod
3627*cf2f2c56Smiod if (frvfdpic_gotrel_section (info)->_raw_size)
3628*cf2f2c56Smiod if (!_bfd_elf_add_dynamic_entry (info, DT_REL, 0)
3629*cf2f2c56Smiod || !_bfd_elf_add_dynamic_entry (info, DT_RELSZ, 0)
3630*cf2f2c56Smiod || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
3631*cf2f2c56Smiod sizeof (Elf32_External_Rel)))
3632*cf2f2c56Smiod return FALSE;
3633*cf2f2c56Smiod }
3634*cf2f2c56Smiod
3635*cf2f2c56Smiod return TRUE;
3636*cf2f2c56Smiod }
3637*cf2f2c56Smiod
3638*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_always_size_sections(bfd * output_bfd,struct bfd_link_info * info)3639*cf2f2c56Smiod elf32_frvfdpic_always_size_sections (bfd *output_bfd,
3640*cf2f2c56Smiod struct bfd_link_info *info)
3641*cf2f2c56Smiod {
3642*cf2f2c56Smiod if (!info->relocatable)
3643*cf2f2c56Smiod {
3644*cf2f2c56Smiod struct elf_link_hash_entry *h;
3645*cf2f2c56Smiod asection *sec;
3646*cf2f2c56Smiod
3647*cf2f2c56Smiod /* Force a PT_GNU_STACK segment to be created. */
3648*cf2f2c56Smiod if (! elf_tdata (output_bfd)->stack_flags)
3649*cf2f2c56Smiod elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
3650*cf2f2c56Smiod
3651*cf2f2c56Smiod /* Define __stacksize if it's not defined yet. */
3652*cf2f2c56Smiod h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
3653*cf2f2c56Smiod FALSE, FALSE, FALSE);
3654*cf2f2c56Smiod if (! h || h->root.type != bfd_link_hash_defined
3655*cf2f2c56Smiod || h->type != STT_OBJECT
3656*cf2f2c56Smiod || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
3657*cf2f2c56Smiod {
3658*cf2f2c56Smiod struct bfd_link_hash_entry *bh = NULL;
3659*cf2f2c56Smiod
3660*cf2f2c56Smiod if (!(_bfd_generic_link_add_one_symbol
3661*cf2f2c56Smiod (info, output_bfd, "__stacksize",
3662*cf2f2c56Smiod BSF_GLOBAL, bfd_abs_section_ptr, DEFAULT_STACK_SIZE,
3663*cf2f2c56Smiod (const char *) NULL, FALSE,
3664*cf2f2c56Smiod get_elf_backend_data (output_bfd)->collect, &bh)))
3665*cf2f2c56Smiod return FALSE;
3666*cf2f2c56Smiod
3667*cf2f2c56Smiod h = (struct elf_link_hash_entry *) bh;
3668*cf2f2c56Smiod h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
3669*cf2f2c56Smiod h->type = STT_OBJECT;
3670*cf2f2c56Smiod }
3671*cf2f2c56Smiod
3672*cf2f2c56Smiod /* Create a stack section, and set its alignment. */
3673*cf2f2c56Smiod sec = bfd_make_section (output_bfd, ".stack");
3674*cf2f2c56Smiod
3675*cf2f2c56Smiod if (sec == NULL
3676*cf2f2c56Smiod || ! bfd_set_section_alignment (output_bfd, sec, 3))
3677*cf2f2c56Smiod return FALSE;
3678*cf2f2c56Smiod }
3679*cf2f2c56Smiod
3680*cf2f2c56Smiod return TRUE;
3681*cf2f2c56Smiod }
3682*cf2f2c56Smiod
3683*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_modify_segment_map(bfd * output_bfd,struct bfd_link_info * info)3684*cf2f2c56Smiod elf32_frvfdpic_modify_segment_map (bfd *output_bfd,
3685*cf2f2c56Smiod struct bfd_link_info *info)
3686*cf2f2c56Smiod {
3687*cf2f2c56Smiod struct elf_segment_map *m;
3688*cf2f2c56Smiod
3689*cf2f2c56Smiod /* objcopy and strip preserve what's already there using
3690*cf2f2c56Smiod elf32_frvfdpic_copy_private_bfd_data (). */
3691*cf2f2c56Smiod if (! info)
3692*cf2f2c56Smiod return TRUE;
3693*cf2f2c56Smiod
3694*cf2f2c56Smiod for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
3695*cf2f2c56Smiod if (m->p_type == PT_GNU_STACK)
3696*cf2f2c56Smiod break;
3697*cf2f2c56Smiod
3698*cf2f2c56Smiod if (m)
3699*cf2f2c56Smiod {
3700*cf2f2c56Smiod asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
3701*cf2f2c56Smiod struct elf_link_hash_entry *h;
3702*cf2f2c56Smiod
3703*cf2f2c56Smiod if (sec)
3704*cf2f2c56Smiod {
3705*cf2f2c56Smiod /* Obtain the pointer to the __stacksize symbol. */
3706*cf2f2c56Smiod h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
3707*cf2f2c56Smiod FALSE, FALSE, FALSE);
3708*cf2f2c56Smiod while (h->root.type == bfd_link_hash_indirect
3709*cf2f2c56Smiod || h->root.type == bfd_link_hash_warning)
3710*cf2f2c56Smiod h = (struct elf_link_hash_entry *)h->root.u.i.link;
3711*cf2f2c56Smiod BFD_ASSERT (h->root.type == bfd_link_hash_defined);
3712*cf2f2c56Smiod
3713*cf2f2c56Smiod /* Set the section size from the symbol value. We
3714*cf2f2c56Smiod intentionally ignore the symbol section. */
3715*cf2f2c56Smiod if (h->root.type == bfd_link_hash_defined)
3716*cf2f2c56Smiod sec->_raw_size = h->root.u.def.value;
3717*cf2f2c56Smiod else
3718*cf2f2c56Smiod sec->_raw_size = DEFAULT_STACK_SIZE;
3719*cf2f2c56Smiod
3720*cf2f2c56Smiod /* Add the stack section to the PT_GNU_STACK segment,
3721*cf2f2c56Smiod such that its size and alignment requirements make it
3722*cf2f2c56Smiod to the segment. */
3723*cf2f2c56Smiod m->sections[m->count] = sec;
3724*cf2f2c56Smiod m->count++;
3725*cf2f2c56Smiod }
3726*cf2f2c56Smiod }
3727*cf2f2c56Smiod
3728*cf2f2c56Smiod return TRUE;
3729*cf2f2c56Smiod }
3730*cf2f2c56Smiod
3731*cf2f2c56Smiod /* Fill in code and data in dynamic sections. */
3732*cf2f2c56Smiod
3733*cf2f2c56Smiod static bfd_boolean
elf32_frv_finish_dynamic_sections(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)3734*cf2f2c56Smiod elf32_frv_finish_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
3735*cf2f2c56Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED)
3736*cf2f2c56Smiod {
3737*cf2f2c56Smiod /* Nothing to be done for non-FDPIC. */
3738*cf2f2c56Smiod return TRUE;
3739*cf2f2c56Smiod }
3740*cf2f2c56Smiod
3741*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_finish_dynamic_sections(bfd * output_bfd,struct bfd_link_info * info)3742*cf2f2c56Smiod elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd,
3743*cf2f2c56Smiod struct bfd_link_info *info)
3744*cf2f2c56Smiod {
3745*cf2f2c56Smiod bfd *dynobj;
3746*cf2f2c56Smiod asection *sdyn;
3747*cf2f2c56Smiod
3748*cf2f2c56Smiod dynobj = elf_hash_table (info)->dynobj;
3749*cf2f2c56Smiod
3750*cf2f2c56Smiod if (frvfdpic_got_section (info))
3751*cf2f2c56Smiod {
3752*cf2f2c56Smiod BFD_ASSERT (frvfdpic_gotrel_section (info)->_raw_size
3753*cf2f2c56Smiod == (frvfdpic_gotrel_section (info)->reloc_count
3754*cf2f2c56Smiod * sizeof (Elf32_External_Rel)));
3755*cf2f2c56Smiod
3756*cf2f2c56Smiod if (frvfdpic_gotfixup_section (info))
3757*cf2f2c56Smiod {
3758*cf2f2c56Smiod struct elf_link_hash_entry *hgot = elf_hash_table (info)->hgot;
3759*cf2f2c56Smiod bfd_vma got_value = hgot->root.u.def.value
3760*cf2f2c56Smiod + hgot->root.u.def.section->output_section->vma
3761*cf2f2c56Smiod + hgot->root.u.def.section->output_offset;
3762*cf2f2c56Smiod
3763*cf2f2c56Smiod _frvfdpic_add_rofixup (output_bfd, frvfdpic_gotfixup_section (info),
3764*cf2f2c56Smiod got_value, 0);
3765*cf2f2c56Smiod
3766*cf2f2c56Smiod if (frvfdpic_gotfixup_section (info)->_raw_size
3767*cf2f2c56Smiod != (frvfdpic_gotfixup_section (info)->reloc_count * 4))
3768*cf2f2c56Smiod {
3769*cf2f2c56Smiod (*_bfd_error_handler)
3770*cf2f2c56Smiod ("LINKER BUG: .rofixup section size mismatch");
3771*cf2f2c56Smiod return FALSE;
3772*cf2f2c56Smiod }
3773*cf2f2c56Smiod }
3774*cf2f2c56Smiod }
3775*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3776*cf2f2c56Smiod {
3777*cf2f2c56Smiod BFD_ASSERT (frvfdpic_pltrel_section (info)->_raw_size
3778*cf2f2c56Smiod == (frvfdpic_pltrel_section (info)->reloc_count
3779*cf2f2c56Smiod * sizeof (Elf32_External_Rel)));
3780*cf2f2c56Smiod }
3781*cf2f2c56Smiod
3782*cf2f2c56Smiod sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
3783*cf2f2c56Smiod
3784*cf2f2c56Smiod if (elf_hash_table (info)->dynamic_sections_created)
3785*cf2f2c56Smiod {
3786*cf2f2c56Smiod Elf32_External_Dyn * dyncon;
3787*cf2f2c56Smiod Elf32_External_Dyn * dynconend;
3788*cf2f2c56Smiod
3789*cf2f2c56Smiod BFD_ASSERT (sdyn != NULL);
3790*cf2f2c56Smiod
3791*cf2f2c56Smiod dyncon = (Elf32_External_Dyn *) sdyn->contents;
3792*cf2f2c56Smiod dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
3793*cf2f2c56Smiod
3794*cf2f2c56Smiod for (; dyncon < dynconend; dyncon++)
3795*cf2f2c56Smiod {
3796*cf2f2c56Smiod Elf_Internal_Dyn dyn;
3797*cf2f2c56Smiod
3798*cf2f2c56Smiod bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
3799*cf2f2c56Smiod
3800*cf2f2c56Smiod switch (dyn.d_tag)
3801*cf2f2c56Smiod {
3802*cf2f2c56Smiod default:
3803*cf2f2c56Smiod break;
3804*cf2f2c56Smiod
3805*cf2f2c56Smiod case DT_PLTGOT:
3806*cf2f2c56Smiod dyn.d_un.d_ptr = frvfdpic_got_section (info)->output_section->vma
3807*cf2f2c56Smiod + frvfdpic_got_section (info)->output_offset
3808*cf2f2c56Smiod + frvfdpic_got_initial_offset (info);
3809*cf2f2c56Smiod bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
3810*cf2f2c56Smiod break;
3811*cf2f2c56Smiod
3812*cf2f2c56Smiod case DT_JMPREL:
3813*cf2f2c56Smiod dyn.d_un.d_ptr = frvfdpic_pltrel_section (info)
3814*cf2f2c56Smiod ->output_section->vma
3815*cf2f2c56Smiod + frvfdpic_pltrel_section (info)->output_offset;
3816*cf2f2c56Smiod bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
3817*cf2f2c56Smiod break;
3818*cf2f2c56Smiod
3819*cf2f2c56Smiod case DT_PLTRELSZ:
3820*cf2f2c56Smiod if (frvfdpic_pltrel_section (info)->_cooked_size != 0)
3821*cf2f2c56Smiod dyn.d_un.d_val = frvfdpic_pltrel_section (info)->_cooked_size;
3822*cf2f2c56Smiod else
3823*cf2f2c56Smiod dyn.d_un.d_val = frvfdpic_pltrel_section (info)->_raw_size;
3824*cf2f2c56Smiod bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
3825*cf2f2c56Smiod break;
3826*cf2f2c56Smiod }
3827*cf2f2c56Smiod }
3828*cf2f2c56Smiod }
3829*cf2f2c56Smiod
3830*cf2f2c56Smiod return TRUE;
3831*cf2f2c56Smiod }
3832*cf2f2c56Smiod
3833*cf2f2c56Smiod /* Adjust a symbol defined by a dynamic object and referenced by a
3834*cf2f2c56Smiod regular object. */
3835*cf2f2c56Smiod
3836*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_adjust_dynamic_symbol(struct bfd_link_info * info ATTRIBUTE_UNUSED,struct elf_link_hash_entry * h ATTRIBUTE_UNUSED)3837*cf2f2c56Smiod elf32_frvfdpic_adjust_dynamic_symbol
3838*cf2f2c56Smiod (struct bfd_link_info *info ATTRIBUTE_UNUSED,
3839*cf2f2c56Smiod struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
3840*cf2f2c56Smiod {
3841*cf2f2c56Smiod bfd * dynobj;
3842*cf2f2c56Smiod
3843*cf2f2c56Smiod dynobj = elf_hash_table (info)->dynobj;
3844*cf2f2c56Smiod
3845*cf2f2c56Smiod /* Make sure we know what is going on here. */
3846*cf2f2c56Smiod BFD_ASSERT (dynobj != NULL
3847*cf2f2c56Smiod && (h->weakdef != NULL
3848*cf2f2c56Smiod || ((h->elf_link_hash_flags
3849*cf2f2c56Smiod & ELF_LINK_HASH_DEF_DYNAMIC) != 0
3850*cf2f2c56Smiod && (h->elf_link_hash_flags
3851*cf2f2c56Smiod & ELF_LINK_HASH_REF_REGULAR) != 0
3852*cf2f2c56Smiod && (h->elf_link_hash_flags
3853*cf2f2c56Smiod & ELF_LINK_HASH_DEF_REGULAR) == 0)));
3854*cf2f2c56Smiod
3855*cf2f2c56Smiod /* If this is a weak symbol, and there is a real definition, the
3856*cf2f2c56Smiod processor independent code will have arranged for us to see the
3857*cf2f2c56Smiod real definition first, and we can just use the same value. */
3858*cf2f2c56Smiod if (h->weakdef != NULL)
3859*cf2f2c56Smiod {
3860*cf2f2c56Smiod BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
3861*cf2f2c56Smiod || h->weakdef->root.type == bfd_link_hash_defweak);
3862*cf2f2c56Smiod h->root.u.def.section = h->weakdef->root.u.def.section;
3863*cf2f2c56Smiod h->root.u.def.value = h->weakdef->root.u.def.value;
3864*cf2f2c56Smiod }
3865*cf2f2c56Smiod
3866*cf2f2c56Smiod return TRUE;
3867*cf2f2c56Smiod }
3868*cf2f2c56Smiod
3869*cf2f2c56Smiod /* Perform any actions needed for dynamic symbols. */
3870*cf2f2c56Smiod
3871*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_finish_dynamic_symbol(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,struct elf_link_hash_entry * h ATTRIBUTE_UNUSED,Elf_Internal_Sym * sym ATTRIBUTE_UNUSED)3872*cf2f2c56Smiod elf32_frvfdpic_finish_dynamic_symbol
3873*cf2f2c56Smiod (bfd *output_bfd ATTRIBUTE_UNUSED,
3874*cf2f2c56Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED,
3875*cf2f2c56Smiod struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
3876*cf2f2c56Smiod Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
3877*cf2f2c56Smiod {
3878*cf2f2c56Smiod return TRUE;
3879*cf2f2c56Smiod }
3880*cf2f2c56Smiod
3881*cf2f2c56Smiod /* Decide whether to attempt to turn absptr or lsda encodings in
3882*cf2f2c56Smiod shared libraries into pcrel within the given input section. */
3883*cf2f2c56Smiod
3884*cf2f2c56Smiod static bfd_boolean
frvfdpic_elf_use_relative_eh_frame(bfd * input_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * eh_frame_section ATTRIBUTE_UNUSED)3885*cf2f2c56Smiod frvfdpic_elf_use_relative_eh_frame
3886*cf2f2c56Smiod (bfd *input_bfd ATTRIBUTE_UNUSED,
3887*cf2f2c56Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED,
3888*cf2f2c56Smiod asection *eh_frame_section ATTRIBUTE_UNUSED)
3889*cf2f2c56Smiod {
3890*cf2f2c56Smiod /* We can't use PC-relative encodings in FDPIC binaries, in general. */
3891*cf2f2c56Smiod return FALSE;
3892*cf2f2c56Smiod }
3893*cf2f2c56Smiod
3894*cf2f2c56Smiod /* Adjust the contents of an eh_frame_hdr section before they're output. */
3895*cf2f2c56Smiod
3896*cf2f2c56Smiod static bfd_byte
frvfdpic_elf_encode_eh_address(bfd * abfd,struct bfd_link_info * info,asection * osec,bfd_vma offset,asection * loc_sec,bfd_vma loc_offset,bfd_vma * encoded)3897*cf2f2c56Smiod frvfdpic_elf_encode_eh_address (bfd *abfd,
3898*cf2f2c56Smiod struct bfd_link_info *info,
3899*cf2f2c56Smiod asection *osec, bfd_vma offset,
3900*cf2f2c56Smiod asection *loc_sec, bfd_vma loc_offset,
3901*cf2f2c56Smiod bfd_vma *encoded)
3902*cf2f2c56Smiod {
3903*cf2f2c56Smiod struct elf_link_hash_entry *h;
3904*cf2f2c56Smiod
3905*cf2f2c56Smiod h = elf_hash_table (info)->hgot;
3906*cf2f2c56Smiod BFD_ASSERT (h && h->root.type == bfd_link_hash_defined);
3907*cf2f2c56Smiod
3908*cf2f2c56Smiod if (! h || (_frvfdpic_osec_to_segment (abfd, osec)
3909*cf2f2c56Smiod == _frvfdpic_osec_to_segment (abfd, loc_sec->output_section)))
3910*cf2f2c56Smiod return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
3911*cf2f2c56Smiod loc_sec, loc_offset, encoded);
3912*cf2f2c56Smiod
3913*cf2f2c56Smiod BFD_ASSERT (_frvfdpic_osec_to_segment (abfd, osec)
3914*cf2f2c56Smiod == (_frvfdpic_osec_to_segment
3915*cf2f2c56Smiod (abfd, h->root.u.def.section->output_section)));
3916*cf2f2c56Smiod
3917*cf2f2c56Smiod *encoded = osec->vma + offset
3918*cf2f2c56Smiod - (h->root.u.def.value
3919*cf2f2c56Smiod + h->root.u.def.section->output_section->vma
3920*cf2f2c56Smiod + h->root.u.def.section->output_offset);
3921*cf2f2c56Smiod
3922*cf2f2c56Smiod return DW_EH_PE_datarel | DW_EH_PE_sdata4;
3923*cf2f2c56Smiod }
3924*cf2f2c56Smiod
3925d2201f2fSdrahn /* Look through the relocs for a section during the first phase.
3926*cf2f2c56Smiod
3927*cf2f2c56Smiod Besides handling virtual table relocs for gc, we have to deal with
3928*cf2f2c56Smiod all sorts of PIC-related relocations. We describe below the
3929*cf2f2c56Smiod general plan on how to handle such relocations, even though we only
3930*cf2f2c56Smiod collect information at this point, storing them in hash tables for
3931*cf2f2c56Smiod perusal of later passes.
3932*cf2f2c56Smiod
3933*cf2f2c56Smiod 32 relocations are propagated to the linker output when creating
3934*cf2f2c56Smiod position-independent output. LO16 and HI16 relocations are not
3935*cf2f2c56Smiod supposed to be encountered in this case.
3936*cf2f2c56Smiod
3937*cf2f2c56Smiod LABEL16 should always be resolvable by the linker, since it's only
3938*cf2f2c56Smiod used by branches.
3939*cf2f2c56Smiod
3940*cf2f2c56Smiod LABEL24, on the other hand, is used by calls. If it turns out that
3941*cf2f2c56Smiod the target of a call is a dynamic symbol, a PLT entry must be
3942*cf2f2c56Smiod created for it, which triggers the creation of a private function
3943*cf2f2c56Smiod descriptor and, unless lazy binding is disabled, a lazy PLT entry.
3944*cf2f2c56Smiod
3945*cf2f2c56Smiod GPREL relocations require the referenced symbol to be in the same
3946*cf2f2c56Smiod segment as _gp, but this can only be checked later.
3947*cf2f2c56Smiod
3948*cf2f2c56Smiod All GOT, GOTOFF and FUNCDESC relocations require a .got section to
3949*cf2f2c56Smiod exist. LABEL24 might as well, since it may require a PLT entry,
3950*cf2f2c56Smiod that will require a got.
3951*cf2f2c56Smiod
3952*cf2f2c56Smiod Non-FUNCDESC GOT relocations require a GOT entry to be created
3953*cf2f2c56Smiod regardless of whether the symbol is dynamic. However, since a
3954*cf2f2c56Smiod global symbol that turns out to not be exported may have the same
3955*cf2f2c56Smiod address of a non-dynamic symbol, we don't assign GOT entries at
3956*cf2f2c56Smiod this point, such that we can share them in this case. A relocation
3957*cf2f2c56Smiod for the GOT entry always has to be created, be it to offset a
3958*cf2f2c56Smiod private symbol by the section load address, be it to get the symbol
3959*cf2f2c56Smiod resolved dynamically.
3960*cf2f2c56Smiod
3961*cf2f2c56Smiod FUNCDESC GOT relocations require a GOT entry to be created, and
3962*cf2f2c56Smiod handled as if a FUNCDESC relocation was applied to the GOT entry in
3963*cf2f2c56Smiod an object file.
3964*cf2f2c56Smiod
3965*cf2f2c56Smiod FUNCDESC relocations referencing a symbol that turns out to NOT be
3966*cf2f2c56Smiod dynamic cause a private function descriptor to be created. The
3967*cf2f2c56Smiod FUNCDESC relocation then decays to a 32 relocation that points at
3968*cf2f2c56Smiod the private descriptor. If the symbol is dynamic, the FUNCDESC
3969*cf2f2c56Smiod relocation is propagated to the linker output, such that the
3970*cf2f2c56Smiod dynamic linker creates the canonical descriptor, pointing to the
3971*cf2f2c56Smiod dynamically-resolved definition of the function.
3972*cf2f2c56Smiod
3973*cf2f2c56Smiod Non-FUNCDESC GOTOFF relocations must always refer to non-dynamic
3974*cf2f2c56Smiod symbols that are assigned to the same segment as the GOT, but we
3975*cf2f2c56Smiod can only check this later, after we know the complete set of
3976*cf2f2c56Smiod symbols defined and/or exported.
3977*cf2f2c56Smiod
3978*cf2f2c56Smiod FUNCDESC GOTOFF relocations require a function descriptor to be
3979*cf2f2c56Smiod created and, unless lazy binding is disabled or the symbol is not
3980*cf2f2c56Smiod dynamic, a lazy PLT entry. Since we can't tell at this point
3981*cf2f2c56Smiod whether a symbol is going to be dynamic, we have to decide later
3982*cf2f2c56Smiod whether to create a lazy PLT entry or bind the descriptor directly
3983*cf2f2c56Smiod to the private function.
3984*cf2f2c56Smiod
3985*cf2f2c56Smiod FUNCDESC_VALUE relocations are not supposed to be present in object
3986*cf2f2c56Smiod files, but they may very well be simply propagated to the linker
3987*cf2f2c56Smiod output, since they have no side effect.
3988*cf2f2c56Smiod
3989*cf2f2c56Smiod
3990*cf2f2c56Smiod A function descriptor always requires a FUNCDESC_VALUE relocation.
3991*cf2f2c56Smiod Whether it's in .plt.rel or not depends on whether lazy binding is
3992*cf2f2c56Smiod enabled and on whether the referenced symbol is dynamic.
3993*cf2f2c56Smiod
3994*cf2f2c56Smiod The existence of a lazy PLT requires the resolverStub lazy PLT
3995*cf2f2c56Smiod entry to be present.
3996*cf2f2c56Smiod
3997*cf2f2c56Smiod
3998*cf2f2c56Smiod As for assignment of GOT, PLT and lazy PLT entries, and private
3999*cf2f2c56Smiod descriptors, we might do them all sequentially, but we can do
4000*cf2f2c56Smiod better than that. For example, we can place GOT entries and
4001*cf2f2c56Smiod private function descriptors referenced using 12-bit operands
4002*cf2f2c56Smiod closer to the PIC register value, such that these relocations don't
4003*cf2f2c56Smiod overflow. Those that are only referenced with LO16 relocations
4004*cf2f2c56Smiod could come next, but we may as well place PLT-required function
4005*cf2f2c56Smiod descriptors in the 12-bit range to make them shorter. Symbols
4006*cf2f2c56Smiod referenced with LO16/HI16 may come next, but we may place
4007*cf2f2c56Smiod additional function descriptors in the 16-bit range if we can
4008*cf2f2c56Smiod reliably tell that we've already placed entries that are ever
4009*cf2f2c56Smiod referenced with only LO16. PLT entries are therefore generated as
4010*cf2f2c56Smiod small as possible, while not introducing relocation overflows in
4011*cf2f2c56Smiod GOT or FUNCDESC_GOTOFF relocations. Lazy PLT entries could be
4012*cf2f2c56Smiod generated before or after PLT entries, but not intermingled with
4013*cf2f2c56Smiod them, such that we can have more lazy PLT entries in range for a
4014*cf2f2c56Smiod branch to the resolverStub. The resolverStub should be emitted at
4015*cf2f2c56Smiod the most distant location from the first lazy PLT entry such that
4016*cf2f2c56Smiod it's still in range for a branch, or closer, if there isn't a need
4017*cf2f2c56Smiod for so many lazy PLT entries. Additional lazy PLT entries may be
4018*cf2f2c56Smiod emitted after the resolverStub, as long as branches are still in
4019*cf2f2c56Smiod range. If the branch goes out of range, longer lazy PLT entries
4020*cf2f2c56Smiod are emitted.
4021*cf2f2c56Smiod
4022*cf2f2c56Smiod We could further optimize PLT and lazy PLT entries by giving them
4023*cf2f2c56Smiod priority in assignment to closer-to-gr17 locations depending on the
4024*cf2f2c56Smiod number of occurrences of references to them (assuming a function
4025*cf2f2c56Smiod that's called more often is more important for performance, so its
4026*cf2f2c56Smiod PLT entry should be faster), or taking hints from the compiler.
4027*cf2f2c56Smiod Given infinite time and money... :-) */
4028d2201f2fSdrahn
4029d2201f2fSdrahn static bfd_boolean
elf32_frv_check_relocs(abfd,info,sec,relocs)4030d2201f2fSdrahn elf32_frv_check_relocs (abfd, info, sec, relocs)
4031d2201f2fSdrahn bfd *abfd;
4032d2201f2fSdrahn struct bfd_link_info *info;
4033d2201f2fSdrahn asection *sec;
4034d2201f2fSdrahn const Elf_Internal_Rela *relocs;
4035d2201f2fSdrahn {
4036d2201f2fSdrahn Elf_Internal_Shdr *symtab_hdr;
4037d2201f2fSdrahn struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
4038d2201f2fSdrahn const Elf_Internal_Rela *rel;
4039d2201f2fSdrahn const Elf_Internal_Rela *rel_end;
4040*cf2f2c56Smiod bfd *dynobj;
4041*cf2f2c56Smiod struct frvfdpic_relocs_info *picrel;
4042d2201f2fSdrahn
4043*cf2f2c56Smiod if (info->relocatable)
4044d2201f2fSdrahn return TRUE;
4045d2201f2fSdrahn
4046d2201f2fSdrahn symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
4047d2201f2fSdrahn sym_hashes = elf_sym_hashes (abfd);
4048d2201f2fSdrahn sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
4049d2201f2fSdrahn if (!elf_bad_symtab (abfd))
4050d2201f2fSdrahn sym_hashes_end -= symtab_hdr->sh_info;
4051d2201f2fSdrahn
4052*cf2f2c56Smiod dynobj = elf_hash_table (info)->dynobj;
4053d2201f2fSdrahn rel_end = relocs + sec->reloc_count;
4054d2201f2fSdrahn for (rel = relocs; rel < rel_end; rel++)
4055d2201f2fSdrahn {
4056d2201f2fSdrahn struct elf_link_hash_entry *h;
4057d2201f2fSdrahn unsigned long r_symndx;
4058d2201f2fSdrahn
4059d2201f2fSdrahn r_symndx = ELF32_R_SYM (rel->r_info);
4060d2201f2fSdrahn if (r_symndx < symtab_hdr->sh_info)
4061d2201f2fSdrahn h = NULL;
4062d2201f2fSdrahn else
4063d2201f2fSdrahn h = sym_hashes[r_symndx - symtab_hdr->sh_info];
4064d2201f2fSdrahn
4065d2201f2fSdrahn switch (ELF32_R_TYPE (rel->r_info))
4066d2201f2fSdrahn {
4067*cf2f2c56Smiod case R_FRV_GOT12:
4068*cf2f2c56Smiod case R_FRV_GOTHI:
4069*cf2f2c56Smiod case R_FRV_GOTLO:
4070*cf2f2c56Smiod case R_FRV_FUNCDESC_GOT12:
4071*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTHI:
4072*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTLO:
4073*cf2f2c56Smiod case R_FRV_GOTOFF12:
4074*cf2f2c56Smiod case R_FRV_GOTOFFHI:
4075*cf2f2c56Smiod case R_FRV_GOTOFFLO:
4076*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFF12:
4077*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFHI:
4078*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFLO:
4079*cf2f2c56Smiod case R_FRV_FUNCDESC:
4080*cf2f2c56Smiod case R_FRV_FUNCDESC_VALUE:
4081*cf2f2c56Smiod if (! IS_FDPIC (abfd))
4082*cf2f2c56Smiod goto bad_reloc;
4083*cf2f2c56Smiod /* Fall through. */
4084*cf2f2c56Smiod case R_FRV_GPREL12:
4085*cf2f2c56Smiod case R_FRV_GPRELU12:
4086*cf2f2c56Smiod case R_FRV_GPRELHI:
4087*cf2f2c56Smiod case R_FRV_GPRELLO:
4088*cf2f2c56Smiod case R_FRV_LABEL24:
4089*cf2f2c56Smiod case R_FRV_32:
4090*cf2f2c56Smiod if (! dynobj)
4091*cf2f2c56Smiod {
4092*cf2f2c56Smiod elf_hash_table (info)->dynobj = dynobj = abfd;
4093*cf2f2c56Smiod if (! _frv_create_got_section (abfd, info))
4094*cf2f2c56Smiod return FALSE;
4095*cf2f2c56Smiod }
4096*cf2f2c56Smiod if (! IS_FDPIC (abfd))
4097*cf2f2c56Smiod {
4098*cf2f2c56Smiod picrel = NULL;
4099*cf2f2c56Smiod break;
4100*cf2f2c56Smiod }
4101*cf2f2c56Smiod if (h != NULL)
4102*cf2f2c56Smiod {
4103*cf2f2c56Smiod if (h->dynindx == -1)
4104*cf2f2c56Smiod switch (ELF_ST_VISIBILITY (h->other))
4105*cf2f2c56Smiod {
4106*cf2f2c56Smiod case STV_INTERNAL:
4107*cf2f2c56Smiod case STV_HIDDEN:
4108*cf2f2c56Smiod break;
4109*cf2f2c56Smiod default:
4110*cf2f2c56Smiod bfd_elf_link_record_dynamic_symbol (info, h);
4111*cf2f2c56Smiod break;
4112*cf2f2c56Smiod }
4113*cf2f2c56Smiod picrel
4114*cf2f2c56Smiod = frvfdpic_relocs_info_for_global (frvfdpic_relocs_info (info),
4115*cf2f2c56Smiod abfd, h,
4116*cf2f2c56Smiod rel->r_addend, INSERT);
4117*cf2f2c56Smiod }
4118*cf2f2c56Smiod else
4119*cf2f2c56Smiod picrel = frvfdpic_relocs_info_for_local (frvfdpic_relocs_info
4120*cf2f2c56Smiod (info), abfd, r_symndx,
4121*cf2f2c56Smiod rel->r_addend, INSERT);
4122*cf2f2c56Smiod if (! picrel)
4123*cf2f2c56Smiod return FALSE;
4124*cf2f2c56Smiod break;
4125*cf2f2c56Smiod
4126*cf2f2c56Smiod default:
4127*cf2f2c56Smiod picrel = NULL;
4128*cf2f2c56Smiod break;
4129*cf2f2c56Smiod }
4130*cf2f2c56Smiod
4131*cf2f2c56Smiod switch (ELF32_R_TYPE (rel->r_info))
4132*cf2f2c56Smiod {
4133*cf2f2c56Smiod case R_FRV_LABEL24:
4134*cf2f2c56Smiod if (IS_FDPIC (abfd))
4135*cf2f2c56Smiod picrel->call = 1;
4136*cf2f2c56Smiod break;
4137*cf2f2c56Smiod
4138*cf2f2c56Smiod case R_FRV_FUNCDESC_VALUE:
4139*cf2f2c56Smiod picrel->relocsfdv++;
4140*cf2f2c56Smiod if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
4141*cf2f2c56Smiod picrel->relocs32--;
4142*cf2f2c56Smiod /* Fall through. */
4143*cf2f2c56Smiod
4144*cf2f2c56Smiod case R_FRV_32:
4145*cf2f2c56Smiod if (! IS_FDPIC (abfd))
4146*cf2f2c56Smiod break;
4147*cf2f2c56Smiod
4148*cf2f2c56Smiod picrel->sym = 1;
4149*cf2f2c56Smiod if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
4150*cf2f2c56Smiod picrel->relocs32++;
4151*cf2f2c56Smiod break;
4152*cf2f2c56Smiod
4153*cf2f2c56Smiod case R_FRV_GOT12:
4154*cf2f2c56Smiod picrel->got12 = 1;
4155*cf2f2c56Smiod break;
4156*cf2f2c56Smiod
4157*cf2f2c56Smiod case R_FRV_GOTHI:
4158*cf2f2c56Smiod case R_FRV_GOTLO:
4159*cf2f2c56Smiod picrel->gothilo = 1;
4160*cf2f2c56Smiod break;
4161*cf2f2c56Smiod
4162*cf2f2c56Smiod case R_FRV_FUNCDESC_GOT12:
4163*cf2f2c56Smiod picrel->fdgot12 = 1;
4164*cf2f2c56Smiod break;
4165*cf2f2c56Smiod
4166*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTHI:
4167*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTLO:
4168*cf2f2c56Smiod picrel->fdgothilo = 1;
4169*cf2f2c56Smiod break;
4170*cf2f2c56Smiod
4171*cf2f2c56Smiod case R_FRV_GOTOFF12:
4172*cf2f2c56Smiod case R_FRV_GOTOFFHI:
4173*cf2f2c56Smiod case R_FRV_GOTOFFLO:
4174*cf2f2c56Smiod picrel->gotoff = 1;
4175*cf2f2c56Smiod break;
4176*cf2f2c56Smiod
4177*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFF12:
4178*cf2f2c56Smiod picrel->fdgoff12 = 1;
4179*cf2f2c56Smiod break;
4180*cf2f2c56Smiod
4181*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFHI:
4182*cf2f2c56Smiod case R_FRV_FUNCDESC_GOTOFFLO:
4183*cf2f2c56Smiod picrel->fdgoffhilo = 1;
4184*cf2f2c56Smiod break;
4185*cf2f2c56Smiod
4186*cf2f2c56Smiod case R_FRV_FUNCDESC:
4187*cf2f2c56Smiod picrel->fd = 1;
4188*cf2f2c56Smiod picrel->relocsfd++;
4189*cf2f2c56Smiod break;
4190*cf2f2c56Smiod
4191d2201f2fSdrahn /* This relocation describes the C++ object vtable hierarchy.
4192d2201f2fSdrahn Reconstruct it for later use during GC. */
4193d2201f2fSdrahn case R_FRV_GNU_VTINHERIT:
4194*cf2f2c56Smiod if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
4195d2201f2fSdrahn return FALSE;
4196d2201f2fSdrahn break;
4197d2201f2fSdrahn
4198d2201f2fSdrahn /* This relocation describes which C++ vtable entries are actually
4199d2201f2fSdrahn used. Record for later use during GC. */
4200d2201f2fSdrahn case R_FRV_GNU_VTENTRY:
4201*cf2f2c56Smiod if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
4202d2201f2fSdrahn return FALSE;
4203d2201f2fSdrahn break;
4204*cf2f2c56Smiod
4205*cf2f2c56Smiod case R_FRV_LABEL16:
4206*cf2f2c56Smiod case R_FRV_LO16:
4207*cf2f2c56Smiod case R_FRV_HI16:
4208*cf2f2c56Smiod case R_FRV_GPREL12:
4209*cf2f2c56Smiod case R_FRV_GPRELU12:
4210*cf2f2c56Smiod case R_FRV_GPREL32:
4211*cf2f2c56Smiod case R_FRV_GPRELHI:
4212*cf2f2c56Smiod case R_FRV_GPRELLO:
4213*cf2f2c56Smiod break;
4214*cf2f2c56Smiod
4215*cf2f2c56Smiod default:
4216*cf2f2c56Smiod bad_reloc:
4217*cf2f2c56Smiod (*_bfd_error_handler)
4218*cf2f2c56Smiod (_("%s: unsupported relocation type %i"),
4219*cf2f2c56Smiod bfd_archive_filename (abfd), ELF32_R_TYPE (rel->r_info));
4220*cf2f2c56Smiod return FALSE;
4221d2201f2fSdrahn }
4222d2201f2fSdrahn }
4223d2201f2fSdrahn
4224d2201f2fSdrahn return TRUE;
4225d2201f2fSdrahn }
4226d2201f2fSdrahn
4227d2201f2fSdrahn
4228d2201f2fSdrahn /* Return the machine subcode from the ELF e_flags header. */
4229d2201f2fSdrahn
4230d2201f2fSdrahn static int
elf32_frv_machine(abfd)4231d2201f2fSdrahn elf32_frv_machine (abfd)
4232d2201f2fSdrahn bfd *abfd;
4233d2201f2fSdrahn {
4234d2201f2fSdrahn switch (elf_elfheader (abfd)->e_flags & EF_FRV_CPU_MASK)
4235d2201f2fSdrahn {
4236d2201f2fSdrahn default: break;
4237*cf2f2c56Smiod case EF_FRV_CPU_FR550: return bfd_mach_fr550;
4238d2201f2fSdrahn case EF_FRV_CPU_FR500: return bfd_mach_fr500;
4239d2201f2fSdrahn case EF_FRV_CPU_FR400: return bfd_mach_fr400;
4240d2201f2fSdrahn case EF_FRV_CPU_FR300: return bfd_mach_fr300;
4241d2201f2fSdrahn case EF_FRV_CPU_SIMPLE: return bfd_mach_frvsimple;
4242d2201f2fSdrahn case EF_FRV_CPU_TOMCAT: return bfd_mach_frvtomcat;
4243d2201f2fSdrahn }
4244d2201f2fSdrahn
4245d2201f2fSdrahn return bfd_mach_frv;
4246d2201f2fSdrahn }
4247d2201f2fSdrahn
4248d2201f2fSdrahn /* Set the right machine number for a FRV ELF file. */
4249d2201f2fSdrahn
4250d2201f2fSdrahn static bfd_boolean
elf32_frv_object_p(abfd)4251d2201f2fSdrahn elf32_frv_object_p (abfd)
4252d2201f2fSdrahn bfd *abfd;
4253d2201f2fSdrahn {
4254d2201f2fSdrahn bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
4255*cf2f2c56Smiod return (((elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC) != 0)
4256*cf2f2c56Smiod == (IS_FDPIC (abfd)));
4257d2201f2fSdrahn }
4258d2201f2fSdrahn
4259d2201f2fSdrahn /* Function to set the ELF flag bits. */
4260d2201f2fSdrahn
4261d2201f2fSdrahn static bfd_boolean
frv_elf_set_private_flags(abfd,flags)4262d2201f2fSdrahn frv_elf_set_private_flags (abfd, flags)
4263d2201f2fSdrahn bfd *abfd;
4264d2201f2fSdrahn flagword flags;
4265d2201f2fSdrahn {
4266d2201f2fSdrahn elf_elfheader (abfd)->e_flags = flags;
4267d2201f2fSdrahn elf_flags_init (abfd) = TRUE;
4268d2201f2fSdrahn return TRUE;
4269d2201f2fSdrahn }
4270d2201f2fSdrahn
4271d2201f2fSdrahn /* Copy backend specific data from one object module to another. */
4272d2201f2fSdrahn
4273d2201f2fSdrahn static bfd_boolean
frv_elf_copy_private_bfd_data(ibfd,obfd)4274d2201f2fSdrahn frv_elf_copy_private_bfd_data (ibfd, obfd)
4275d2201f2fSdrahn bfd *ibfd;
4276d2201f2fSdrahn bfd *obfd;
4277d2201f2fSdrahn {
4278d2201f2fSdrahn if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
4279d2201f2fSdrahn || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
4280d2201f2fSdrahn return TRUE;
4281d2201f2fSdrahn
4282d2201f2fSdrahn BFD_ASSERT (!elf_flags_init (obfd)
4283d2201f2fSdrahn || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
4284d2201f2fSdrahn
4285d2201f2fSdrahn elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
4286d2201f2fSdrahn elf_flags_init (obfd) = TRUE;
4287d2201f2fSdrahn return TRUE;
4288d2201f2fSdrahn }
4289d2201f2fSdrahn
4290*cf2f2c56Smiod static bfd_boolean
elf32_frvfdpic_copy_private_bfd_data(bfd * ibfd,bfd * obfd)4291*cf2f2c56Smiod elf32_frvfdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
4292*cf2f2c56Smiod {
4293*cf2f2c56Smiod unsigned i;
4294*cf2f2c56Smiod
4295*cf2f2c56Smiod if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
4296*cf2f2c56Smiod || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
4297*cf2f2c56Smiod return TRUE;
4298*cf2f2c56Smiod
4299*cf2f2c56Smiod if (! frv_elf_copy_private_bfd_data (ibfd, obfd))
4300*cf2f2c56Smiod return FALSE;
4301*cf2f2c56Smiod
4302*cf2f2c56Smiod if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr
4303*cf2f2c56Smiod || ! elf_tdata (obfd) || ! elf_tdata (obfd)->phdr)
4304*cf2f2c56Smiod return TRUE;
4305*cf2f2c56Smiod
4306*cf2f2c56Smiod /* Copy the stack size. */
4307*cf2f2c56Smiod for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++)
4308*cf2f2c56Smiod if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK)
4309*cf2f2c56Smiod {
4310*cf2f2c56Smiod Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i];
4311*cf2f2c56Smiod
4312*cf2f2c56Smiod for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++)
4313*cf2f2c56Smiod if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK)
4314*cf2f2c56Smiod {
4315*cf2f2c56Smiod memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr));
4316*cf2f2c56Smiod
4317*cf2f2c56Smiod /* Rewrite the phdrs, since we're only called after they
4318*cf2f2c56Smiod were first written. */
4319*cf2f2c56Smiod if (bfd_seek (obfd, (bfd_signed_vma) get_elf_backend_data (obfd)
4320*cf2f2c56Smiod ->s->sizeof_ehdr, SEEK_SET) != 0
4321*cf2f2c56Smiod || get_elf_backend_data (obfd)->s
4322*cf2f2c56Smiod ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr,
4323*cf2f2c56Smiod elf_elfheader (obfd)->e_phnum) != 0)
4324*cf2f2c56Smiod return FALSE;
4325*cf2f2c56Smiod break;
4326*cf2f2c56Smiod }
4327*cf2f2c56Smiod
4328*cf2f2c56Smiod break;
4329*cf2f2c56Smiod }
4330*cf2f2c56Smiod
4331*cf2f2c56Smiod return TRUE;
4332*cf2f2c56Smiod }
4333*cf2f2c56Smiod
4334d2201f2fSdrahn /* Merge backend specific data from an object file to the output
4335d2201f2fSdrahn object file when linking. */
4336d2201f2fSdrahn
4337d2201f2fSdrahn static bfd_boolean
frv_elf_merge_private_bfd_data(ibfd,obfd)4338d2201f2fSdrahn frv_elf_merge_private_bfd_data (ibfd, obfd)
4339d2201f2fSdrahn bfd *ibfd;
4340d2201f2fSdrahn bfd *obfd;
4341d2201f2fSdrahn {
4342d2201f2fSdrahn flagword old_flags, old_partial;
4343d2201f2fSdrahn flagword new_flags, new_partial;
4344d2201f2fSdrahn bfd_boolean error = FALSE;
4345d2201f2fSdrahn char new_opt[80];
4346d2201f2fSdrahn char old_opt[80];
4347d2201f2fSdrahn
4348d2201f2fSdrahn new_opt[0] = old_opt[0] = '\0';
4349d2201f2fSdrahn new_flags = elf_elfheader (ibfd)->e_flags;
4350d2201f2fSdrahn old_flags = elf_elfheader (obfd)->e_flags;
4351d2201f2fSdrahn
4352*cf2f2c56Smiod if (new_flags & EF_FRV_FDPIC)
4353*cf2f2c56Smiod new_flags &= ~EF_FRV_PIC;
4354*cf2f2c56Smiod
4355d2201f2fSdrahn #ifdef DEBUG
4356d2201f2fSdrahn (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
4357d2201f2fSdrahn old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
4358d2201f2fSdrahn bfd_get_filename (ibfd));
4359d2201f2fSdrahn #endif
4360d2201f2fSdrahn
4361d2201f2fSdrahn if (!elf_flags_init (obfd)) /* First call, no flags set. */
4362d2201f2fSdrahn {
4363d2201f2fSdrahn elf_flags_init (obfd) = TRUE;
4364d2201f2fSdrahn old_flags = new_flags;
4365d2201f2fSdrahn }
4366d2201f2fSdrahn
4367d2201f2fSdrahn else if (new_flags == old_flags) /* Compatible flags are ok. */
4368d2201f2fSdrahn ;
4369d2201f2fSdrahn
4370d2201f2fSdrahn else /* Possibly incompatible flags. */
4371d2201f2fSdrahn {
4372d2201f2fSdrahn /* Warn if different # of gprs are used. Note, 0 means nothing is
4373d2201f2fSdrahn said about the size of gprs. */
4374d2201f2fSdrahn new_partial = (new_flags & EF_FRV_GPR_MASK);
4375d2201f2fSdrahn old_partial = (old_flags & EF_FRV_GPR_MASK);
4376d2201f2fSdrahn if (new_partial == old_partial)
4377d2201f2fSdrahn ;
4378d2201f2fSdrahn
4379d2201f2fSdrahn else if (new_partial == 0)
4380d2201f2fSdrahn ;
4381d2201f2fSdrahn
4382d2201f2fSdrahn else if (old_partial == 0)
4383d2201f2fSdrahn old_flags |= new_partial;
4384d2201f2fSdrahn
4385d2201f2fSdrahn else
4386d2201f2fSdrahn {
4387d2201f2fSdrahn switch (new_partial)
4388d2201f2fSdrahn {
4389d2201f2fSdrahn default: strcat (new_opt, " -mgpr-??"); break;
4390d2201f2fSdrahn case EF_FRV_GPR_32: strcat (new_opt, " -mgpr-32"); break;
4391d2201f2fSdrahn case EF_FRV_GPR_64: strcat (new_opt, " -mgpr-64"); break;
4392d2201f2fSdrahn }
4393d2201f2fSdrahn
4394d2201f2fSdrahn switch (old_partial)
4395d2201f2fSdrahn {
4396d2201f2fSdrahn default: strcat (old_opt, " -mgpr-??"); break;
4397d2201f2fSdrahn case EF_FRV_GPR_32: strcat (old_opt, " -mgpr-32"); break;
4398d2201f2fSdrahn case EF_FRV_GPR_64: strcat (old_opt, " -mgpr-64"); break;
4399d2201f2fSdrahn }
4400d2201f2fSdrahn }
4401d2201f2fSdrahn
4402d2201f2fSdrahn /* Warn if different # of fprs are used. Note, 0 means nothing is
4403d2201f2fSdrahn said about the size of fprs. */
4404d2201f2fSdrahn new_partial = (new_flags & EF_FRV_FPR_MASK);
4405d2201f2fSdrahn old_partial = (old_flags & EF_FRV_FPR_MASK);
4406d2201f2fSdrahn if (new_partial == old_partial)
4407d2201f2fSdrahn ;
4408d2201f2fSdrahn
4409d2201f2fSdrahn else if (new_partial == 0)
4410d2201f2fSdrahn ;
4411d2201f2fSdrahn
4412d2201f2fSdrahn else if (old_partial == 0)
4413d2201f2fSdrahn old_flags |= new_partial;
4414d2201f2fSdrahn
4415d2201f2fSdrahn else
4416d2201f2fSdrahn {
4417d2201f2fSdrahn switch (new_partial)
4418d2201f2fSdrahn {
4419d2201f2fSdrahn default: strcat (new_opt, " -mfpr-?"); break;
4420d2201f2fSdrahn case EF_FRV_FPR_32: strcat (new_opt, " -mfpr-32"); break;
4421d2201f2fSdrahn case EF_FRV_FPR_64: strcat (new_opt, " -mfpr-64"); break;
4422d2201f2fSdrahn case EF_FRV_FPR_NONE: strcat (new_opt, " -msoft-float"); break;
4423d2201f2fSdrahn }
4424d2201f2fSdrahn
4425d2201f2fSdrahn switch (old_partial)
4426d2201f2fSdrahn {
4427d2201f2fSdrahn default: strcat (old_opt, " -mfpr-?"); break;
4428d2201f2fSdrahn case EF_FRV_FPR_32: strcat (old_opt, " -mfpr-32"); break;
4429d2201f2fSdrahn case EF_FRV_FPR_64: strcat (old_opt, " -mfpr-64"); break;
4430d2201f2fSdrahn case EF_FRV_FPR_NONE: strcat (old_opt, " -msoft-float"); break;
4431d2201f2fSdrahn }
4432d2201f2fSdrahn }
4433d2201f2fSdrahn
4434d2201f2fSdrahn /* Warn if different dword support was used. Note, 0 means nothing is
4435d2201f2fSdrahn said about the dword support. */
4436d2201f2fSdrahn new_partial = (new_flags & EF_FRV_DWORD_MASK);
4437d2201f2fSdrahn old_partial = (old_flags & EF_FRV_DWORD_MASK);
4438d2201f2fSdrahn if (new_partial == old_partial)
4439d2201f2fSdrahn ;
4440d2201f2fSdrahn
4441d2201f2fSdrahn else if (new_partial == 0)
4442d2201f2fSdrahn ;
4443d2201f2fSdrahn
4444d2201f2fSdrahn else if (old_partial == 0)
4445d2201f2fSdrahn old_flags |= new_partial;
4446d2201f2fSdrahn
4447d2201f2fSdrahn else
4448d2201f2fSdrahn {
4449d2201f2fSdrahn switch (new_partial)
4450d2201f2fSdrahn {
4451d2201f2fSdrahn default: strcat (new_opt, " -mdword-?"); break;
4452d2201f2fSdrahn case EF_FRV_DWORD_YES: strcat (new_opt, " -mdword"); break;
4453d2201f2fSdrahn case EF_FRV_DWORD_NO: strcat (new_opt, " -mno-dword"); break;
4454d2201f2fSdrahn }
4455d2201f2fSdrahn
4456d2201f2fSdrahn switch (old_partial)
4457d2201f2fSdrahn {
4458d2201f2fSdrahn default: strcat (old_opt, " -mdword-?"); break;
4459d2201f2fSdrahn case EF_FRV_DWORD_YES: strcat (old_opt, " -mdword"); break;
4460d2201f2fSdrahn case EF_FRV_DWORD_NO: strcat (old_opt, " -mno-dword"); break;
4461d2201f2fSdrahn }
4462d2201f2fSdrahn }
4463d2201f2fSdrahn
4464d2201f2fSdrahn /* Or in flags that accumulate (ie, if one module uses it, mark that the
4465d2201f2fSdrahn feature is used. */
4466d2201f2fSdrahn old_flags |= new_flags & (EF_FRV_DOUBLE
4467d2201f2fSdrahn | EF_FRV_MEDIA
4468d2201f2fSdrahn | EF_FRV_MULADD
4469d2201f2fSdrahn | EF_FRV_NON_PIC_RELOCS);
4470d2201f2fSdrahn
4471d2201f2fSdrahn /* If any module was compiled without -G0, clear the G0 bit. */
4472d2201f2fSdrahn old_flags = ((old_flags & ~ EF_FRV_G0)
4473d2201f2fSdrahn | (old_flags & new_flags & EF_FRV_G0));
4474d2201f2fSdrahn
4475d2201f2fSdrahn /* If any module was compiled without -mnopack, clear the mnopack bit. */
4476d2201f2fSdrahn old_flags = ((old_flags & ~ EF_FRV_NOPACK)
4477d2201f2fSdrahn | (old_flags & new_flags & EF_FRV_NOPACK));
4478d2201f2fSdrahn
4479d2201f2fSdrahn /* We don't have to do anything if the pic flags are the same, or the new
4480d2201f2fSdrahn module(s) were compiled with -mlibrary-pic. */
4481d2201f2fSdrahn new_partial = (new_flags & EF_FRV_PIC_FLAGS);
4482d2201f2fSdrahn old_partial = (old_flags & EF_FRV_PIC_FLAGS);
4483d2201f2fSdrahn if ((new_partial == old_partial) || ((new_partial & EF_FRV_LIBPIC) != 0))
4484d2201f2fSdrahn ;
4485d2201f2fSdrahn
4486d2201f2fSdrahn /* If the old module(s) were compiled with -mlibrary-pic, copy in the pic
4487d2201f2fSdrahn flags if any from the new module. */
4488d2201f2fSdrahn else if ((old_partial & EF_FRV_LIBPIC) != 0)
4489d2201f2fSdrahn old_flags = (old_flags & ~ EF_FRV_PIC_FLAGS) | new_partial;
4490d2201f2fSdrahn
4491d2201f2fSdrahn /* If we have mixtures of -fpic and -fPIC, or in both bits. */
4492d2201f2fSdrahn else if (new_partial != 0 && old_partial != 0)
4493d2201f2fSdrahn old_flags |= new_partial;
4494d2201f2fSdrahn
4495d2201f2fSdrahn /* One module was compiled for pic and the other was not, see if we have
4496d2201f2fSdrahn had any relocations that are not pic-safe. */
4497d2201f2fSdrahn else
4498d2201f2fSdrahn {
4499d2201f2fSdrahn if ((old_flags & EF_FRV_NON_PIC_RELOCS) == 0)
4500d2201f2fSdrahn old_flags |= new_partial;
4501d2201f2fSdrahn else
4502d2201f2fSdrahn {
4503d2201f2fSdrahn old_flags &= ~ EF_FRV_PIC_FLAGS;
4504d2201f2fSdrahn #ifndef FRV_NO_PIC_ERROR
4505d2201f2fSdrahn error = TRUE;
4506d2201f2fSdrahn (*_bfd_error_handler)
4507d2201f2fSdrahn (_("%s: compiled with %s and linked with modules that use non-pic relocations"),
4508d2201f2fSdrahn bfd_get_filename (ibfd),
4509d2201f2fSdrahn (new_flags & EF_FRV_BIGPIC) ? "-fPIC" : "-fpic");
4510d2201f2fSdrahn #endif
4511d2201f2fSdrahn }
4512d2201f2fSdrahn }
4513d2201f2fSdrahn
4514d2201f2fSdrahn /* Warn if different cpu is used (allow a specific cpu to override
4515d2201f2fSdrahn the generic cpu). */
4516d2201f2fSdrahn new_partial = (new_flags & EF_FRV_CPU_MASK);
4517d2201f2fSdrahn old_partial = (old_flags & EF_FRV_CPU_MASK);
4518d2201f2fSdrahn if (new_partial == old_partial)
4519d2201f2fSdrahn ;
4520d2201f2fSdrahn
4521d2201f2fSdrahn else if (new_partial == EF_FRV_CPU_GENERIC)
4522d2201f2fSdrahn ;
4523d2201f2fSdrahn
4524d2201f2fSdrahn else if (old_partial == EF_FRV_CPU_GENERIC)
4525d2201f2fSdrahn old_flags = (old_flags & ~EF_FRV_CPU_MASK) | new_partial;
4526d2201f2fSdrahn
4527d2201f2fSdrahn else
4528d2201f2fSdrahn {
4529d2201f2fSdrahn switch (new_partial)
4530d2201f2fSdrahn {
4531d2201f2fSdrahn default: strcat (new_opt, " -mcpu=?"); break;
4532d2201f2fSdrahn case EF_FRV_CPU_GENERIC: strcat (new_opt, " -mcpu=frv"); break;
4533d2201f2fSdrahn case EF_FRV_CPU_SIMPLE: strcat (new_opt, " -mcpu=simple"); break;
4534*cf2f2c56Smiod case EF_FRV_CPU_FR550: strcat (new_opt, " -mcpu=fr550"); break;
4535d2201f2fSdrahn case EF_FRV_CPU_FR500: strcat (new_opt, " -mcpu=fr500"); break;
4536d2201f2fSdrahn case EF_FRV_CPU_FR400: strcat (new_opt, " -mcpu=fr400"); break;
4537d2201f2fSdrahn case EF_FRV_CPU_FR300: strcat (new_opt, " -mcpu=fr300"); break;
4538d2201f2fSdrahn case EF_FRV_CPU_TOMCAT: strcat (new_opt, " -mcpu=tomcat"); break;
4539d2201f2fSdrahn }
4540d2201f2fSdrahn
4541d2201f2fSdrahn switch (old_partial)
4542d2201f2fSdrahn {
4543d2201f2fSdrahn default: strcat (old_opt, " -mcpu=?"); break;
4544d2201f2fSdrahn case EF_FRV_CPU_GENERIC: strcat (old_opt, " -mcpu=frv"); break;
4545d2201f2fSdrahn case EF_FRV_CPU_SIMPLE: strcat (old_opt, " -mcpu=simple"); break;
4546*cf2f2c56Smiod case EF_FRV_CPU_FR550: strcat (old_opt, " -mcpu=fr550"); break;
4547d2201f2fSdrahn case EF_FRV_CPU_FR500: strcat (old_opt, " -mcpu=fr500"); break;
4548d2201f2fSdrahn case EF_FRV_CPU_FR400: strcat (old_opt, " -mcpu=fr400"); break;
4549d2201f2fSdrahn case EF_FRV_CPU_FR300: strcat (old_opt, " -mcpu=fr300"); break;
4550d2201f2fSdrahn case EF_FRV_CPU_TOMCAT: strcat (old_opt, " -mcpu=tomcat"); break;
4551d2201f2fSdrahn }
4552d2201f2fSdrahn }
4553d2201f2fSdrahn
4554d2201f2fSdrahn /* Print out any mismatches from above. */
4555d2201f2fSdrahn if (new_opt[0])
4556d2201f2fSdrahn {
4557d2201f2fSdrahn error = TRUE;
4558d2201f2fSdrahn (*_bfd_error_handler)
4559d2201f2fSdrahn (_("%s: compiled with %s and linked with modules compiled with %s"),
4560d2201f2fSdrahn bfd_get_filename (ibfd), new_opt, old_opt);
4561d2201f2fSdrahn }
4562d2201f2fSdrahn
4563d2201f2fSdrahn /* Warn about any other mismatches */
4564d2201f2fSdrahn new_partial = (new_flags & ~ EF_FRV_ALL_FLAGS);
4565d2201f2fSdrahn old_partial = (old_flags & ~ EF_FRV_ALL_FLAGS);
4566d2201f2fSdrahn if (new_partial != old_partial)
4567d2201f2fSdrahn {
4568d2201f2fSdrahn old_flags |= new_partial;
4569d2201f2fSdrahn error = TRUE;
4570d2201f2fSdrahn (*_bfd_error_handler)
4571d2201f2fSdrahn (_("%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)"),
4572d2201f2fSdrahn bfd_get_filename (ibfd), (long)new_partial, (long)old_partial);
4573d2201f2fSdrahn }
4574d2201f2fSdrahn }
4575d2201f2fSdrahn
4576d2201f2fSdrahn /* If the cpu is -mcpu=simple, then set the -mnopack bit. */
4577d2201f2fSdrahn if ((old_flags & EF_FRV_CPU_MASK) == EF_FRV_CPU_SIMPLE)
4578d2201f2fSdrahn old_flags |= EF_FRV_NOPACK;
4579d2201f2fSdrahn
4580d2201f2fSdrahn /* Update the old flags now with changes made above. */
4581d2201f2fSdrahn old_partial = elf_elfheader (obfd)->e_flags & EF_FRV_CPU_MASK;
4582d2201f2fSdrahn elf_elfheader (obfd)->e_flags = old_flags;
4583d2201f2fSdrahn if (old_partial != (old_flags & EF_FRV_CPU_MASK))
4584d2201f2fSdrahn bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
4585d2201f2fSdrahn
4586*cf2f2c56Smiod if (((new_flags & EF_FRV_FDPIC) == 0)
4587*cf2f2c56Smiod != (! IS_FDPIC (ibfd)))
4588*cf2f2c56Smiod {
4589*cf2f2c56Smiod error = TRUE;
4590*cf2f2c56Smiod if (IS_FDPIC (obfd))
4591*cf2f2c56Smiod (*_bfd_error_handler)
4592*cf2f2c56Smiod (_("%s: cannot link non-fdpic object file into fdpic executable"),
4593*cf2f2c56Smiod bfd_get_filename (ibfd));
4594*cf2f2c56Smiod else
4595*cf2f2c56Smiod (*_bfd_error_handler)
4596*cf2f2c56Smiod (_("%s: cannot link fdpic object file into non-fdpic executable"),
4597*cf2f2c56Smiod bfd_get_filename (ibfd));
4598*cf2f2c56Smiod }
4599*cf2f2c56Smiod
4600d2201f2fSdrahn if (error)
4601d2201f2fSdrahn bfd_set_error (bfd_error_bad_value);
4602d2201f2fSdrahn
4603d2201f2fSdrahn return !error;
4604d2201f2fSdrahn }
4605d2201f2fSdrahn
4606d2201f2fSdrahn
4607d2201f2fSdrahn bfd_boolean
frv_elf_print_private_bfd_data(abfd,ptr)4608d2201f2fSdrahn frv_elf_print_private_bfd_data (abfd, ptr)
4609d2201f2fSdrahn bfd *abfd;
4610d2201f2fSdrahn PTR ptr;
4611d2201f2fSdrahn {
4612d2201f2fSdrahn FILE *file = (FILE *) ptr;
4613d2201f2fSdrahn flagword flags;
4614d2201f2fSdrahn
4615d2201f2fSdrahn BFD_ASSERT (abfd != NULL && ptr != NULL);
4616d2201f2fSdrahn
4617d2201f2fSdrahn /* Print normal ELF private data. */
4618d2201f2fSdrahn _bfd_elf_print_private_bfd_data (abfd, ptr);
4619d2201f2fSdrahn
4620d2201f2fSdrahn flags = elf_elfheader (abfd)->e_flags;
4621d2201f2fSdrahn fprintf (file, _("private flags = 0x%lx:"), (long)flags);
4622d2201f2fSdrahn
4623d2201f2fSdrahn switch (flags & EF_FRV_CPU_MASK)
4624d2201f2fSdrahn {
4625d2201f2fSdrahn default: break;
4626d2201f2fSdrahn case EF_FRV_CPU_SIMPLE: fprintf (file, " -mcpu=simple"); break;
4627*cf2f2c56Smiod case EF_FRV_CPU_FR550: fprintf (file, " -mcpu=fr550"); break;
4628d2201f2fSdrahn case EF_FRV_CPU_FR500: fprintf (file, " -mcpu=fr500"); break;
4629d2201f2fSdrahn case EF_FRV_CPU_FR400: fprintf (file, " -mcpu=fr400"); break;
4630d2201f2fSdrahn case EF_FRV_CPU_FR300: fprintf (file, " -mcpu=fr300"); break;
4631d2201f2fSdrahn case EF_FRV_CPU_TOMCAT: fprintf (file, " -mcpu=tomcat"); break;
4632d2201f2fSdrahn }
4633d2201f2fSdrahn
4634d2201f2fSdrahn switch (flags & EF_FRV_GPR_MASK)
4635d2201f2fSdrahn {
4636d2201f2fSdrahn default: break;
4637d2201f2fSdrahn case EF_FRV_GPR_32: fprintf (file, " -mgpr-32"); break;
4638d2201f2fSdrahn case EF_FRV_GPR_64: fprintf (file, " -mgpr-64"); break;
4639d2201f2fSdrahn }
4640d2201f2fSdrahn
4641d2201f2fSdrahn switch (flags & EF_FRV_FPR_MASK)
4642d2201f2fSdrahn {
4643d2201f2fSdrahn default: break;
4644d2201f2fSdrahn case EF_FRV_FPR_32: fprintf (file, " -mfpr-32"); break;
4645d2201f2fSdrahn case EF_FRV_FPR_64: fprintf (file, " -mfpr-64"); break;
4646d2201f2fSdrahn case EF_FRV_FPR_NONE: fprintf (file, " -msoft-float"); break;
4647d2201f2fSdrahn }
4648d2201f2fSdrahn
4649d2201f2fSdrahn switch (flags & EF_FRV_DWORD_MASK)
4650d2201f2fSdrahn {
4651d2201f2fSdrahn default: break;
4652d2201f2fSdrahn case EF_FRV_DWORD_YES: fprintf (file, " -mdword"); break;
4653d2201f2fSdrahn case EF_FRV_DWORD_NO: fprintf (file, " -mno-dword"); break;
4654d2201f2fSdrahn }
4655d2201f2fSdrahn
4656d2201f2fSdrahn if (flags & EF_FRV_DOUBLE)
4657d2201f2fSdrahn fprintf (file, " -mdouble");
4658d2201f2fSdrahn
4659d2201f2fSdrahn if (flags & EF_FRV_MEDIA)
4660d2201f2fSdrahn fprintf (file, " -mmedia");
4661d2201f2fSdrahn
4662d2201f2fSdrahn if (flags & EF_FRV_MULADD)
4663d2201f2fSdrahn fprintf (file, " -mmuladd");
4664d2201f2fSdrahn
4665d2201f2fSdrahn if (flags & EF_FRV_PIC)
4666d2201f2fSdrahn fprintf (file, " -fpic");
4667d2201f2fSdrahn
4668d2201f2fSdrahn if (flags & EF_FRV_BIGPIC)
4669d2201f2fSdrahn fprintf (file, " -fPIC");
4670d2201f2fSdrahn
4671*cf2f2c56Smiod if (flags & EF_FRV_LIBPIC)
4672*cf2f2c56Smiod fprintf (file, " -mlibrary-pic");
4673*cf2f2c56Smiod
4674*cf2f2c56Smiod if (flags & EF_FRV_FDPIC)
4675*cf2f2c56Smiod fprintf (file, " -mfdpic");
4676*cf2f2c56Smiod
4677d2201f2fSdrahn if (flags & EF_FRV_NON_PIC_RELOCS)
4678d2201f2fSdrahn fprintf (file, " non-pic relocations");
4679d2201f2fSdrahn
4680d2201f2fSdrahn if (flags & EF_FRV_G0)
4681d2201f2fSdrahn fprintf (file, " -G0");
4682d2201f2fSdrahn
4683d2201f2fSdrahn fputc ('\n', file);
4684d2201f2fSdrahn return TRUE;
4685d2201f2fSdrahn }
4686d2201f2fSdrahn
4687d2201f2fSdrahn
4688d2201f2fSdrahn #define ELF_ARCH bfd_arch_frv
4689d2201f2fSdrahn #define ELF_MACHINE_CODE EM_CYGNUS_FRV
4690d2201f2fSdrahn #define ELF_MAXPAGESIZE 0x1000
4691d2201f2fSdrahn
4692d2201f2fSdrahn #define TARGET_BIG_SYM bfd_elf32_frv_vec
4693d2201f2fSdrahn #define TARGET_BIG_NAME "elf32-frv"
4694d2201f2fSdrahn
4695d2201f2fSdrahn #define elf_info_to_howto frv_info_to_howto_rela
4696d2201f2fSdrahn #define elf_backend_relocate_section elf32_frv_relocate_section
4697d2201f2fSdrahn #define elf_backend_gc_mark_hook elf32_frv_gc_mark_hook
4698d2201f2fSdrahn #define elf_backend_gc_sweep_hook elf32_frv_gc_sweep_hook
4699d2201f2fSdrahn #define elf_backend_check_relocs elf32_frv_check_relocs
4700d2201f2fSdrahn #define elf_backend_object_p elf32_frv_object_p
4701d2201f2fSdrahn #define elf_backend_add_symbol_hook elf32_frv_add_symbol_hook
4702d2201f2fSdrahn
4703d2201f2fSdrahn #define elf_backend_can_gc_sections 1
4704d2201f2fSdrahn #define elf_backend_rela_normal 1
4705d2201f2fSdrahn
4706d2201f2fSdrahn #define bfd_elf32_bfd_reloc_type_lookup frv_reloc_type_lookup
4707d2201f2fSdrahn #define bfd_elf32_bfd_set_private_flags frv_elf_set_private_flags
4708d2201f2fSdrahn #define bfd_elf32_bfd_copy_private_bfd_data frv_elf_copy_private_bfd_data
4709d2201f2fSdrahn #define bfd_elf32_bfd_merge_private_bfd_data frv_elf_merge_private_bfd_data
4710d2201f2fSdrahn #define bfd_elf32_bfd_print_private_bfd_data frv_elf_print_private_bfd_data
4711d2201f2fSdrahn
4712*cf2f2c56Smiod #define elf_backend_want_got_sym 1
4713*cf2f2c56Smiod #define elf_backend_got_header_size 0
4714*cf2f2c56Smiod #define elf_backend_want_got_plt 0
4715*cf2f2c56Smiod #define elf_backend_plt_readonly 1
4716*cf2f2c56Smiod #define elf_backend_want_plt_sym 0
4717*cf2f2c56Smiod #define elf_backend_plt_header_size 0
4718*cf2f2c56Smiod
4719*cf2f2c56Smiod #define elf_backend_finish_dynamic_sections \
4720*cf2f2c56Smiod elf32_frv_finish_dynamic_sections
4721*cf2f2c56Smiod
4722*cf2f2c56Smiod #include "elf32-target.h"
4723*cf2f2c56Smiod
4724*cf2f2c56Smiod #undef ELF_MAXPAGESIZE
4725*cf2f2c56Smiod #define ELF_MAXPAGESIZE 0x4000
4726*cf2f2c56Smiod
4727*cf2f2c56Smiod #undef TARGET_BIG_SYM
4728*cf2f2c56Smiod #define TARGET_BIG_SYM bfd_elf32_frvfdpic_vec
4729*cf2f2c56Smiod #undef TARGET_BIG_NAME
4730*cf2f2c56Smiod #define TARGET_BIG_NAME "elf32-frvfdpic"
4731*cf2f2c56Smiod #undef elf32_bed
4732*cf2f2c56Smiod #define elf32_bed elf32_frvfdpic_bed
4733*cf2f2c56Smiod
4734*cf2f2c56Smiod #undef elf_info_to_howto_rel
4735*cf2f2c56Smiod #define elf_info_to_howto_rel frvfdpic_info_to_howto_rel
4736*cf2f2c56Smiod
4737*cf2f2c56Smiod #undef bfd_elf32_bfd_link_hash_table_create
4738*cf2f2c56Smiod #define bfd_elf32_bfd_link_hash_table_create \
4739*cf2f2c56Smiod frvfdpic_elf_link_hash_table_create
4740*cf2f2c56Smiod #undef elf_backend_always_size_sections
4741*cf2f2c56Smiod #define elf_backend_always_size_sections \
4742*cf2f2c56Smiod elf32_frvfdpic_always_size_sections
4743*cf2f2c56Smiod #undef elf_backend_modify_segment_map
4744*cf2f2c56Smiod #define elf_backend_modify_segment_map \
4745*cf2f2c56Smiod elf32_frvfdpic_modify_segment_map
4746*cf2f2c56Smiod #undef bfd_elf32_bfd_copy_private_bfd_data
4747*cf2f2c56Smiod #define bfd_elf32_bfd_copy_private_bfd_data \
4748*cf2f2c56Smiod elf32_frvfdpic_copy_private_bfd_data
4749*cf2f2c56Smiod
4750*cf2f2c56Smiod #undef elf_backend_create_dynamic_sections
4751*cf2f2c56Smiod #define elf_backend_create_dynamic_sections \
4752*cf2f2c56Smiod elf32_frvfdpic_create_dynamic_sections
4753*cf2f2c56Smiod #undef elf_backend_adjust_dynamic_symbol
4754*cf2f2c56Smiod #define elf_backend_adjust_dynamic_symbol \
4755*cf2f2c56Smiod elf32_frvfdpic_adjust_dynamic_symbol
4756*cf2f2c56Smiod #undef elf_backend_size_dynamic_sections
4757*cf2f2c56Smiod #define elf_backend_size_dynamic_sections \
4758*cf2f2c56Smiod elf32_frvfdpic_size_dynamic_sections
4759*cf2f2c56Smiod #undef elf_backend_finish_dynamic_symbol
4760*cf2f2c56Smiod #define elf_backend_finish_dynamic_symbol \
4761*cf2f2c56Smiod elf32_frvfdpic_finish_dynamic_symbol
4762*cf2f2c56Smiod #undef elf_backend_finish_dynamic_sections
4763*cf2f2c56Smiod #define elf_backend_finish_dynamic_sections \
4764*cf2f2c56Smiod elf32_frvfdpic_finish_dynamic_sections
4765*cf2f2c56Smiod
4766*cf2f2c56Smiod #undef elf_backend_can_make_relative_eh_frame
4767*cf2f2c56Smiod #define elf_backend_can_make_relative_eh_frame \
4768*cf2f2c56Smiod frvfdpic_elf_use_relative_eh_frame
4769*cf2f2c56Smiod #undef elf_backend_can_make_lsda_relative_eh_frame
4770*cf2f2c56Smiod #define elf_backend_can_make_lsda_relative_eh_frame \
4771*cf2f2c56Smiod frvfdpic_elf_use_relative_eh_frame
4772*cf2f2c56Smiod #undef elf_backend_encode_eh_address
4773*cf2f2c56Smiod #define elf_backend_encode_eh_address \
4774*cf2f2c56Smiod frvfdpic_elf_encode_eh_address
4775*cf2f2c56Smiod
4776*cf2f2c56Smiod #undef elf_backend_may_use_rel_p
4777*cf2f2c56Smiod #define elf_backend_may_use_rel_p 1
4778*cf2f2c56Smiod #undef elf_backend_may_use_rela_p
4779*cf2f2c56Smiod #define elf_backend_may_use_rela_p 1
4780*cf2f2c56Smiod /* We use REL for dynamic relocations only. */
4781*cf2f2c56Smiod #undef elf_backend_default_use_rela_p
4782*cf2f2c56Smiod #define elf_backend_default_use_rela_p 1
4783*cf2f2c56Smiod
4784d2201f2fSdrahn #include "elf32-target.h"
4785