xref: /openbsd/gnu/usr.bin/binutils/bfd/elf32-frv.c (revision cf2f2c56)
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