add a heavily cleaned up version of ubicom32 toolchain support
[openwrt/openwrt.git] / toolchain / binutils / patches / 2.19.1 / 600-ubicom32_binutils_20090818.patch
1 --- a/bfd/archures.c
2 +++ b/bfd/archures.c
3 @@ -375,6 +375,11 @@ DESCRIPTION
4 . bfd_arch_score, {* Sunplus score *}
5 . bfd_arch_openrisc, {* OpenRISC *}
6 . bfd_arch_mmix, {* Donald Knuth's educational processor. *}
7 +. bfd_arch_ubicom32,
8 +.#define bfd_mach_ubicom32 0
9 +.#define bfd_mach_ubicom32dsp 1
10 +.#define bfd_mach_ubicom32ver4 2
11 +.#define bfd_mach_ubicom32posix 3
12 . bfd_arch_xstormy16,
13 .#define bfd_mach_xstormy16 1
14 . bfd_arch_msp430, {* Texas Instruments MSP430 architecture. *}
15 @@ -501,6 +506,7 @@ extern const bfd_arch_info_type bfd_tic3
16 extern const bfd_arch_info_type bfd_tic4x_arch;
17 extern const bfd_arch_info_type bfd_tic54x_arch;
18 extern const bfd_arch_info_type bfd_tic80_arch;
19 +extern const bfd_arch_info_type bfd_ubicom32_arch;
20 extern const bfd_arch_info_type bfd_v850_arch;
21 extern const bfd_arch_info_type bfd_vax_arch;
22 extern const bfd_arch_info_type bfd_we32k_arch;
23 @@ -570,6 +576,7 @@ static const bfd_arch_info_type * const
24 &bfd_tic4x_arch,
25 &bfd_tic54x_arch,
26 &bfd_tic80_arch,
27 + &bfd_ubicom32_arch,
28 &bfd_v850_arch,
29 &bfd_vax_arch,
30 &bfd_w65_arch,
31 --- a/bfd/bfd-in2.h
32 +++ b/bfd/bfd-in2.h
33 @@ -1997,6 +1997,11 @@ enum bfd_architecture
34 bfd_arch_score, /* Sunplus score */
35 bfd_arch_openrisc, /* OpenRISC */
36 bfd_arch_mmix, /* Donald Knuth's educational processor. */
37 + bfd_arch_ubicom32,
38 +#define bfd_mach_ubicom32 0
39 +#define bfd_mach_ubicom32dsp 1
40 +#define bfd_mach_ubicom32ver4 2
41 +#define bfd_mach_ubicom32posix 3
42 bfd_arch_xstormy16,
43 #define bfd_mach_xstormy16 1
44 bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */
45 @@ -3908,6 +3913,41 @@ instructions */
46 BFD_RELOC_VPE4KMATH_DATA,
47 BFD_RELOC_VPE4KMATH_INSN,
48
49 +/* Ubicom UBICOM32 Relocations. */
50 + BFD_RELOC_UBICOM32_21_PCREL,
51 + BFD_RELOC_UBICOM32_24_PCREL,
52 + BFD_RELOC_UBICOM32_HI24,
53 + BFD_RELOC_UBICOM32_LO7_S,
54 + BFD_RELOC_UBICOM32_LO7_2_S,
55 + BFD_RELOC_UBICOM32_LO7_4_S,
56 + BFD_RELOC_UBICOM32_LO7_D,
57 + BFD_RELOC_UBICOM32_LO7_2_D,
58 + BFD_RELOC_UBICOM32_LO7_4_D,
59 + BFD_RELOC_UBICOM32_LO7_CALLI,
60 + BFD_RELOC_UBICOM32_LO16_CALLI,
61 + BFD_RELOC_UBICOM32_GOT_HI24,
62 + BFD_RELOC_UBICOM32_GOT_LO7_S,
63 + BFD_RELOC_UBICOM32_GOT_LO7_2_S,
64 + BFD_RELOC_UBICOM32_GOT_LO7_4_S,
65 + BFD_RELOC_UBICOM32_GOT_LO7_D,
66 + BFD_RELOC_UBICOM32_GOT_LO7_2_D,
67 + BFD_RELOC_UBICOM32_GOT_LO7_4_D,
68 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_HI24,
69 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_S,
70 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_2_S,
71 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_4_S,
72 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_D,
73 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_2_D,
74 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_4_D,
75 + BFD_RELOC_UBICOM32_GOT_LO7_CALLI,
76 + BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_CALLI,
77 + BFD_RELOC_UBICOM32_FUNCDESC_VALUE,
78 + BFD_RELOC_UBICOM32_FUNCDESC,
79 + BFD_RELOC_UBICOM32_GOTOFFSET_LO,
80 + BFD_RELOC_UBICOM32_GOTOFFSET_HI,
81 + BFD_RELOC_UBICOM32_FUNCDESC_GOTOFFSET_LO,
82 + BFD_RELOC_UBICOM32_FUNCDESC_GOTOFFSET_HI,
83 +
84 /* These two relocations are used by the linker to determine which of
85 the entries in a C++ virtual function table are actually used. When
86 the --gc-sections option is given, the linker will zero out the entries
87 --- a/bfd/config.bfd
88 +++ b/bfd/config.bfd
89 @@ -1432,6 +1432,11 @@ case "${targ}" in
90 targ_underscore=yes
91 ;;
92
93 + ubicom32-*-*)
94 + targ_defvec=bfd_elf32_ubicom32_vec
95 + targ_selvecs=bfd_elf32_ubicom32fdpic_vec
96 + ;;
97 +
98 v850-*-*)
99 targ_defvec=bfd_elf32_v850_vec
100 ;;
101 --- a/bfd/configure
102 +++ b/bfd/configure
103 @@ -19743,6 +19743,8 @@ do
104 bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
105 bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
106 bfd_elf32_us_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;;
107 + bfd_elf32_ubicom32_vec) tb="$tb elf32-ubicom32.lo elf32.lo $elf" ;;
108 + bfd_elf32_ubicom32fdpic_vec) tb="$tb elf32-ubicom32.lo elf32.lo $elf" ;;
109 bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;;
110 bfd_elf32_vax_vec) tb="$tb elf32-vax.lo elf32.lo $elf" ;;
111 bfd_elf32_xstormy16_vec) tb="$tb elf32-xstormy16.lo elf32.lo $elf" ;;
112 --- a/bfd/configure.in
113 +++ b/bfd/configure.in
114 @@ -736,6 +736,8 @@ do
115 bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
116 bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
117 bfd_elf32_us_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;;
118 + bfd_elf32_ubicom32_vec) tb="$tb elf32-ubicom32.lo elf32.lo $elf" ;;
119 + bfd_elf32_ubicom32fdpic_vec) tb="$tb elf32-ubicom32.lo elf32.lo $elf" ;;
120 bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;;
121 bfd_elf32_vax_vec) tb="$tb elf32-vax.lo elf32.lo $elf" ;;
122 bfd_elf32_xstormy16_vec) tb="$tb elf32-xstormy16.lo elf32.lo $elf" ;;
123 --- /dev/null
124 +++ b/bfd/cpu-ubicom32.c
125 @@ -0,0 +1,126 @@
126 +/* BFD support for the Ubicom32 processor.
127 + Copyright (C) 2000 Free Software Foundation, Inc.
128 +
129 +This file is part of BFD, the Binary File Descriptor library.
130 +
131 +This program is free software; you can redistribute it and/or modify
132 +it under the terms of the GNU General Public License as published by
133 +the Free Software Foundation; either version 2 of the License, or
134 +(at your option) any later version.
135 +
136 +This program is distributed in the hope that it will be useful,
137 +but WITHOUT ANY WARRANTY; without even the implied warranty of
138 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
139 +GNU General Public License for more details.
140 +
141 +You should have received a copy of the GNU General Public License
142 +along with this program; if not, write to the Free Software
143 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
144 +
145 +#include "bfd.h"
146 +#include "sysdep.h"
147 +#include "libbfd.h"
148 +
149 +static const bfd_arch_info_type *
150 +ubicom32_arch_compatible (const bfd_arch_info_type *a,
151 + const bfd_arch_info_type *b)
152 +{
153 + if (a->arch != b->arch)
154 + return NULL;
155 +
156 + if (a->bits_per_word != b->bits_per_word)
157 + return NULL;
158 +
159 + if (a->mach > b->mach)
160 + return a;
161 +
162 + if (b->mach > a->mach)
163 + return b;
164 +
165 + if (b->mach == bfd_mach_ubicom32ver4 &&
166 + strcmp("ubicom32uclinux", b->printable_name) == 0) {
167 + return b;
168 + }
169 +
170 + return a;
171 +}
172 +
173 +const bfd_arch_info_type bfd_ubicom32_uclinux_arch =
174 +{
175 + 32, /* bits per word */
176 + 32, /* bits per address */
177 + 8, /* bits per byte */
178 + bfd_arch_ubicom32, /* architecture */
179 + bfd_mach_ubicom32ver4, /* machine */
180 + "ubicom32", /* architecture name */
181 + "ubicom32uclinux", /* printable name */
182 + 3, /* section align power */
183 + FALSE, /* the default ? */
184 + ubicom32_arch_compatible, /* architecture comparison fn */
185 + bfd_default_scan, /* string to architecture convert fn */
186 + NULL /* next in list */
187 +};
188 +
189 +const bfd_arch_info_type bfd_ubicom32_posix_arch =
190 +{
191 + 32, /* bits per word */
192 + 32, /* bits per address */
193 + 8, /* bits per byte */
194 + bfd_arch_ubicom32, /* architecture */
195 + bfd_mach_ubicom32ver4, /* machine */
196 + "ubicom32", /* architecture name */
197 + "ubicom32posix", /* printable name */
198 + 3, /* section align power */
199 + FALSE, /* the default ? */
200 + bfd_default_compatible, /* architecture comparison fn */
201 + bfd_default_scan, /* string to architecture convert fn */
202 + &bfd_ubicom32_uclinux_arch, /* next in list */
203 +};
204 +
205 +const bfd_arch_info_type bfd_ubicom32_ver4_arch =
206 +{
207 + 32, /* bits per word */
208 + 32, /* bits per address */
209 + 8, /* bits per byte */
210 + bfd_arch_ubicom32, /* architecture */
211 + bfd_mach_ubicom32ver4, /* machine */
212 + "ubicom32", /* architecture name */
213 + "ubicom32ver4", /* printable name */
214 + 3, /* section align power */
215 + FALSE, /* the default ? */
216 + ubicom32_arch_compatible, /* architecture comparison fn */
217 + bfd_default_scan, /* string to architecture convert fn */
218 + &bfd_ubicom32_posix_arch /* next in list */
219 +};
220 +
221 +const bfd_arch_info_type bfd_ubicom32_nonext_arch =
222 +{
223 + 32, /* bits per word */
224 + 32, /* bits per address */
225 + 8, /* bits per byte */
226 + bfd_arch_ubicom32, /* architecture */
227 + bfd_mach_ubicom32dsp, /* machine */
228 + "ubicom32", /* architecture name */
229 + "ubicom32dsp", /* printable name */
230 + 3, /* section align power */
231 + FALSE, /* the default ? */
232 + bfd_default_compatible, /* architecture comparison fn */
233 + bfd_default_scan, /* string to architecture convert fn */
234 + & bfd_ubicom32_ver4_arch /* next in list */
235 +};
236 +
237 +const bfd_arch_info_type bfd_ubicom32_arch =
238 +{
239 + 32, /* bits per word */
240 + 32, /* bits per address */
241 + 8, /* bits per byte */
242 + bfd_arch_ubicom32, /* architecture */
243 + bfd_mach_ubicom32, /* machine */
244 + "ubicom32", /* architecture name */
245 + "ubicom32", /* printable name */
246 + 3, /* section align power */
247 + TRUE, /* the default ? */
248 + bfd_default_compatible, /* architecture comparison fn */
249 + bfd_default_scan, /* string to architecture convert fn */
250 + & bfd_ubicom32_nonext_arch /* next in list */
251 +};
252 --- a/bfd/doc/archures.texi
253 +++ b/bfd/doc/archures.texi
254 @@ -303,6 +303,11 @@ enum bfd_architecture
255 bfd_arch_ip2k, /* Ubicom IP2K microcontrollers. */
256 #define bfd_mach_ip2022 1
257 #define bfd_mach_ip2022ext 2
258 + bfd_arch_ubicom32,
259 +#define bfd_mach_ubicom32 0
260 +#define bfd_mach_ubicom32dsp 1
261 +#define bfd_mach_ubicom32ver4 2
262 +#define bfd_mach_ubicom32posix 3
263 bfd_arch_iq2000, /* Vitesse IQ2000. */
264 #define bfd_mach_iq2000 1
265 #define bfd_mach_iq10 2
266 --- /dev/null
267 +++ b/bfd/elf32-ubicom32.c
268 @@ -0,0 +1,5008 @@
269 +/* Ubicom32 specific support for 32-bit ELF
270 + Copyright 2000 Free Software Foundation, Inc.
271 +
272 +This file is part of BFD, the Binary File Descriptor library.
273 +
274 +This program is free software; you can redistribute it and/or modify
275 +it under the terms of the GNU General Public License as published by
276 +the Free Software Foundation; either version 2 of the License, or
277 +(at your option) any later version.
278 +
279 +This program is distributed in the hope that it will be useful,
280 +but WITHOUT ANY WARRANTY; without even the implied warranty of
281 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
282 +GNU General Public License for more details.
283 +
284 +You should have received a copy of the GNU General Public License
285 +along with this program; if not, write to the Free Software
286 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
287 +
288 +#include <string.h>
289 +#include "bfd.h"
290 +#include "sysdep.h"
291 +#include "libbfd.h"
292 +#include "elf-bfd.h"
293 +#include "elf/ubicom32.h"
294 +#include "elf/dwarf2.h"
295 +
296 +/* Call offset = signed 24bit word offset
297 + => 26bit signed byte offset. */
298 +#define UBICOM32_CALL_MAX_POS_OFFS ((1 << 25) - 1)
299 +#define UBICOM32_CALL_MAX_NEG_OFFS (-(1 << 25))
300 +
301 +#define UNDEFINED_SYMBOL (~(bfd_vma)0)
302 +#define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
303 +
304 +#if 0
305 +#define DPRINTF(fmt, ...) { printf("DBG %4d:" fmt, __LINE__, __VA_ARGS__); fflush(stdout); }
306 +#else
307 +#define DPRINTF(fmt, ...) {}
308 +#endif
309 +struct debugLineInfo {
310 + unsigned int startOffset;
311 + unsigned int length;
312 + char *sectionName;
313 + unsigned int startRelocIndex;
314 + unsigned int endRelocIndex;
315 + unsigned int discard;
316 +};
317 +
318 +struct debugLineInfoHeader {
319 + unsigned int numEntries;
320 + struct debugLineInfo linfo[1];
321 +};
322 +
323 +/* we want RELA relocations, not REL */
324 +#undef USE_REL
325 +#define USE_RELA
326 +
327 +static bfd_reloc_status_type ubicom32_elf_generic_reloc
328 + PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol, PTR data,
329 + asection *input_section, bfd *output_bfd, char **error_message));
330 +static bfd_reloc_status_type ubicom32_elf_relocate_hi16
331 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
332 +static bfd_reloc_status_type ubicom32_elf_relocate_lo16
333 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
334 +static bfd_reloc_status_type ubicom32_elf_relocate_hi24
335 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
336 +static bfd_reloc_status_type ubicom32_elf_relocate_lo7_s
337 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
338 +static bfd_reloc_status_type ubicom32_elf_relocate_lo7_2_s
339 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
340 +static bfd_reloc_status_type ubicom32_elf_relocate_lo7_4_s
341 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
342 +static bfd_reloc_status_type ubicom32_elf_relocate_lo7_d
343 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
344 +static bfd_reloc_status_type ubicom32_elf_relocate_lo7_2_d
345 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
346 +static bfd_reloc_status_type ubicom32_elf_relocate_lo7_4_d
347 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
348 +static bfd_reloc_status_type ubicom32_elf_relocate_pcrel24
349 + PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
350 +static bfd_reloc_status_type ubicom32_elf_relocate_lo_calli
351 + PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma, int));
352 +
353 +static void ubicom32_info_to_howto_rela
354 + PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
355 +
356 +static reloc_howto_type * ubicom32_reloc_type_lookup
357 + PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
358 +
359 +static bfd_vma symbol_value
360 + PARAMS ((bfd *, Elf_Internal_Rela *));
361 +static Elf_Internal_Shdr *file_symtab_hdr
362 + PARAMS ((bfd *));
363 +static Elf_Internal_Sym *file_isymbuf
364 + PARAMS ((bfd *));
365 +static Elf_Internal_Rela *section_relocs
366 + PARAMS ((bfd *, asection *));
367 +static bfd_byte *section_contents
368 + PARAMS ((bfd *, asection *));
369 +static bfd_boolean ubicom32_elf_relax_section
370 + PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
371 +static bfd_boolean ubicom32_elf_relax_calli
372 + PARAMS ((bfd *, asection *, bfd_boolean *));
373 +static bfd_boolean ubicom32_elf_relax_delete_bytes
374 + PARAMS ((bfd *, asection *, bfd_vma, int));
375 +static void adjust_sec_relocations
376 + PARAMS ((bfd *, asection *, asection *, bfd_vma, int));
377 +static void adjust_all_relocations
378 + PARAMS ((bfd *, asection *, bfd_vma, int));
379 +
380 +static bfd_reloc_status_type ubicom32_final_link_relocate
381 + PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
382 + Elf_Internal_Rela *, bfd_vma));
383 +static bfd_boolean ubicom32_elf_relocate_section
384 + PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
385 + bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *,
386 + asection **));
387 +
388 +static bfd_boolean ubicom32_elf_gc_sweep_hook
389 + PARAMS ((bfd *, struct bfd_link_info *, asection *, const
390 + Elf_Internal_Rela *));
391 +static asection * ubicom32_elf_gc_mark_hook
392 + PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct
393 + elf_link_hash_entry *, Elf_Internal_Sym *));
394 +static bfd_boolean ubicom32_elf_check_relocs
395 + PARAMS ((bfd *, struct bfd_link_info *, asection *,
396 + const Elf_Internal_Rela *));
397 +extern bfd_boolean ubicom32_elf_discard_info
398 + PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *));
399 +
400 +static bfd_boolean ubicom32_elf_object_p PARAMS ((bfd *));
401 +static bfd_boolean ubicom32_elf_set_private_flags PARAMS ((bfd *, flagword));
402 +static bfd_boolean ubicom32_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
403 +static bfd_boolean ubicom32_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
404 +static bfd_boolean ubicom32_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
405 +
406 +//static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
407 +
408 +//static long read_signed_leb128 (bfd *, char *, unsigned int *);
409 +
410 +/* read dwarf information from a buffer */
411 +
412 +#define UBICOM32_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \
413 + HOWTO(t, /* type */ \
414 + rs, /* rightshift */ \
415 + s, /* size (0 = byte, 1 = short, 2 = long) */ \
416 + bs, /* bitsize */ \
417 + pr, /* pc_relative */ \
418 + bp, /* bitpos */ \
419 + complain_overflow_bitfield, /* complain_on_overflow */ \
420 + ubicom32_elf_generic_reloc, /* special_function */ \
421 + name, /* name */ \
422 + FALSE, /* partial_inplace */ \
423 + sm, /* src_mask */ \
424 + dm, /* dst_mask */ \
425 + pr) /* pcrel_offset */
426 +
427 +/* Special Note: For addresses, we must always zero out the top byte of a
428 + address because the harvard address space is represented as
429 + a single virtual address space that uses the top byte to denote
430 + whether the address belongs in the data or program space. This is
431 + done to accomodate GDB which cannot handle program and data addresses
432 + overlapping. */
433 +
434 +static reloc_howto_type ubicom32_elf_howto_table [] =
435 +{
436 + /* This reloc does nothing. */
437 + UBICOM32_HOWTO (R_UBICOM32_NONE, 0, 2, 32, FALSE, 0, "R_UBICOM32_NONE", 0, 0),
438 +
439 + /* A 16 bit absolute relocation. */
440 + UBICOM32_HOWTO (R_UBICOM32_16, 0, 1, 16, FALSE, 0, "R_UBICOM32_16", 0, 0xffff),
441 +
442 + /* A 32 bit absolute relocation. Must zero top byte of virtual address. */
443 + UBICOM32_HOWTO (R_UBICOM32_32, 0, 2, 32, FALSE, 0, "R_UBICOM32_32", 0, 0xffffffff),
444 +
445 + /* A 16 bit indirect relocation, low 16 bits of 32 */
446 + UBICOM32_HOWTO (R_UBICOM32_LO16, 0, 2, 16, FALSE, 0, "R_UBICOM32_LO16", 0x0, 0x0000ffff),
447 +
448 + /* A 16 bit indirect relocation, high 16 bits of 32 - must zero top byte of virtual address */
449 + UBICOM32_HOWTO (R_UBICOM32_HI16, 0, 2, 16, FALSE, 0, "R_UBICOM32_HI16", 0x0, 0x0000ffff),
450 +
451 + /* A 21 bit relative relocation. */
452 + UBICOM32_HOWTO (R_UBICOM32_21_PCREL, 2, 2, 21, TRUE, 0, "R_UBICOM32_21_PCREL", 0x0, 0x001fffff),
453 +
454 + /* A 24 bit relative relocation. */
455 + UBICOM32_HOWTO (R_UBICOM32_24_PCREL, 2, 2, 24, TRUE, 0, "R_UBICOM32_24_PCREL", 0x0, 0x071fffff),
456 +
457 + /* A 24 bit indirect relocation, bits 31:7 - assume top byte zero. */
458 + UBICOM32_HOWTO (R_UBICOM32_HI24, 7, 2, 24, FALSE, 0, "R_UBICOM32_HI24", 0x0, 0x0001ffff),
459 +
460 + /* A source operand low 7 bit indirect relocation. */
461 + UBICOM32_HOWTO (R_UBICOM32_LO7_S, 0, 2, 7, FALSE, 0, "R_UBICOM32_LO7_S", 0x0, 0x0000031f),
462 +
463 + /* A source operand low 7 bit .2 insn indirect relocation. */
464 + UBICOM32_HOWTO (R_UBICOM32_LO7_2_S, 1, 2, 7, FALSE, 0, "R_UBICOM32_LO7_2_S", 0x0, 0x0000031f),
465 +
466 + /* A source operand low 7 bit .4 insn indirect relocation. */
467 + UBICOM32_HOWTO (R_UBICOM32_LO7_4_S, 2, 2, 7, FALSE, 0, "R_UBICOM32_LO7_4_S", 0x0, 0x0000031f),
468 +
469 + /* A destination operand low 7 bit indirect relocation. */
470 + UBICOM32_HOWTO (R_UBICOM32_LO7_D, 0, 2, 7, FALSE, 0, "R_UBICOM32_LO7_D", 0x0, 0x031f0000),
471 +
472 + /* A destination operand low 7 bit .2 insn indirect relocation. */
473 + UBICOM32_HOWTO (R_UBICOM32_LO7_2_D, 1, 2, 7, FALSE, 0, "R_UBICOM32_LO7_2_D", 0x0, 0x031f0000),
474 +
475 + /* A destination operand low 7 bit .2 insn indirect relocation. */
476 + UBICOM32_HOWTO (R_UBICOM32_LO7_4_D, 2, 2, 7, FALSE, 0, "R_UBICOM32_LO7_4_D", 0x0, 0x031f0000),
477 +
478 + /* A 32 bit absolute relocation in debug section. Must retain top byte of virtual address. */
479 + UBICOM32_HOWTO (R_UBICOM32_32_HARVARD, 0, 2, 32, FALSE, 0, "R_UBICOM32_32_HARVARD", 0, 0xffffffff),
480 +
481 + /* A calli offset operand low 7 bit .4 insn indirect relocation. */
482 + UBICOM32_HOWTO (R_UBICOM32_LO7_CALLI, 2, 2, 7, FALSE, 0, "R_UBICOM32_LO7_CALLI", 0x0, 0x071f071f),
483 +
484 + /* A calli offset operand low 18 bit .4 insn indirect relocation. */
485 + UBICOM32_HOWTO (R_UBICOM32_LO16_CALLI, 2, 2, 16, FALSE, 0, "R_UBICOM32_LO16_CALLI", 0x0, 0x071f071f),
486 +
487 + /* A 24 bit indirect relocation, bits 31:7 - assume top byte zero. */
488 + UBICOM32_HOWTO (R_UBICOM32_GOT_HI24, 7, 2, 24, FALSE, 0, "R_UBICOM32_GOT_HI24", 0x0, 0x0001ffff),
489 +
490 + /* A source operand low 7 bit indirect relocation. */
491 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_S, 0, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_S", 0x0, 0x0000031f),
492 +
493 + /* A source operand low 7 bit .2 insn indirect relocation. */
494 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_2_S, 1, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_2_S", 0x0, 0x0000031f),
495 +
496 + /* A source operand low 7 bit .4 insn indirect relocation. */
497 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_4_S, 2, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_4_S", 0x0, 0x0000031f),
498 +
499 + /* A destination operand low 7 bit indirect relocation. */
500 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_D, 0, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_D", 0x0, 0x031f0000),
501 +
502 + /* A destination operand low 7 bit .2 insn indirect relocation. */
503 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_2_D, 1, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_2_D", 0x0, 0x031f0000),
504 +
505 + /* A destination operand low 7 bit .2 insn indirect relocation. */
506 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_4_D, 2, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_4_D", 0x0, 0x031f0000),
507 +
508 + /* A 24 bit indirect relocation, bits 31:7 - assume top byte zero. */
509 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_HI24, 7, 2, 24, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_HI24", 0x0, 0x0001ffff),
510 +
511 + /* A source operand low 7 bit indirect relocation. */
512 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_S, 0, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_S", 0x0, 0x0000031f),
513 +
514 + /* A source operand low 7 bit .2 insn indirect relocation. */
515 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_2_S, 1, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_2_S", 0x0, 0x0000031f),
516 +
517 + /* A source operand low 7 bit .4 insn indirect relocation. */
518 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_4_S, 2, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_4_S", 0x0, 0x0000031f),
519 +
520 + /* A destination operand low 7 bit indirect relocation. */
521 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_D, 0, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_D", 0x0, 0x031f0000),
522 +
523 + /* A destination operand low 7 bit .2 insn indirect relocation. */
524 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_2_D, 1, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_2_D", 0x0, 0x031f0000),
525 +
526 + /* A destination operand low 7 bit .2 insn indirect relocation. */
527 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_4_D, 2, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_4_D", 0x0, 0x031f0000),
528 +
529 + /* A calli offset operand low 7 bit .4 insn indirect relocation. */
530 + UBICOM32_HOWTO (R_UBICOM32_GOT_LO7_CALLI, 2, 2, 7, FALSE, 0, "R_UBICOM32_GOT_LO7_CALLI", 0x0, 0x071f071f),
531 +
532 + /* A calli offset operand low 7 bit .4 insn indirect relocation. */
533 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOT_LO7_CALLI, 2, 2, 7, FALSE, 0, "R_UBICOM32_FUNCDESC_GOT_LO7_CALLI", 0x0, 0x071f071f),
534 +
535 + /* A 32 bit absolute relocation. Must zero top byte of virtual address. */
536 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_VALUE, 0, 2, 32, FALSE, 0, "R_UBICOM32_FUNCDESC_VALUE", 0, 0xffffffff),
537 +
538 + /* A 32 bit absolute relocation. Must zero top byte of virtual address. */
539 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC, 0, 2, 32, FALSE, 0, "R_UBICOM32_FUNCDESC", 0, 0xffffffff),
540 +
541 + /* A 16 bit absolute relocation. */
542 + UBICOM32_HOWTO (R_UBICOM32_GOTOFFSET_LO, 0, 1, 16, FALSE, 0, "R_UBICOM32_GOTOFFSET_LO", 0, 0xffff),
543 +
544 + /* A 16 bit absolute relocation. */
545 + UBICOM32_HOWTO (R_UBICOM32_GOTOFFSET_HI, 0, 1, 16, FALSE, 0, "R_UBICOM32_GOTOFFSET_HI", 0, 0xffff),
546 +
547 + /* A 16 bit absolute relocation. */
548 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOTOFFSET_LO, 0, 1, 16, FALSE, 0, "R_UBICOM32_FUNCDESC_GOTOFFSET_LO", 0, 0xffff),
549 +
550 + /* A 16 bit absolute relocation. */
551 + UBICOM32_HOWTO (R_UBICOM32_FUNCDESC_GOTOFFSET_HI, 0, 1, 16, FALSE, 0, "R_UBICOM32_FUNCDESC_GOTOFFSET_HI", 0, 0xffff),
552 +};
553 +
554 +/* GNU extension to record C++ vtable hierarchy */
555 +static reloc_howto_type ubicom32_elf_vtinherit_howto =
556 + HOWTO (R_UBICOM32_GNU_VTINHERIT, /* type */
557 + 0, /* rightshift */
558 + 2, /* size (0 = byte, 1 = short, 2 = long) */
559 + 0, /* bitsize */
560 + FALSE, /* pc_relative */
561 + 0, /* bitpos */
562 + complain_overflow_dont, /* complain_on_overflow */
563 + NULL, /* special_function */
564 + "R_UBICOM32_GNU_VTINHERIT", /* name */
565 + FALSE, /* partial_inplace */
566 + 0, /* src_mask */
567 + 0, /* dst_mask */
568 + FALSE); /* pcrel_offset */
569 +
570 + /* GNU extension to record C++ vtable member usage */
571 +static reloc_howto_type ubicom32_elf_vtentry_howto =
572 + HOWTO (R_UBICOM32_GNU_VTENTRY, /* type */
573 + 0, /* rightshift */
574 + 2, /* size (0 = byte, 1 = short, 2 = long) */
575 + 0, /* bitsize */
576 + FALSE, /* pc_relative */
577 + 0, /* bitpos */
578 + complain_overflow_dont, /* complain_on_overflow */
579 + _bfd_elf_rel_vtable_reloc_fn, /* special_function */
580 + "R_UBICOM32_GNU_VTENTRY", /* name */
581 + FALSE, /* partial_inplace */
582 + 0, /* src_mask */
583 + 0, /* dst_mask */
584 + FALSE); /* pcrel_offset */
585 +
586 +extern const bfd_target bfd_elf32_ubicom32fdpic_vec;
587 +#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_ubicom32fdpic_vec)
588 +\f
589 +/* Relocation helpers */
590 +bfd_reloc_status_type
591 +ubicom32_elf_generic_reloc (abfd,
592 + reloc_entry,
593 + symbol,
594 + data,
595 + input_section,
596 + output_bfd,
597 + error_message)
598 + bfd *abfd ATTRIBUTE_UNUSED;
599 + arelent *reloc_entry;
600 + asymbol *symbol;
601 + PTR data ATTRIBUTE_UNUSED;
602 + asection *input_section;
603 + bfd *output_bfd;
604 + char **error_message ATTRIBUTE_UNUSED;
605 +{
606 + if (output_bfd != (bfd *) NULL
607 + && (symbol->flags & BSF_SECTION_SYM) == 0
608 + && (! reloc_entry->howto->partial_inplace
609 + || reloc_entry->addend == 0))
610 + {
611 + reloc_entry->address += input_section->output_offset;
612 + symbol = *reloc_entry->sym_ptr_ptr;
613 +
614 + if((symbol->flags & BSF_OBJECT) == 0)
615 + {
616 + reloc_entry->addend -= symbol->value;
617 + }
618 + return bfd_reloc_ok;
619 + }
620 +
621 + return bfd_reloc_continue;
622 +}
623 +
624 +bfd_reloc_status_type
625 +ubicom32_elf_relocate_hi16 (input_bfd, relhi, contents, value)
626 + bfd *input_bfd;
627 + Elf_Internal_Rela *relhi;
628 + bfd_byte *contents;
629 + bfd_vma value;
630 +{
631 + bfd_vma insn;
632 +
633 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
634 +
635 + value += relhi->r_addend;
636 + value >>= 16;
637 + value &= 0xffff; /* take off top byte of virtual address */
638 + insn = ((insn & ~0xFFFF) | value);
639 +
640 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
641 + return bfd_reloc_ok;
642 +}
643 +
644 +bfd_reloc_status_type
645 +ubicom32_elf_relocate_lo16 (input_bfd, relhi, contents, value)
646 + bfd *input_bfd;
647 + Elf_Internal_Rela *relhi;
648 + bfd_byte *contents;
649 + bfd_vma value;
650 +{
651 + bfd_vma insn;
652 +
653 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
654 +
655 + value += relhi->r_addend;
656 + value &= 0xFFFF;
657 + insn = ((insn & ~0xFFFF) | value);
658 +
659 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
660 + return bfd_reloc_ok;
661 +}
662 +
663 +bfd_reloc_status_type
664 +ubicom32_elf_relocate_hi24 (input_bfd, relhi, contents, value)
665 + bfd *input_bfd;
666 + Elf_Internal_Rela *relhi;
667 + bfd_byte *contents;
668 + bfd_vma value;
669 +{
670 + bfd_vma insn;
671 +
672 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
673 +
674 + value += relhi->r_addend;
675 + if (value & 0x80000000) {
676 + fprintf (stderr,"@@@: You are trying load the address of something at %08lx\n This is >= 0x80000000 and the moveai instruction does not support it!\n",value);
677 + }
678 + value &= 0x7fffffff; /* zero off top bit of virtual address */
679 + value >>= 7;
680 + insn = (insn & ~0x071FFFFF);
681 +
682 + insn |= (value & 0x1FFFFF);
683 + insn |= (value & 0xe00000) << 3;
684 +
685 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
686 + return bfd_reloc_ok;
687 +}
688 +
689 +bfd_reloc_status_type
690 +ubicom32_elf_relocate_lo7_s (input_bfd, relhi, contents, value)
691 + bfd *input_bfd;
692 + Elf_Internal_Rela *relhi;
693 + bfd_byte *contents;
694 + bfd_vma value;
695 +{
696 + bfd_vma insn;
697 + bfd_vma top;
698 + bfd_vma bottom;
699 +
700 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
701 +
702 + value += relhi->r_addend;
703 + value &= 0x7f;
704 +
705 + /* must split up value into top 2 bits and bottom 5 bits */
706 + top = value >> 5;
707 + bottom = value & 0x1f;
708 + insn = ((insn & ~0x31f) | (top << 8) | bottom);
709 +
710 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
711 + return bfd_reloc_ok;
712 +}
713 +
714 +bfd_reloc_status_type
715 +ubicom32_elf_relocate_lo7_2_s (input_bfd, relhi, contents, value)
716 + bfd *input_bfd;
717 + Elf_Internal_Rela *relhi;
718 + bfd_byte *contents;
719 + bfd_vma value;
720 +{
721 + bfd_vma insn;
722 + bfd_vma top;
723 + bfd_vma bottom;
724 +
725 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
726 +
727 + value += relhi->r_addend;
728 + value &= 0x7f;
729 + value >>= 1; /* must shift by 1 because this is .2 insn */
730 +
731 + /* must split up value into top 2 bits and bottom 5 bits */
732 + top = value >> 5;
733 + bottom = value & 0x1f;
734 + insn = ((insn & ~0x31f) | (top << 8) | bottom);
735 +
736 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
737 + return bfd_reloc_ok;
738 +}
739 +
740 +bfd_reloc_status_type
741 +ubicom32_elf_relocate_lo7_4_s (input_bfd, relhi, contents, value)
742 + bfd *input_bfd;
743 + Elf_Internal_Rela *relhi;
744 + bfd_byte *contents;
745 + bfd_vma value;
746 +{
747 + bfd_vma insn;
748 + bfd_vma top;
749 + bfd_vma bottom;
750 +
751 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
752 +
753 + value += relhi->r_addend;
754 + value &= 0x7f;
755 + value >>= 2; /* must shift by 1 because this is .4 insn */
756 +
757 + /* must split up value into top 2 bits and bottom 5 bits */
758 + top = value >> 5;
759 + bottom = value & 0x1f;
760 + insn = ((insn & ~0x31f) | (top << 8) | bottom);
761 +
762 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
763 + return bfd_reloc_ok;
764 +}
765 +
766 +bfd_reloc_status_type
767 +ubicom32_elf_relocate_lo7_d (input_bfd, relhi, contents, value)
768 + bfd *input_bfd;
769 + Elf_Internal_Rela *relhi;
770 + bfd_byte *contents;
771 + bfd_vma value;
772 +{
773 + bfd_vma insn;
774 + bfd_vma top;
775 + bfd_vma bottom;
776 +
777 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
778 +
779 + value += relhi->r_addend;
780 + value &= 0x7f;
781 +
782 + /* must split up value into top 2 bits and bottom 5 bits */
783 + top = value >> 5;
784 + bottom = value & 0x1f;
785 + insn = ((insn & ~0x031f0000) | (top << 24) | (bottom << 16));
786 +
787 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
788 + return bfd_reloc_ok;
789 +}
790 +
791 +bfd_reloc_status_type
792 +ubicom32_elf_relocate_lo7_2_d (input_bfd, relhi, contents, value)
793 + bfd *input_bfd;
794 + Elf_Internal_Rela *relhi;
795 + bfd_byte *contents;
796 + bfd_vma value;
797 +{
798 + bfd_vma insn;
799 + bfd_vma top;
800 + bfd_vma bottom;
801 +
802 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
803 +
804 + value += relhi->r_addend;
805 + value &= 0x7f;
806 + value >>= 1; /* must shift by 1 because this is for a .2 insn */
807 +
808 + /* must split up value into top 2 bits and bottom 5 bits */
809 + top = value >> 5;
810 + bottom = value & 0x1f;
811 + insn = ((insn & ~0x031f0000) | (top << 24) | (bottom << 16));
812 +
813 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
814 + return bfd_reloc_ok;
815 +}
816 +
817 +bfd_reloc_status_type
818 +ubicom32_elf_relocate_lo7_4_d (input_bfd, relhi, contents, value)
819 + bfd *input_bfd;
820 + Elf_Internal_Rela *relhi;
821 + bfd_byte *contents;
822 + bfd_vma value;
823 +{
824 + bfd_vma insn;
825 + bfd_vma top;
826 + bfd_vma bottom;
827 +
828 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
829 +
830 + value += relhi->r_addend;
831 + value &= 0x7f;
832 + value >>= 2; /* must shift by 2 because this is for a .4 insn */
833 +
834 + /* must split up value into top 2 bits and bottom 5 bits */
835 + top = value >> 5;
836 + bottom = value & 0x1f;
837 + insn = ((insn & ~0x031f0000) | (top << 24) | (bottom << 16));
838 +
839 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
840 + return bfd_reloc_ok;
841 +}
842 +
843 +/* Perform the relocation for call instructions */
844 +static bfd_reloc_status_type
845 +ubicom32_elf_relocate_pcrel24 (input_bfd, input_section, rello, contents, value)
846 + bfd *input_bfd;
847 + asection *input_section;
848 + Elf_Internal_Rela *rello;
849 + bfd_byte *contents;
850 + bfd_vma value;
851 +{
852 + bfd_vma insn;
853 + bfd_vma value_top;
854 + bfd_vma value_bottom;
855 +
856 + /* Grab the instruction */
857 + insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
858 +
859 + value -= input_section->output_section->vma + input_section->output_offset;
860 + value -= rello->r_offset;
861 + value += rello->r_addend;
862 +
863 + /* insn uses bottom 24 bits of relocation value times 4 */
864 + if (value & 0x03)
865 + return bfd_reloc_dangerous;
866 +
867 + value = (value & 0x3ffffff) >> 2;
868 +
869 + if ((long) value > 0xffffff)
870 + return bfd_reloc_overflow;
871 +
872 + value_top = (value >> 21) << 24;
873 + value_bottom = value & 0x1fffff;
874 +
875 + insn = insn & 0xf8e00000;
876 + insn = insn | value_top | value_bottom;
877 +
878 + bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
879 +
880 + return bfd_reloc_ok;
881 +}
882 +
883 +static bfd_reloc_status_type
884 +ubicom32_elf_relocate_gotoffset_lo (input_bfd, input_section, rello, contents, value)
885 + bfd *input_bfd;
886 + asection *input_section;
887 + Elf_Internal_Rela *rello;
888 + bfd_byte *contents;
889 + bfd_vma value;
890 +{
891 + bfd_vma insn;
892 +
893 + /* Grab the instruction */
894 + insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
895 +
896 + /* Truncte to 16 and store. */
897 + value &= 0xffff;
898 +
899 + insn = (insn & 0xffff0000) | value;
900 +
901 + /* output it. */
902 + bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
903 +}
904 +
905 +static bfd_reloc_status_type
906 +ubicom32_elf_relocate_funcdesc_gotoffset_lo (input_bfd, input_section, rello, contents, value)
907 + bfd *input_bfd;
908 + asection *input_section;
909 + Elf_Internal_Rela *rello;
910 + bfd_byte *contents;
911 + bfd_vma value;
912 +{
913 + bfd_vma insn;
914 +
915 + /* Grab the instruction */
916 + insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
917 +
918 + /* Truncte to 16 and store. */
919 + value &= 0xffff;
920 +
921 + insn = (insn & 0xffff0000) | value;
922 +
923 + /* output it. */
924 + bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
925 +}
926 +
927 +static bfd_reloc_status_type
928 +ubicom32_elf_relocate_funcdesc (input_bfd, input_section, rello, contents, value)
929 + bfd *input_bfd;
930 + asection *input_section;
931 + Elf_Internal_Rela *rello;
932 + bfd_byte *contents;
933 + bfd_vma value;
934 +{
935 + bfd_vma insn;
936 +
937 + /* Grab the instruction */
938 + insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
939 +
940 + /* Truncte to 16 and store. */
941 + value &= 0xffff;
942 +
943 + insn = (insn & 0xffff0000) | value;
944 +
945 + /* output it. */
946 + bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
947 +}
948 +
949 +bfd_reloc_status_type
950 +ubicom32_elf_relocate_lo_calli (input_bfd, relhi, contents, value, bits)
951 + bfd *input_bfd;
952 + Elf_Internal_Rela *relhi;
953 + bfd_byte *contents;
954 + bfd_vma value;
955 + int bits;
956 +{
957 + bfd_vma insn;
958 +
959 + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
960 +
961 + value += relhi->r_addend;
962 + value &= (1 << bits) - 1;
963 + value >>= 2; /* must shift by 2 because this is .4 insn */
964 +
965 + /* must split up value into top 2 bits and bottom 5 bits */
966 + insn &= ~0x071f071f;
967 + insn |= (value & 0x1f) << 0;
968 + value >>= 5;
969 + insn |= (value & 0x07) << 8;
970 + value >>= 3;
971 + insn |= (value & 0x1f) << 16;
972 + value >>= 5;
973 + insn |= (value & 0x07) << 24;
974 +
975 + bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
976 + return bfd_reloc_ok;
977 +}
978 +
979 +\f
980 +/* Set the howto pointer for a UBICOM32 ELF reloc. */
981 +
982 +static void
983 +ubicom32_info_to_howto_rela (abfd, cache_ptr, dst)
984 + bfd * abfd ATTRIBUTE_UNUSED;
985 + arelent * cache_ptr;
986 + Elf_Internal_Rela * dst;
987 +{
988 + unsigned int r_type;
989 +
990 + r_type = ELF32_R_TYPE (dst->r_info);
991 + switch (r_type)
992 + {
993 + case R_UBICOM32_GNU_VTINHERIT:
994 + cache_ptr->howto = &ubicom32_elf_vtinherit_howto;
995 + break;
996 +
997 + case R_UBICOM32_GNU_VTENTRY:
998 + cache_ptr->howto = &ubicom32_elf_vtentry_howto;
999 + break;
1000 +
1001 + default:
1002 + cache_ptr->howto = &ubicom32_elf_howto_table[r_type];
1003 + break;
1004 + }
1005 +}
1006 +
1007 +\f
1008 +static reloc_howto_type *
1009 +ubicom32_reloc_type_lookup (abfd, code)
1010 + bfd * abfd ATTRIBUTE_UNUSED;
1011 + bfd_reloc_code_real_type code;
1012 +{
1013 + switch (code)
1014 + {
1015 + case BFD_RELOC_NONE:
1016 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_NONE];
1017 +
1018 + case BFD_RELOC_16:
1019 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_16];
1020 +
1021 + case BFD_RELOC_32:
1022 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_32];
1023 +
1024 + case BFD_RELOC_LO16:
1025 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO16];
1026 +
1027 + case BFD_RELOC_HI16:
1028 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_HI16];
1029 +
1030 + case BFD_RELOC_UBICOM32_HI24:
1031 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_HI24];
1032 +
1033 + case BFD_RELOC_UBICOM32_LO7_S:
1034 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_S];
1035 +
1036 + case BFD_RELOC_UBICOM32_LO7_2_S:
1037 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_2_S];
1038 +
1039 + case BFD_RELOC_UBICOM32_LO7_4_S:
1040 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_4_S];
1041 +
1042 + case BFD_RELOC_UBICOM32_LO7_D:
1043 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_D];
1044 +
1045 + case BFD_RELOC_UBICOM32_LO7_2_D:
1046 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_2_D];
1047 +
1048 + case BFD_RELOC_UBICOM32_LO7_4_D:
1049 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_4_D];
1050 +
1051 + case BFD_RELOC_UBICOM32_21_PCREL:
1052 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_21_PCREL];
1053 +
1054 + case BFD_RELOC_UBICOM32_24_PCREL:
1055 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_24_PCREL];
1056 +
1057 + case BFD_RELOC_UBICOM32_GOT_HI24:
1058 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_HI24];
1059 +
1060 + case BFD_RELOC_UBICOM32_GOT_LO7_S:
1061 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_S];
1062 +
1063 + case BFD_RELOC_UBICOM32_GOT_LO7_2_S:
1064 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_2_S];
1065 +
1066 + case BFD_RELOC_UBICOM32_GOT_LO7_4_S:
1067 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_4_S];
1068 +
1069 + case BFD_RELOC_UBICOM32_GOT_LO7_D:
1070 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_D];
1071 +
1072 + case BFD_RELOC_UBICOM32_GOT_LO7_2_D:
1073 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_2_D];
1074 +
1075 + case BFD_RELOC_UBICOM32_GOT_LO7_4_D:
1076 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_4_D];
1077 +
1078 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_HI24:
1079 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_HI24];
1080 +
1081 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_S:
1082 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_S];
1083 +
1084 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_2_S:
1085 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_2_S];
1086 +
1087 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_4_S:
1088 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_4_S];
1089 +
1090 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_D:
1091 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_D];
1092 +
1093 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_2_D:
1094 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_2_D];
1095 +
1096 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_4_D:
1097 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_4_D];
1098 +
1099 + case BFD_RELOC_UBICOM32_LO7_CALLI:
1100 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO7_CALLI];
1101 +
1102 + case BFD_RELOC_UBICOM32_GOT_LO7_CALLI:
1103 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOT_LO7_CALLI];
1104 +
1105 + case BFD_RELOC_UBICOM32_FUNCDESC_GOT_LO7_CALLI:
1106 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOT_LO7_CALLI];
1107 +
1108 + case BFD_RELOC_UBICOM32_LO16_CALLI:
1109 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_LO16_CALLI];
1110 +
1111 + case BFD_RELOC_UBICOM32_FUNCDESC_VALUE:
1112 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_VALUE];
1113 +
1114 + case BFD_RELOC_UBICOM32_FUNCDESC:
1115 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC];
1116 +
1117 + case BFD_RELOC_UBICOM32_GOTOFFSET_LO:
1118 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOTOFFSET_LO];
1119 +
1120 + case BFD_RELOC_UBICOM32_GOTOFFSET_HI:
1121 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_GOTOFFSET_HI];
1122 +
1123 + case BFD_RELOC_UBICOM32_FUNCDESC_GOTOFFSET_LO:
1124 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOTOFFSET_LO];
1125 +
1126 + case BFD_RELOC_UBICOM32_FUNCDESC_GOTOFFSET_HI:
1127 + return &ubicom32_elf_howto_table[(int)R_UBICOM32_FUNCDESC_GOTOFFSET_HI];
1128 +
1129 + case BFD_RELOC_VTABLE_INHERIT:
1130 + return &ubicom32_elf_vtinherit_howto;
1131 +
1132 + case BFD_RELOC_VTABLE_ENTRY:
1133 + return &ubicom32_elf_vtentry_howto;
1134 +
1135 + default:
1136 + /* Pacify gcc -Wall. */
1137 + return NULL;
1138 + }
1139 +
1140 + return NULL;
1141 +}
1142 +
1143 +static reloc_howto_type *
1144 +ubicom32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1145 + const char *r_name)
1146 +{
1147 + unsigned int i;
1148 +
1149 + for (i = 0;
1150 + i < (sizeof (ubicom32_elf_howto_table)
1151 + / sizeof (ubicom32_elf_howto_table[0]));
1152 + i++)
1153 + if (ubicom32_elf_howto_table[i].name != NULL
1154 + && strcasecmp (ubicom32_elf_howto_table[i].name, r_name) == 0)
1155 + return &ubicom32_elf_howto_table[i];
1156 +
1157 + return NULL;
1158 +}
1159 +
1160 +/* Return the value of the symbol associated with the relocation IREL. */
1161 +
1162 +static bfd_vma
1163 +symbol_value (abfd, irel)
1164 + bfd *abfd;
1165 + Elf_Internal_Rela *irel;
1166 +{
1167 + Elf_Internal_Shdr *symtab_hdr = file_symtab_hdr (abfd);
1168 + Elf_Internal_Sym *isymbuf = file_isymbuf (abfd);
1169 +
1170 + if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1171 + {
1172 + Elf_Internal_Sym *isym;
1173 + asection *sym_sec;
1174 +
1175 + isym = isymbuf + ELF32_R_SYM (irel->r_info);
1176 + if (isym->st_shndx == SHN_UNDEF)
1177 + sym_sec = bfd_und_section_ptr;
1178 + else if (isym->st_shndx == SHN_ABS)
1179 + sym_sec = bfd_abs_section_ptr;
1180 + else if (isym->st_shndx == SHN_COMMON)
1181 + sym_sec = bfd_com_section_ptr;
1182 + else
1183 + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1184 +
1185 + return isym->st_value + BASEADDR (sym_sec);
1186 + }
1187 + else
1188 + {
1189 + unsigned long indx;
1190 + struct elf_link_hash_entry *h;
1191 +
1192 + indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1193 + h = elf_sym_hashes (abfd)[indx];
1194 + BFD_ASSERT (h != NULL);
1195 +
1196 + if (h->root.type != bfd_link_hash_defined
1197 + && h->root.type != bfd_link_hash_defweak)
1198 + return UNDEFINED_SYMBOL;
1199 +
1200 + return (h->root.u.def.value + BASEADDR (h->root.u.def.section));
1201 + }
1202 +}
1203 +
1204 +
1205 +static Elf_Internal_Shdr *
1206 +file_symtab_hdr (abfd)
1207 + bfd *abfd;
1208 +{
1209 + return &elf_tdata (abfd)->symtab_hdr;
1210 +}
1211 +
1212 +static Elf_Internal_Sym *
1213 +file_isymbuf (abfd)
1214 + bfd *abfd;
1215 +{
1216 + Elf_Internal_Shdr *symtab_hdr;
1217 +
1218 + symtab_hdr = file_symtab_hdr (abfd);
1219 + if (symtab_hdr->sh_info == 0)
1220 + return NULL;
1221 +
1222 + if (symtab_hdr->contents == NULL)
1223 + {
1224 + Elf_Internal_Sym * contents = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0,
1225 + NULL, NULL, NULL);
1226 + symtab_hdr->contents = (unsigned char *) contents;
1227 + }
1228 +
1229 + return (Elf_Internal_Sym *) symtab_hdr->contents;
1230 +}
1231 +
1232 +static Elf_Internal_Rela *
1233 +section_relocs (abfd, sec)
1234 + bfd *abfd;
1235 + asection *sec;
1236 +{
1237 + if ((sec->flags & SEC_RELOC) == 0)
1238 + return NULL;
1239 +
1240 + if (sec->reloc_count == 0)
1241 + return NULL;
1242 +
1243 + if (elf_section_data (sec)->relocs == NULL)
1244 + elf_section_data (sec)->relocs =
1245 + _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, 1);
1246 +
1247 + return elf_section_data (sec)->relocs;
1248 +}
1249 +
1250 +static bfd_byte *
1251 +section_contents (abfd, sec)
1252 + bfd *abfd;
1253 + asection *sec;
1254 +{
1255 + bfd_byte *contents;
1256 +
1257 + sec->rawsize = sec->rawsize ? sec->rawsize: sec->size;
1258 +
1259 + if (elf_section_data (sec)->this_hdr.contents)
1260 + return elf_section_data (sec)->this_hdr.contents;
1261 +
1262 + contents = (bfd_byte *) bfd_malloc (sec->rawsize);
1263 + if (contents == NULL)
1264 + return NULL;
1265 +
1266 + if (! bfd_get_section_contents (abfd, sec, contents,
1267 + (file_ptr) 0, sec->rawsize))
1268 + {
1269 + free (contents);
1270 + return NULL;
1271 + }
1272 +
1273 + elf_section_data (sec)->this_hdr.contents = contents;
1274 + return contents;
1275 +}
1276 +
1277 +/* This function handles relaxing for the ubicom32.
1278 +
1279 + Principle: Start with the first page and remove page instructions that
1280 + are not require on this first page. By removing page instructions more
1281 + code will fit into this page - repeat until nothing more can be achieved
1282 + for this page. Move on to the next page.
1283 +
1284 + Processing the pages one at a time from the lowest page allows a removal
1285 + only policy to be used - pages can be removed but are never reinserted. */
1286 +
1287 +static bfd_boolean
1288 +ubicom32_elf_relax_section (abfd, sec, link_info, again)
1289 + bfd *abfd;
1290 + asection *sec;
1291 + struct bfd_link_info *link_info;
1292 + bfd_boolean *again;
1293 +{
1294 + /* Assume nothing changes. */
1295 + *again = FALSE;
1296 +
1297 + /* We don't have to do anything for a relocatable link,
1298 + if this section does not have relocs, or if this is
1299 + not a code section. */
1300 + if (link_info->relocatable
1301 + || (sec->flags & SEC_RELOC) == 0
1302 + || sec->reloc_count == 0
1303 + || (sec->flags & SEC_CODE) == 0)
1304 + return TRUE;
1305 +
1306 + /* If this is the first time we have been called
1307 + for this section, initialise the cooked size.
1308 + if (sec->_cooked_size == 0)
1309 + sec->_cooked_size = sec->rawsize;
1310 + */
1311 +
1312 + /* This is where all the relaxation actually get done. */
1313 + if (!ubicom32_elf_relax_calli (abfd, sec, again))
1314 + return FALSE;
1315 +
1316 + if (sec->rawsize != sec->size)
1317 + sec->size = sec->rawsize;
1318 +
1319 + /* Success! */
1320 + return TRUE;
1321 +}
1322 +
1323 +static bfd_boolean
1324 +ubicom32_elf_relax_calli (abfd, sec, again)
1325 + bfd *abfd;
1326 + asection *sec;
1327 + bfd_boolean *again;
1328 +{
1329 + bfd_byte *contents = section_contents (abfd, sec);
1330 + Elf_Internal_Rela *irelbase = section_relocs (abfd, sec);
1331 + Elf_Internal_Rela *irelend = irelbase + sec->reloc_count;
1332 + Elf_Internal_Rela *irel_moveai = NULL;
1333 + Elf_Internal_Rela *irel;
1334 + unsigned long insn;
1335 + bfd_vma symval;
1336 + bfd_vma pc;
1337 + bfd_vma dest;
1338 + signed long offs;
1339 +
1340 + /* Walk thru the section looking for relaxation opertunities. */
1341 + for (irel = irelbase; irel < irelend; irel++)
1342 + {
1343 + /* Remember last moveai instruction */
1344 + if (ELF32_R_TYPE (irel->r_info) == (int) R_UBICOM32_HI24)
1345 + {
1346 + irel_moveai = irel;
1347 + continue;
1348 + }
1349 +
1350 + /* Ignore non calli instructions */
1351 + if (ELF32_R_TYPE (irel->r_info) != (int) R_UBICOM32_LO7_CALLI)
1352 + continue;
1353 +
1354 + /* calli instruction => verify it is a calli instruction
1355 + using a5 with a 5 bit positive offset */
1356 + insn = bfd_get_32 (abfd, (bfd_byte *)(contents + irel->r_offset));
1357 + if ((insn & 0xffffffe0) != 0xf0a000a0)
1358 + continue;
1359 + symval = symbol_value (abfd, irel);
1360 + if (symval == UNDEFINED_SYMBOL)
1361 + continue;
1362 + dest = symval + irel->r_addend;
1363 +
1364 + /* Check proceeding instruction for a valid moveai */
1365 + if (!irel_moveai)
1366 + continue;
1367 + if (irel_moveai->r_offset != (irel->r_offset - 4))
1368 + continue;
1369 + insn = bfd_get_32 (abfd, (bfd_byte *)(contents + irel_moveai->r_offset));
1370 + if ((insn & 0xf8e00000) != 0xe0a00000)
1371 + continue;
1372 + symval = symbol_value (abfd, irel_moveai);
1373 + if (symval == UNDEFINED_SYMBOL)
1374 + continue;
1375 + symval += irel_moveai->r_addend;
1376 + if (symval != dest)
1377 + continue;
1378 +
1379 + /* Check offset required */
1380 + pc = BASEADDR (sec) + irel_moveai->r_offset;
1381 + offs = dest - pc;
1382 + if (offs > (UBICOM32_CALL_MAX_POS_OFFS + 4))
1383 + continue;
1384 + if (offs < UBICOM32_CALL_MAX_NEG_OFFS)
1385 + continue;
1386 +
1387 + /* Replace calli with a call instruction */
1388 + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_UBICOM32_24_PCREL);
1389 + bfd_put_32 (abfd, 0xd8a00000, contents + irel->r_offset);
1390 +
1391 + /* Delete moveai instruction */
1392 + irel_moveai->r_info = ELF32_R_INFO (ELF32_R_SYM (irel_moveai->r_info), R_UBICOM32_NONE);
1393 + if (!ubicom32_elf_relax_delete_bytes (abfd, sec, irel_moveai->r_offset, 4))
1394 + return FALSE;
1395 +
1396 + /* Modified => will need to iterate relaxation again. */
1397 + *again = TRUE;
1398 + }
1399 +
1400 + return TRUE;
1401 +}
1402 +
1403 +/* Delete some bytes from a section while relaxing. */
1404 +
1405 +static bfd_boolean
1406 +ubicom32_elf_relax_delete_bytes (abfd, sec, addr, count)
1407 + bfd *abfd;
1408 + asection *sec;
1409 + bfd_vma addr;
1410 + int count;
1411 +{
1412 + bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
1413 + bfd_vma endaddr = sec->rawsize;
1414 +
1415 + /* Actually delete the bytes. */
1416 + memmove (contents + addr, contents + addr + count,
1417 + endaddr - addr - count);
1418 +
1419 + sec->rawsize -= count;
1420 +
1421 + adjust_all_relocations (abfd, sec, addr + count, -count);
1422 + return TRUE;
1423 +}
1424 +
1425 +/* Adjust all the relocations entries after adding or inserting instructions. */
1426 +
1427 +static void
1428 +adjust_sec_relocations (abfd, sec_to_process, addr_sec, addr, count)
1429 + bfd *abfd;
1430 + asection *sec_to_process;
1431 + asection *addr_sec;
1432 + bfd_vma addr;
1433 + int count;
1434 +{
1435 + Elf_Internal_Shdr *symtab_hdr;
1436 + Elf_Internal_Sym *isymbuf, *isym;
1437 + Elf_Internal_Rela *irel, *irelend, *irelbase;
1438 + unsigned int addr_shndx;
1439 +
1440 + irelbase = section_relocs (abfd, sec_to_process);
1441 + if (irelbase == NULL)
1442 + return;
1443 + irelend = irelbase + sec_to_process->reloc_count;
1444 +
1445 + symtab_hdr = file_symtab_hdr (abfd);
1446 + isymbuf = file_isymbuf (abfd);
1447 +
1448 + addr_shndx = _bfd_elf_section_from_bfd_section (abfd, addr_sec);
1449 +
1450 + for (irel = irelbase; irel < irelend; irel++)
1451 + {
1452 + if (ELF32_R_TYPE (irel->r_info) != R_UBICOM32_NONE)
1453 + {
1454 + /* Get the value of the symbol referred to by the reloc. */
1455 + if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1456 + {
1457 + asection *sym_sec;
1458 + bfd_vma xaddr, symval, relval;
1459 +
1460 + /* A local symbol. */
1461 + isym = isymbuf + ELF32_R_SYM (irel->r_info);
1462 + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1463 + xaddr = BASEADDR (addr_sec) + addr;
1464 + symval = BASEADDR (sym_sec) + isym->st_value;
1465 + relval = symval + irel->r_addend;
1466 +
1467 + if ((isym->st_shndx == addr_shndx)
1468 + && (xaddr > symval)
1469 + && (xaddr <= relval))
1470 + irel->r_addend += count;
1471 + }
1472 + }
1473 +
1474 + /* Adjust irel base address for PC space relocations after a deleted instruction. */
1475 + if (sec_to_process == addr_sec)
1476 + {
1477 + if (addr <= irel->r_offset)
1478 + irel->r_offset += count;
1479 + }
1480 + }
1481 +}
1482 +
1483 +static void
1484 +adjust_all_relocations (abfd, sec, addr, count)
1485 + bfd *abfd;
1486 + asection *sec;
1487 + bfd_vma addr;
1488 + int count;
1489 +{
1490 + Elf_Internal_Shdr *symtab_hdr;
1491 + Elf_Internal_Sym *isymbuf, *isym, *isymend;
1492 + struct elf_link_hash_entry **sym_hashes;
1493 + struct elf_link_hash_entry **end_hashes;
1494 + unsigned int symcount;
1495 + asection *section;
1496 + unsigned int shndx;
1497 +
1498 + symtab_hdr = file_symtab_hdr (abfd);
1499 + isymbuf = file_isymbuf (abfd);
1500 +
1501 + shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1502 +
1503 + /* Adjust all relocations that are affected. */
1504 + for (section = abfd->sections; section != NULL; section = section->next)
1505 + adjust_sec_relocations (abfd, section, sec, addr, count);
1506 +
1507 + /* Adjust the local symbols defined in this section. */
1508 + isymend = isymbuf + symtab_hdr->sh_info;
1509 + for (isym = isymbuf; isym < isymend; isym++)
1510 + {
1511 + if (isym->st_shndx == shndx
1512 + && addr <= isym->st_value)
1513 + isym->st_value += count;
1514 + }
1515 +
1516 + /* Now adjust the global symbols defined in this section. */
1517 + symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1518 + - symtab_hdr->sh_info);
1519 + sym_hashes = elf_sym_hashes (abfd);
1520 + end_hashes = sym_hashes + symcount;
1521 + for (; sym_hashes < end_hashes; sym_hashes++)
1522 + {
1523 + struct elf_link_hash_entry *sym_hash = *sym_hashes;
1524 +
1525 + if ((sym_hash->root.type == bfd_link_hash_defined
1526 + || sym_hash->root.type == bfd_link_hash_defweak)
1527 + && sym_hash->root.u.def.section == sec)
1528 + {
1529 + if (addr <= sym_hash->root.u.def.value)
1530 + sym_hash->root.u.def.value += count;
1531 + }
1532 + }
1533 +}
1534 +
1535 +/* Perform a single relocation. By default we use the standard BFD
1536 + routines. */
1537 +
1538 +static bfd_reloc_status_type
1539 +ubicom32_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
1540 + reloc_howto_type * howto;
1541 + bfd * input_bfd;
1542 + asection * input_section;
1543 + bfd_byte * contents;
1544 + Elf_Internal_Rela * rel;
1545 + bfd_vma relocation;
1546 +{
1547 + bfd_reloc_status_type r = bfd_reloc_ok;
1548 +
1549 + switch (howto->type)
1550 + {
1551 + default:
1552 + r = _bfd_final_link_relocate (howto, input_bfd, input_section,
1553 + contents, rel->r_offset,
1554 + relocation, rel->r_addend);
1555 + }
1556 +
1557 + return r;
1558 +}
1559 +
1560 +/* Relocate a UBICOM32 ELF section.
1561 + There is some attempt to make this function usable for many architectures,
1562 + both USE_REL and USE_RELA ['twould be nice if such a critter existed],
1563 + if only to serve as a learning tool.
1564 +
1565 + The RELOCATE_SECTION function is called by the new ELF backend linker
1566 + to handle the relocations for a section.
1567 +
1568 + The relocs are always passed as Rela structures; if the section
1569 + actually uses Rel structures, the r_addend field will always be
1570 + zero.
1571 +
1572 + This function is responsible for adjusting the section contents as
1573 + necessary, and (if using Rela relocs and generating a relocatable
1574 + output file) adjusting the reloc addend as necessary.
1575 +
1576 + This function does not have to worry about setting the reloc
1577 + address or the reloc symbol index.
1578 +
1579 + LOCAL_SYMS is a pointer to the swapped in local symbols.
1580 +
1581 + LOCAL_SECTIONS is an array giving the section in the input file
1582 + corresponding to the st_shndx field of each local symbol.
1583 +
1584 + The global hash table entry for the global symbols can be found
1585 + via elf_sym_hashes (input_bfd).
1586 +
1587 + When generating relocatable output, this function must handle
1588 + STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1589 + going to be the section symbol corresponding to the output
1590 + section, which means that the addend must be adjusted
1591 + accordingly. */
1592 +
1593 +static bfd_boolean
1594 +ubicom32_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1595 + contents, relocs, local_syms, local_sections)
1596 + bfd * output_bfd ATTRIBUTE_UNUSED;
1597 + struct bfd_link_info * info;
1598 + bfd * input_bfd;
1599 + asection * input_section;
1600 + bfd_byte * contents;
1601 + Elf_Internal_Rela * relocs;
1602 + Elf_Internal_Sym * local_syms;
1603 + asection ** local_sections;
1604 +{
1605 + Elf_Internal_Shdr * symtab_hdr;
1606 + struct elf_link_hash_entry ** sym_hashes;
1607 + Elf_Internal_Rela * rel;
1608 + Elf_Internal_Rela * relend;
1609 + struct debugLineInfoHeader *lh = NULL;
1610 + int cooked_size, discard_size;
1611 + bfd_byte *src, *dest, *content_end;
1612 + unsigned int i;
1613 +
1614 + symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1615 + sym_hashes = elf_sym_hashes (input_bfd);
1616 + relend = relocs + input_section->reloc_count;
1617 +
1618 + for (rel = relocs; rel < relend; rel ++)
1619 + {
1620 + reloc_howto_type * howto;
1621 + unsigned long r_symndx;
1622 + Elf_Internal_Sym * sym;
1623 + asection * sec;
1624 + struct elf_link_hash_entry * h;
1625 + bfd_vma relocation;
1626 + bfd_reloc_status_type r;
1627 + const char * name = NULL;
1628 + int r_type;
1629 +
1630 + r_type = ELF32_R_TYPE (rel->r_info);
1631 +
1632 + if ( r_type == R_UBICOM32_GNU_VTINHERIT
1633 + || r_type == R_UBICOM32_GNU_VTENTRY)
1634 + continue;
1635 +
1636 + r_symndx = ELF32_R_SYM (rel->r_info);
1637 +
1638 + if (info->relocatable)
1639 + {
1640 + /* This is a relocatable link. We don't have to change
1641 + anything, unless the reloc is against a section symbol,
1642 + in which case we have to adjust according to where the
1643 + section symbol winds up in the output section. */
1644 + if (r_symndx < symtab_hdr->sh_info)
1645 + {
1646 + sym = local_syms + r_symndx;
1647 +
1648 + if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1649 + {
1650 + sec = local_sections [r_symndx];
1651 + rel->r_addend += sec->output_offset + sym->st_value;
1652 + }
1653 + }
1654 +
1655 + continue;
1656 + }
1657 +
1658 + /* This is a final link. */
1659 + howto = ubicom32_elf_howto_table + ELF32_R_TYPE (rel->r_info);
1660 + h = NULL;
1661 + sym = NULL;
1662 + sec = NULL;
1663 +
1664 + if (r_symndx < symtab_hdr->sh_info)
1665 + {
1666 + sym = local_syms + r_symndx;
1667 + sec = local_sections [r_symndx];
1668 + relocation = (sec->output_section->vma
1669 + + sec->output_offset
1670 + + sym->st_value);
1671 +
1672 + name = bfd_elf_string_from_elf_section
1673 + (input_bfd, symtab_hdr->sh_link, sym->st_name);
1674 + name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1675 + }
1676 + else
1677 + {
1678 + h = sym_hashes [r_symndx - symtab_hdr->sh_info];
1679 +
1680 + while (h->root.type == bfd_link_hash_indirect
1681 + || h->root.type == bfd_link_hash_warning)
1682 + h = (struct elf_link_hash_entry *) h->root.u.i.link;
1683 +
1684 + name = h->root.root.string;
1685 +
1686 + if (h->root.type == bfd_link_hash_defined
1687 + || h->root.type == bfd_link_hash_defweak)
1688 + {
1689 + sec = h->root.u.def.section;
1690 + relocation = (h->root.u.def.value
1691 + + sec->output_section->vma
1692 + + sec->output_offset);
1693 + }
1694 + else if (h->root.type == bfd_link_hash_undefweak)
1695 + {
1696 + relocation = 0;
1697 + }
1698 + else
1699 + {
1700 + if (! ((*info->callbacks->undefined_symbol)
1701 + (info, h->root.root.string, input_bfd,
1702 + input_section, rel->r_offset,
1703 + (!info->shared ))))
1704 + return FALSE;
1705 + relocation = 0;
1706 + }
1707 + }
1708 +
1709 + switch (r_type)
1710 + {
1711 + case R_UBICOM32_LO16:
1712 + r = ubicom32_elf_relocate_lo16 (input_bfd, rel, contents, relocation);
1713 + break;
1714 +
1715 + case R_UBICOM32_HI16:
1716 + r = ubicom32_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
1717 + break;
1718 +
1719 + case R_UBICOM32_HI24:
1720 + r = ubicom32_elf_relocate_hi24 (input_bfd, rel, contents, relocation);
1721 + break;
1722 +
1723 + case R_UBICOM32_LO7_S:
1724 + r = ubicom32_elf_relocate_lo7_s (input_bfd, rel, contents, relocation);
1725 + break;
1726 +
1727 + case R_UBICOM32_LO7_2_S:
1728 + r = ubicom32_elf_relocate_lo7_2_s (input_bfd, rel, contents, relocation);
1729 + break;
1730 +
1731 + case R_UBICOM32_LO7_4_S:
1732 + r = ubicom32_elf_relocate_lo7_4_s (input_bfd, rel, contents, relocation);
1733 + break;
1734 +
1735 + case R_UBICOM32_LO7_D:
1736 + r = ubicom32_elf_relocate_lo7_d (input_bfd, rel, contents, relocation);
1737 + break;
1738 +
1739 + case R_UBICOM32_LO7_2_D:
1740 + r = ubicom32_elf_relocate_lo7_2_d (input_bfd, rel, contents, relocation);
1741 + break;
1742 +
1743 + case R_UBICOM32_LO7_4_D:
1744 + r = ubicom32_elf_relocate_lo7_4_d (input_bfd, rel, contents, relocation);
1745 + break;
1746 +
1747 + case R_UBICOM32_24_PCREL:
1748 + r = ubicom32_elf_relocate_pcrel24 (input_bfd, input_section, rel, contents, relocation);
1749 + break;
1750 +
1751 + case R_UBICOM32_LO7_CALLI:
1752 + r = ubicom32_elf_relocate_lo_calli (input_bfd, rel, contents, relocation, 7);
1753 + break;
1754 +
1755 + case R_UBICOM32_LO16_CALLI:
1756 + r = ubicom32_elf_relocate_lo_calli (input_bfd, rel, contents, relocation, 18);
1757 + break;
1758 +
1759 + case R_UBICOM32_32:
1760 + /* relocation &= ~(0xff << 24); */
1761 + /* FALLTHROUGH */
1762 +
1763 + default:
1764 + r = ubicom32_final_link_relocate (howto, input_bfd, input_section,
1765 + contents, rel, relocation);
1766 + break;
1767 + }
1768 +
1769 + if (r != bfd_reloc_ok)
1770 + {
1771 + const char * msg = (const char *) NULL;
1772 +
1773 + switch (r)
1774 + {
1775 + case bfd_reloc_overflow:
1776 + r = info->callbacks->reloc_overflow
1777 + (info, NULL, name, howto->name, (bfd_vma) 0,
1778 + input_bfd, input_section, rel->r_offset);
1779 + break;
1780 +
1781 + case bfd_reloc_undefined:
1782 + r = info->callbacks->undefined_symbol
1783 + (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1784 + break;
1785 +
1786 + case bfd_reloc_outofrange:
1787 + msg = _("internal error: out of range error");
1788 + break;
1789 +
1790 + case bfd_reloc_notsupported:
1791 + msg = _("internal error: unsupported relocation error");
1792 + break;
1793 +
1794 + case bfd_reloc_dangerous:
1795 + msg = _("internal error: dangerous relocation");
1796 + break;
1797 +
1798 + default:
1799 + msg = _("internal error: unknown error");
1800 + break;
1801 + }
1802 +
1803 + if (msg)
1804 + r = info->callbacks->warning
1805 + (info, msg, name, input_bfd, input_section, rel->r_offset);
1806 +
1807 + if (! r)
1808 + return FALSE;
1809 + }
1810 + }
1811 +
1812 + /*
1813 + * now we have to collapse the .debug_line section if it has a
1814 + * sec_info section
1815 + */
1816 +
1817 + if(strcmp(input_section->name, ".debug_line"))
1818 + return TRUE;
1819 +
1820 + /* this is a .debug_line section. See it has a sec_info entry */
1821 + if(elf_section_data(input_section)->sec_info == NULL)
1822 + return TRUE;
1823 +
1824 + lh = (struct debugLineInfoHeader *) elf_section_data(input_section)->sec_info;
1825 +
1826 + if(lh->numEntries == 0)
1827 + return TRUE;
1828 +
1829 + dest = contents + lh->linfo[0].startOffset;
1830 +
1831 + cooked_size = input_section->rawsize;
1832 + content_end = contents + cooked_size;
1833 + discard_size = 0;
1834 +
1835 + for(i=0; i< lh->numEntries; i++)
1836 + {
1837 + if(lh->linfo[i].discard)
1838 + discard_size += lh->linfo[i].length;
1839 + else
1840 + {
1841 + src = contents + lh->linfo[i].startOffset;
1842 + (void) memcpy(dest, src, lh->linfo[i].length);
1843 + dest += lh->linfo[i].length;
1844 + }
1845 + }
1846 +
1847 + src = contents + lh->linfo[lh->numEntries-1].startOffset + lh->linfo[lh->numEntries-1].length;
1848 + if(src < content_end)
1849 + (void) memcpy(dest, src, content_end - src);
1850 +
1851 + i = bfd_get_32(input_bfd, contents);
1852 + i -= discard_size;
1853 + bfd_put_32(input_bfd, i, contents);
1854 + //input_section->rawsize -= discard_size;
1855 + return TRUE;
1856 +}
1857 +
1858 +\f
1859 +/* Update the got entry reference counts for the section being
1860 + removed. */
1861 +
1862 +static bfd_boolean
1863 +ubicom32_elf_gc_sweep_hook (abfd, info, sec, relocs)
1864 + bfd * abfd ATTRIBUTE_UNUSED;
1865 + struct bfd_link_info * info ATTRIBUTE_UNUSED;
1866 + asection * sec ATTRIBUTE_UNUSED;
1867 + const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
1868 +{
1869 + return TRUE;
1870 +}
1871 +
1872 +/* Return the section that should be marked against GC for a given
1873 + relocation. */
1874 +
1875 +static asection *
1876 +ubicom32_elf_gc_mark_hook (sec, info, rel, h, sym)
1877 + asection * sec;
1878 + struct bfd_link_info * info ATTRIBUTE_UNUSED;
1879 + Elf_Internal_Rela * rel;
1880 + struct elf_link_hash_entry * h;
1881 + Elf_Internal_Sym * sym;
1882 +{
1883 + if (h != NULL)
1884 + {
1885 + switch (ELF32_R_TYPE (rel->r_info))
1886 + {
1887 + case R_UBICOM32_GNU_VTINHERIT:
1888 + case R_UBICOM32_GNU_VTENTRY:
1889 + break;
1890 +
1891 + default:
1892 + switch (h->root.type)
1893 + {
1894 + case bfd_link_hash_defined:
1895 + case bfd_link_hash_defweak:
1896 + return h->root.u.def.section;
1897 +
1898 + case bfd_link_hash_common:
1899 + return h->root.u.c.p->section;
1900 +
1901 + default:
1902 + break;
1903 + }
1904 + }
1905 + }
1906 + else
1907 + {
1908 + if (!(elf_bad_symtab (sec->owner)
1909 + && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
1910 + && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
1911 + && sym->st_shndx != SHN_COMMON))
1912 + {
1913 + return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1914 + }
1915 + }
1916 +
1917 + return NULL;
1918 +}
1919 +
1920 +/* Look through the relocs for a section during the first phase.
1921 + Since we don't do .gots or .plts, we just need to consider the
1922 + virtual table relocs for gc. */
1923 +
1924 +static bfd_boolean
1925 +ubicom32_elf_check_relocs (abfd, info, sec, relocs)
1926 + bfd *abfd;
1927 + struct bfd_link_info *info;
1928 + asection *sec;
1929 + const Elf_Internal_Rela *relocs;
1930 +{
1931 + Elf_Internal_Shdr *symtab_hdr;
1932 + struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
1933 + Elf_Internal_Rela *rel;
1934 + Elf_Internal_Rela *rel_end;
1935 + Elf_Internal_Rela *my_rel = ( Elf_Internal_Rela*)relocs;
1936 + if (info->relocatable)
1937 + return TRUE;
1938 +
1939 + symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1940 + sym_hashes = elf_sym_hashes (abfd);
1941 + sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
1942 + if (!elf_bad_symtab (abfd))
1943 + sym_hashes_end -= symtab_hdr->sh_info;
1944 +
1945 + rel_end = my_rel + sec->reloc_count;
1946 + for (rel = my_rel; rel < rel_end; rel++)
1947 + {
1948 + struct elf_link_hash_entry *h;
1949 + unsigned long r_symndx;
1950 +
1951 + r_symndx = ELF32_R_SYM (rel->r_info);
1952 + if (r_symndx < symtab_hdr->sh_info)
1953 + h = NULL;
1954 + else
1955 + h = sym_hashes [r_symndx - symtab_hdr->sh_info];
1956 +
1957 + switch (ELF32_R_TYPE (rel->r_info))
1958 + {
1959 + /* This relocation describes the C++ object vtable hierarchy.
1960 + Reconstruct it for later use during GC. */
1961 + case R_UBICOM32_GNU_VTINHERIT:
1962 + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
1963 + return FALSE;
1964 + break;
1965 +
1966 + /* This relocation describes which C++ vtable entries are actually
1967 + used. Record for later use during GC. */
1968 + case R_UBICOM32_GNU_VTENTRY:
1969 + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
1970 + return FALSE;
1971 + break;
1972 +
1973 + case R_UBICOM32_32:
1974 + /* For debug section, change to harvard relocations */
1975 + if (memcmp (sec->name, ".debug", 6) == 0
1976 + || memcmp (sec->name, ".stab", 5) == 0)
1977 + rel->r_info = ELF32_R_INFO (ELF32_R_SYM (rel->r_info), R_UBICOM32_32_HARVARD);
1978 + break;
1979 + }
1980 + }
1981 + return TRUE;
1982 +}
1983 +
1984 +static bfd_boolean
1985 +ubicom32_elf_object_p (abfd)
1986 + bfd *abfd;
1987 +{
1988 + flagword mach = elf_elfheader (abfd)->e_flags & 0xffff;
1989 + bfd_default_set_arch_mach (abfd, bfd_arch_ubicom32, mach);
1990 + return (((elf_elfheader (abfd)->e_flags & EF_UBICOM32_FDPIC) != 0)
1991 + == (IS_FDPIC (abfd)));
1992 +}
1993 +
1994 +\f
1995 +/* Function to set the ELF flag bits */
1996 +
1997 +static bfd_boolean
1998 +ubicom32_elf_set_private_flags (abfd, flags)
1999 + bfd *abfd;
2000 + flagword flags;
2001 +{
2002 + elf_elfheader (abfd)->e_flags = flags;
2003 + elf_flags_init (abfd) = TRUE;
2004 + return TRUE;
2005 +}
2006 +
2007 +static bfd_boolean
2008 +ubicom32_elf_copy_private_bfd_data (ibfd, obfd)
2009 + bfd *ibfd;
2010 + bfd *obfd;
2011 +{
2012 + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
2013 + || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
2014 + return TRUE;
2015 +
2016 + BFD_ASSERT (!elf_flags_init (obfd)
2017 + || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
2018 +
2019 + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
2020 + elf_flags_init (obfd) = TRUE;
2021 + return TRUE;
2022 +}
2023 +
2024 +/* Merge backend specific data from an object file to the output
2025 + object file when linking. */
2026 +static bfd_boolean
2027 +ubicom32_elf_merge_private_bfd_data (ibfd, obfd)
2028 + bfd *ibfd;
2029 + bfd *obfd;
2030 +{
2031 + flagword old_flags, new_flags;
2032 + bfd_boolean error = FALSE;
2033 +
2034 + new_flags = elf_elfheader (ibfd)->e_flags;
2035 + old_flags = elf_elfheader (obfd)->e_flags;
2036 +
2037 +#ifdef DEBUG
2038 + (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
2039 + old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
2040 + bfd_get_filename (ibfd));
2041 +#endif
2042 +
2043 + if (!elf_flags_init (obfd)) /* First call, no flags set */
2044 + {
2045 + elf_flags_init (obfd) = TRUE;
2046 + elf_elfheader (obfd)->e_flags = new_flags;
2047 + }
2048 + else
2049 + {
2050 + if (new_flags != old_flags)
2051 + {
2052 + /* Mismatched flags. */
2053 + char *output_cpu_version = ((old_flags &0xffff) == 1) ? "V3" : (((old_flags &0xffff) == 2) ? "V4" : "unknown");
2054 + char *input_cpu_version = ((new_flags &0xffff) == 1) ? "V3" : (((new_flags &0xffff) == 2) ? "V4" : "unknown");
2055 + char *output_filename = bfd_get_filename (obfd);
2056 + char *input_filename = bfd_get_filename (ibfd);
2057 + char *output_pic = (old_flags & EF_UBICOM32_PIC_FLAGS) ? ((old_flags & EF_UBICOM32_PIC) ? "FPIC" : "FDPIC") : NULL;
2058 + char *input_pic = (new_flags & EF_UBICOM32_PIC_FLAGS) ? ((new_flags & EF_UBICOM32_PIC) ? "FPIC" : "FDPIC") : NULL;
2059 +
2060 + (*_bfd_error_handler) ("Linking mismatched file types. Output file = %s file type 0x%.8lx, input file = %s file type 0x%.8lx",
2061 + output_filename, old_flags, input_filename, new_flags);
2062 +
2063 + if (output_pic)
2064 + {
2065 + (*_bfd_error_handler)("Output file %s %s for cpu version %s", output_filename, output_pic, output_cpu_version);
2066 + }
2067 + else
2068 + {
2069 + (*_bfd_error_handler)("Output file %s for cpu version %s", output_filename, output_cpu_version);
2070 + }
2071 +
2072 + if (input_pic)
2073 + {
2074 + (*_bfd_error_handler)("Input file %s %s for cpu version %s", input_filename, input_pic, input_cpu_version);
2075 + }
2076 + else
2077 + {
2078 + (*_bfd_error_handler)("Input file %s for cpu version %s", input_filename, input_cpu_version);
2079 + }
2080 +
2081 + (*_bfd_error_handler) ("Link ABORTED.");
2082 + _exit(EXIT_FAILURE);
2083 + }
2084 + }
2085 + if (error)
2086 + bfd_set_error (bfd_error_bad_value);
2087 +
2088 + return !error;
2089 +}
2090 +
2091 +static bfd_boolean
2092 +ubicom32_elf_print_private_bfd_data (abfd, ptr)
2093 + bfd *abfd;
2094 + PTR ptr;
2095 +{
2096 + FILE *file = (FILE *) ptr;
2097 + flagword flags;
2098 +
2099 + BFD_ASSERT (abfd != NULL && ptr != NULL);
2100 +
2101 + /* Print normal ELF private data. */
2102 + _bfd_elf_print_private_bfd_data (abfd, ptr);
2103 +
2104 + flags = elf_elfheader (abfd)->e_flags;
2105 + fprintf (file, _("private flags = 0x%lx:"), (long)flags);
2106 +
2107 + fputc ('\n', file);
2108 +
2109 + return TRUE;
2110 +}
2111 +
2112 +bfd_boolean
2113 +ubicom32_elf_discard_info(abfd, cookie, info)
2114 + bfd *abfd;
2115 + struct elf_reloc_cookie *cookie ATTRIBUTE_UNUSED;
2116 + struct bfd_link_info *info;
2117 +
2118 +{
2119 + unsigned int hasDebugLine=0;
2120 + unsigned needExclude = 0;
2121 + asection *o;
2122 + asection *sec= NULL;
2123 + bfd_byte *contents = NULL;
2124 + bfd_byte *contentsEnd;
2125 + Elf_Internal_Rela *irel, *irelend, *irelbase;
2126 + Elf_Internal_Shdr *symtab_hdr;
2127 + Elf_Internal_Sym *isym;
2128 + Elf_Internal_Sym *isymbuf = NULL;
2129 + struct debugLineInfoHeader *lh = NULL;
2130 + unsigned int maxLineInfoEntries = 10;
2131 + unsigned int offset, contentLength;
2132 + unsigned char *ptr, *sequence_start;
2133 + unsigned int setupEntry=1;
2134 + unsigned int opcode_base, op_code;
2135 + unsigned int bytes_read;
2136 +
2137 + for (o = abfd->sections; o != NULL; o = o->next)
2138 + {
2139 + if(!hasDebugLine)
2140 + if(!strcmp(o->name, ".debug_line"))
2141 + {
2142 + hasDebugLine =1;
2143 + sec = o;
2144 + }
2145 +
2146 + /* Keep special sections. Keep .debug sections. */
2147 + if (o->flags & SEC_EXCLUDE)
2148 + {
2149 + needExclude = 1;
2150 + }
2151 + }
2152 +
2153 + if(needExclude == 0 || hasDebugLine ==0)
2154 + return FALSE;
2155 +
2156 + /*
2157 + * you can be here only if we have .debug_line section and some
2158 + * section is being excudled
2159 + */
2160 +
2161 + /*
2162 + * We need to extract .debug_line section contents and its
2163 + * relocation contents.
2164 + */
2165 +
2166 + /* We don't have to do anything for a relocatable link,
2167 + if this section does not have relocs */
2168 + if (info->relocatable
2169 + || (sec->flags & SEC_RELOC) == 0
2170 + || sec->reloc_count == 0)
2171 + return FALSE;
2172 +
2173 + /* If this is the first time we have been called
2174 + for this section, initialise the cooked size.
2175 + if (sec->_cooked_size == 0)
2176 + sec->_cooked_size = sec->rawsize;
2177 + */
2178 +
2179 + symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2180 +
2181 + irelbase = _bfd_elf_link_read_relocs (abfd, sec, NULL,
2182 + (Elf_Internal_Rela *)NULL,
2183 + info->keep_memory);
2184 +
2185 + if(irelbase == NULL)
2186 + return FALSE;
2187 +
2188 + irelend = irelbase +sec->reloc_count;
2189 +
2190 + /* Get section contents cached copy if it exists. */
2191 + if (contents == NULL)
2192 + {
2193 + contents = section_contents(abfd, sec);
2194 + }
2195 +
2196 + if (isymbuf == NULL && symtab_hdr->sh_info != 0)
2197 + {
2198 + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
2199 + if (isymbuf == NULL)
2200 + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
2201 + symtab_hdr->sh_info, 0,
2202 + NULL, NULL, NULL);
2203 + if (isymbuf == NULL)
2204 + return FALSE;
2205 + }
2206 +
2207 + /* allocate the line header and initialize it */
2208 + lh = (struct debugLineInfoHeader *)
2209 + realloc( (void *)lh, sizeof (struct debugLineInfo)*maxLineInfoEntries +
2210 + sizeof(unsigned int));
2211 +
2212 + lh->numEntries = 0;
2213 +
2214 + /* the first 4 bytes contains the length */
2215 + contentLength = bfd_get_32 (abfd, (bfd_byte *)contents);
2216 + contentsEnd = contents + contentLength + 4;
2217 +
2218 + ptr = (unsigned char *)contents;
2219 + ptr +=6;
2220 + /* read the header length */
2221 + offset = bfd_get_32(abfd, (bfd_byte *)ptr);
2222 + ptr += 4;
2223 + ptr += offset;
2224 +
2225 + /* extract the base opcode */
2226 + opcode_base = (unsigned char)contents[14];
2227 + sequence_start = NULL;
2228 + while(ptr < (unsigned char *) contentsEnd)
2229 + {
2230 + if(setupEntry)
2231 + {
2232 + if(lh->numEntries == maxLineInfoEntries)
2233 + {
2234 + /* need to do some reallocing. Bump up the entries by 10 */
2235 + maxLineInfoEntries += 10;
2236 + lh = (struct debugLineInfoHeader *)
2237 + realloc( (void *)lh,
2238 + sizeof (struct debugLineInfo)*maxLineInfoEntries +
2239 + sizeof(unsigned int));
2240 + }
2241 +
2242 + /* zero out the entry */
2243 + memset((void *) &lh->linfo[lh->numEntries],
2244 + 0,
2245 + sizeof(struct debugLineInfo));
2246 + lh->linfo[lh->numEntries].startOffset = (bfd_byte *)ptr - contents;
2247 + setupEntry = 0;
2248 + sequence_start = ptr;
2249 + }
2250 +
2251 + /* We need to run the state machine */
2252 + op_code = bfd_get_8 (abfd, (bfd_byte *)ptr);
2253 + ptr += 1;
2254 +
2255 + if(op_code >= opcode_base)
2256 + continue;
2257 +
2258 + switch(op_code)
2259 + {
2260 + case DW_LNS_extended_op:
2261 + ptr += 1; /* ignore length */
2262 + op_code = bfd_get_8 (abfd, (bfd_byte *)ptr);
2263 + ptr += 1;
2264 + switch (op_code)
2265 + {
2266 + case DW_LNE_end_sequence:
2267 + /* end of sequence. Time to record stuff */
2268 + lh->linfo[lh->numEntries++].length =
2269 + (bfd_byte *)ptr - sequence_start;
2270 + setupEntry = 1;
2271 + break;
2272 + case DW_LNE_set_address:
2273 + ptr += 4;
2274 + break;
2275 + case DW_LNE_define_file:
2276 + {
2277 + ptr += (strlen((char *)ptr) + 1);
2278 + (void) read_unsigned_leb128(abfd, ptr, &bytes_read);
2279 + ptr += bytes_read;
2280 + (void) read_unsigned_leb128(abfd, ptr, &bytes_read);
2281 + ptr += bytes_read;
2282 + (void) read_unsigned_leb128(abfd, ptr, &bytes_read);
2283 + ptr += bytes_read;
2284 + break;
2285 + }
2286 + }
2287 + case DW_LNS_negate_stmt:
2288 + case DW_LNS_set_basic_block:
2289 + case DW_LNS_const_add_pc:
2290 + case DW_LNS_copy:
2291 + break;
2292 + case DW_LNS_advance_pc:
2293 + case DW_LNS_set_file:
2294 + case DW_LNS_set_column:
2295 + (void) read_unsigned_leb128 (abfd, ptr, &bytes_read);
2296 + ptr += bytes_read;
2297 + break;
2298 + case DW_LNS_advance_line:
2299 + (void) read_signed_leb128 (abfd, ptr, &bytes_read);
2300 + ptr += bytes_read;
2301 + break;
2302 + case DW_LNS_fixed_advance_pc:
2303 + ptr += 2;
2304 + break;
2305 + }
2306 + }
2307 +
2308 + /*
2309 + * now scan through the relocations and match the
2310 + * lineinfo to a section name
2311 + */
2312 + for(irel = irelbase; irel< irelend; irel++)
2313 + {
2314 + bfd_vma offset;
2315 + asection *sym_sec;
2316 + int i;
2317 +
2318 + offset = irel->r_offset;
2319 + isym = isymbuf + ELF32_R_SYM (irel->r_info);
2320 +
2321 + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
2322 +
2323 + /* find which line section this rel entry belongs to */
2324 + for(i=0; i< (int) lh->numEntries; i++)
2325 + {
2326 + if(lh->linfo[i].startOffset <= offset &&
2327 + offset < lh->linfo[i].startOffset + lh->linfo[i].length)
2328 + break;
2329 + }
2330 +
2331 + if(lh->linfo[i].sectionName == NULL)
2332 + lh->linfo[i].sectionName = strdup(sym_sec->name);
2333 + }
2334 +
2335 + /* now scan through and find the exclude sections */
2336 + for (o = abfd->sections; o != NULL; o = o->next)
2337 + {
2338 + if (o->flags & SEC_EXCLUDE)
2339 + {
2340 + /* go through the lh entries and mark as discard */
2341 + int i;
2342 + for(i=0; i< (int) lh->numEntries; i++)
2343 + {
2344 + if(!strcmp(o->name, lh->linfo[i].sectionName))
2345 + lh->linfo[i].discard = 1;
2346 + }
2347 + }
2348 + }
2349 +
2350 + elf_section_data(sec)->sec_info = (PTR)(lh);
2351 +
2352 + return TRUE;
2353 +}
2354 +
2355 +\f
2356 +/* An extension of the elf hash table data structure, containing some
2357 + additional Blackfin-specific data. */
2358 +struct ubicom32fdpic_elf_link_hash_table
2359 +{
2360 + struct elf_link_hash_table elf;
2361 +
2362 + /* A pointer to the .got section. */
2363 + asection *sgot;
2364 + /* A pointer to the .rel.got section. */
2365 + asection *sgotrel;
2366 + /* A pointer to the .rofixup section. */
2367 + asection *sgotfixup;
2368 + /* A pointer to the .plt section. */
2369 + asection *splt;
2370 + /* A pointer to the .rel.plt section. */
2371 + asection *spltrel;
2372 + /* GOT base offset. */
2373 + bfd_vma got0;
2374 + /* Location of the first non-lazy PLT entry, i.e., the number of
2375 + bytes taken by lazy PLT entries. */
2376 + bfd_vma plt0;
2377 + /* A hash table holding information about which symbols were
2378 + referenced with which PIC-related relocations. */
2379 + struct htab *relocs_info;
2380 +};
2381 +
2382 +/* Get the Ubicom32 ELF linker hash table from a link_info structure. */
2383 +
2384 +#define ubicom32fdpic_hash_table(info) \
2385 + ((struct ubicom32fdpic_elf_link_hash_table *) ((info)->hash))
2386 +
2387 +#define ubicom32fdpic_got_section(info) \
2388 + (ubicom32fdpic_hash_table (info)->sgot)
2389 +#define ubicom32fdpic_gotrel_section(info) \
2390 + (ubicom32fdpic_hash_table (info)->sgotrel)
2391 +#define ubicom32fdpic_gotfixup_section(info) \
2392 + (ubicom32fdpic_hash_table (info)->sgotfixup)
2393 +#define ubicom32fdpic_plt_section(info) \
2394 + (ubicom32fdpic_hash_table (info)->splt)
2395 +#define ubicom32fdpic_pltrel_section(info) \
2396 + (ubicom32fdpic_hash_table (info)->spltrel)
2397 +#define ubicom32fdpic_relocs_info(info) \
2398 + (ubicom32fdpic_hash_table (info)->relocs_info)
2399 +#define ubicom32fdpic_got_initial_offset(info) \
2400 + (ubicom32fdpic_hash_table (info)->got0)
2401 +#define ubicom32fdpic_plt_initial_offset(info) \
2402 + (ubicom32fdpic_hash_table (info)->plt0)
2403 +
2404 +/* The name of the dynamic interpreter. This is put in the .interp
2405 + section. */
2406 +
2407 +#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
2408 +
2409 +#define DEFAULT_STACK_SIZE 0x20000
2410 +
2411 +/* This structure is used to collect the number of entries present in
2412 + each addressable range of the got. */
2413 +struct _ubicom32fdpic_dynamic_got_info
2414 +{
2415 + /* Several bits of information about the current link. */
2416 + struct bfd_link_info *info;
2417 + /* Total size needed for GOT entries. */
2418 + bfd_vma gotoffset_lo, gotoffset_hi;
2419 + /* Total size needed for function descriptor entries. */
2420 + bfd_vma fd_gotoffset_lo, fd_gotoffset_hi;
2421 + /* Total size needed function descriptor entries referenced in PLT
2422 + entries, that would be profitable to place in offsets close to
2423 + the PIC register. */
2424 + bfd_vma fdplt, privfdplt;
2425 + /* Total size needed by lazy PLT entries. */
2426 + bfd_vma lzplt;
2427 + bfd_vma num_plts;
2428 +
2429 + /* Number of relocations carried over from input object files. */
2430 + unsigned long relocs;
2431 + /* Number of fixups introduced by relocations in input object files. */
2432 + unsigned long fixups;
2433 +};
2434 +
2435 +/* This structure is used to assign offsets to got entries, function
2436 + descriptors, plt entries and lazy plt entries. */
2437 +struct ubicom32fdpic_dynamic_got_plt_info
2438 +{
2439 + /* Summary information collected with _bfinfdpic_count_got_plt_entries. */
2440 + struct _ubicom32fdpic_dynamic_got_info g;
2441 +
2442 + bfd_signed_vma current_got; /* This will be used during got entry allocation */
2443 + bfd_signed_vma current_fd; /* This will be used for function descriptro allocation. The numbers will go negative */
2444 + bfd_signed_vma current_privfd; /* This will be used for function descriptro allocation. The numbers will go negative */
2445 + bfd_vma current_plt; /* This is the offset to the PLT entry. We will need this to resolve the call entries. */
2446 + bfd_vma current_plt_trampoline; /* This is the offset to the PLT trampoline entry. */
2447 + bfd_vma total_fdplt; /* Total size of function descriptors. This is the memory above GOT pointer. */
2448 + bfd_vma total_got; /* This is the total of got entries for got_lo and got_funcdesc_lo references. */
2449 + bfd_vma total_lzplt; /* This is the total area for the PLT entries. This does not have the trampoline entry. */
2450 + bfd_vma total_trampoline; /* This is the total area for the PLT trampoline entries. */
2451 +};
2452 +
2453 +/* Decide whether a reference to a symbol can be resolved locally or
2454 + not. If the symbol is protected, we want the local address, but
2455 + its function descriptor must be assigned by the dynamic linker. */
2456 +#define UBICOM32FDPIC_SYM_LOCAL(INFO, H) \
2457 + (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
2458 + || ! elf_hash_table (INFO)->dynamic_sections_created)
2459 +#define UBICOM32FDPIC_FUNCDESC_LOCAL(INFO, H) \
2460 + ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
2461 +
2462 +/* This structure collects information on what kind of GOT, PLT or
2463 + function descriptors are required by relocations that reference a
2464 + certain symbol. */
2465 +struct ubicom32fdpic_relocs_info
2466 +{
2467 + /* The index of the symbol, as stored in the relocation r_info, if
2468 + we have a local symbol; -1 otherwise. */
2469 + long symndx;
2470 + union
2471 + {
2472 + /* The input bfd in which the symbol is defined, if it's a local
2473 + symbol. */
2474 + bfd *abfd;
2475 + /* If symndx == -1, the hash table entry corresponding to a global
2476 + symbol (even if it turns out to bind locally, in which case it
2477 + should ideally be replaced with section's symndx + addend). */
2478 + struct elf_link_hash_entry *h;
2479 + } d;
2480 + /* The addend of the relocation that references the symbol. */
2481 + bfd_vma addend;
2482 +
2483 + /* The fields above are used to identify an entry. The fields below
2484 + contain information on how an entry is used and, later on, which
2485 + locations it was assigned. */
2486 + /* The following 2 fields record whether the symbol+addend above was
2487 + ever referenced with a GOT relocation. The 17M4 suffix indicates a
2488 + GOT17M4 relocation; hilo is used for GOTLO/GOTHI pairs. */
2489 + unsigned gotoffset_lo;
2490 + unsigned gotoffset_hi;
2491 + /* Whether a FUNCDESC relocation references symbol+addend. */
2492 + unsigned fd;
2493 + /* Whether a FUNCDESC_GOT relocation references symbol+addend. */
2494 + unsigned fd_gotoffset_lo;
2495 + unsigned fd_gotoffset_hi;
2496 + /* Whether symbol+addend is referenced with GOTOFF17M4, GOTOFFLO or
2497 + GOTOFFHI relocations. The addend doesn't really matter, since we
2498 + envision that this will only be used to check whether the symbol
2499 + is mapped to the same segment as the got. */
2500 + unsigned gotoff;
2501 + /* Whether symbol+addend is referenced by a LABEL24 relocation. */
2502 + unsigned call;
2503 + /* Whether symbol+addend is referenced by a 32 or FUNCDESC_VALUE
2504 + relocation. */
2505 + unsigned sym;
2506 + /* Whether we need a PLT entry for a symbol. Should be implied by
2507 + something like:
2508 + (call && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)) */
2509 + unsigned plt:1;
2510 + /* Whether a function descriptor should be created in this link unit
2511 + for symbol+addend. Should be implied by something like:
2512 + (plt || fd_gotoffset_lo || fd_gotoffset_hi
2513 + || ((fd || fdgot17m4 || fdgothilo)
2514 + && (symndx != -1 || BFINFDPIC_FUNCDESC_LOCAL (info, d.h)))) */
2515 + unsigned privfd:1;
2516 + /* Whether a lazy PLT entry is needed for this symbol+addend.
2517 + Should be implied by something like:
2518 + (privfd && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)
2519 + && ! (info->flags & DF_BIND_NOW)) */
2520 + unsigned lazyplt:1;
2521 + /* Whether we've already emitted GOT relocations and PLT entries as
2522 + needed for this symbol. */
2523 + unsigned done:1;
2524 +
2525 + /* The number of R_byte4_data, R_BFIN_FUNCDESC and R_BFIN_FUNCDESC_VALUE
2526 + relocations referencing the symbol. */
2527 + unsigned relocs32, relocsfd, relocsfdv;
2528 +
2529 + /* The number of .rofixups entries and dynamic relocations allocated
2530 + for this symbol, minus any that might have already been used. */
2531 + unsigned fixups, dynrelocs;
2532 +
2533 + /* The offsets of the GOT entries assigned to symbol+addend, to the
2534 + function descriptor's address, and to a function descriptor,
2535 + respectively. Should be zero if unassigned. The offsets are
2536 + counted from the value that will be assigned to the PIC register,
2537 + not from the beginning of the .got section. */
2538 + bfd_signed_vma got_entry, fdgot_entry, fd_entry;
2539 + /* The offsets of the PLT entries assigned to symbol+addend,
2540 + non-lazy and lazy, respectively. If unassigned, should be
2541 + (bfd_vma)-1. */
2542 + bfd_vma plt_entry;
2543 + bfd_vma plt_trampoline_entry;
2544 +
2545 + /* plt_type is 1 for Sequence type 2 (0 - 255) it is 2 for > 255 */
2546 + bfd_vma plt_type;
2547 +
2548 + /* rel_offset. Plt relocation offset need to be encoded into the plt entry. */
2549 + bfd_vma rel_offset;
2550 +
2551 + /* bfd_vma lzplt_entry; not used in ubicom32 */
2552 +};
2553 +
2554 +/* Compute the total GOT size required by each symbol in each range.
2555 + Symbols may require up to 4 words in the GOT: an entry pointing to
2556 + the symbol, an entry pointing to its function descriptor, and a
2557 + private function descriptors taking two words. */
2558 +
2559 +#if 0
2560 +static bfd_vma plt_code[] = {
2561 + 0xc90f0000, //movei d15,#0
2562 + 0x0123e30f, //lea.4 a3,(a0,d15)
2563 + 0x0124630f, //move.4 a4,(a0,d15)
2564 + 0x01206461, //move.4 a0,4(a3)
2565 + 0xf0800080, //calli a4,0(a4)
2566 +};
2567 +#endif
2568 +
2569 +static bfd_vma plt_trampoline[] = {
2570 + 0xc9280000, // movei mac_hi,#0
2571 + 0x00002400, // ret (a0)
2572 +};
2573 +
2574 +static bfd_vma plt_code_seq1[] = {
2575 + 0xc90fffe8, //movei d15,#-24
2576 + 0x0123e30f, //lea.4 a3,(a0,d15)
2577 + 0x01206461, //move.4 a0,4(a3)
2578 + 0x00002460, //ret (a3)
2579 +};
2580 +
2581 +static bfd_vma plt_code_seq2[] = {
2582 + 0x0123f71f, // pdec a3,4(a0)
2583 + 0x01206461, // move.4 a0,4(a3)
2584 + 0x00002460, // ret (a3)
2585 +};
2586 +
2587 +#define NUM_PLT_CODE_WORDS (sizeof (plt_code) / sizeof (bfd_vma))
2588 +#define LZPLT_NORMAL_SIZE (sizeof(plt_code))
2589 +
2590 +#define NUM_PLT_CODE_WORDS_SEQ1 (sizeof (plt_code_seq1) / sizeof (bfd_vma))
2591 +#define LZPLT_SIZE_SEQ1 (sizeof(plt_code_seq1))
2592 +
2593 +#define NUM_PLT_CODE_WORDS_SEQ2 (sizeof (plt_code_seq2) / sizeof (bfd_vma))
2594 +#define LZPLT_SIZE_SEQ2 (sizeof(plt_code_seq2))
2595 +
2596 +#define NUM_PLT_TRAMPOLINE_WORDS (sizeof (plt_trampoline) / sizeof (bfd_vma))
2597 +#define PLT_TRAMPOLINE_SIZE (sizeof(plt_trampoline))
2598 +
2599 +//#define FUNCTION_DESCRIPTOR_SIZE 12
2600 +#define FUNCTION_DESCRIPTOR_SIZE 8
2601 +/* Decide whether a reference to a symbol can be resolved locally or
2602 + not. If the symbol is protected, we want the local address, but
2603 + its function descriptor must be assigned by the dynamic linker. */
2604 +#define UBICOM32FPIC_SYM_LOCAL(INFO, H) \
2605 + (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
2606 + || ! elf_hash_table (INFO)->dynamic_sections_created)
2607 +#define UBICOM32FPIC_FUNCDESC_LOCAL(INFO, H) \
2608 + ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
2609 +
2610 +
2611 +static int
2612 +ubicom32fdpic_count_got_plt_entries (void **entryp, void *dinfo_)
2613 +{
2614 + struct ubicom32fdpic_relocs_info *entry = *entryp;
2615 + struct _ubicom32fdpic_dynamic_got_info *dinfo = dinfo_;
2616 + unsigned relocs = 0, fixups = 0;
2617 +
2618 + /* Allocate space for a GOT entry pointing to the symbol. */
2619 + if (entry->gotoffset_lo)
2620 + {
2621 + dinfo->gotoffset_lo += 4;
2622 + entry->relocs32++;
2623 + }
2624 +
2625 + /* Allocate space for a GOT entry pointing to the function
2626 + descriptor. */
2627 + if (entry->fd_gotoffset_lo)
2628 + {
2629 + dinfo->gotoffset_lo += 4;
2630 + entry->relocsfd++;
2631 + }
2632 + else if (entry->fd_gotoffset_hi)
2633 + {
2634 + dinfo->gotoffset_lo += 4;
2635 + entry->relocsfd++;
2636 + }
2637 +
2638 + /* Decide whether we need a PLT entry, a function descriptor in the
2639 + GOT, and a lazy PLT entry for this symbol. */
2640 + entry->plt = entry->call
2641 + && entry->symndx == -1 && ! UBICOM32FPIC_SYM_LOCAL (dinfo->info, entry->d.h)
2642 + && elf_hash_table (dinfo->info)->dynamic_sections_created;
2643 + entry->privfd = entry->plt
2644 + || ((entry->fd_gotoffset_lo || entry->fd_gotoffset_hi || entry->fd)
2645 + && (entry->symndx != -1
2646 + || UBICOM32FPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h)));
2647 + entry->lazyplt = entry->privfd
2648 + && entry->symndx == -1 && ! UBICOM32FPIC_SYM_LOCAL (dinfo->info, entry->d.h)
2649 + && ! (dinfo->info->flags & DF_BIND_NOW)
2650 + && elf_hash_table (dinfo->info)->dynamic_sections_created;
2651 +
2652 + /* Allocate space for a function descriptor. */
2653 + if (entry->privfd && entry->plt)
2654 + {
2655 + dinfo->fdplt += FUNCTION_DESCRIPTOR_SIZE;
2656 + entry->relocsfdv++;
2657 + }
2658 + else if (entry->privfd)
2659 + {
2660 + /* privfd with plt = 0 */
2661 + //printf("Privfd set with plt 0 gotoff_lo = %d fd_gotoffset_lo = %d entry = 0x%x\n", entry->gotoffset_lo, entry->fd_gotoffset_lo, entry);
2662 + //printf("symnxd = 0x%x sym_local = %d funcdesc_local = %d\n", entry->symndx,
2663 + // UBICOM32FPIC_SYM_LOCAL (dinfo->info, entry->d.h),
2664 + // UBICOM32FPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h));
2665 + //printf("Name = %s\n\n", entry->d.h->root.root.string);
2666 + dinfo->privfdplt += FUNCTION_DESCRIPTOR_SIZE;
2667 + entry->relocsfdv++;
2668 + }
2669 +
2670 +
2671 + if (entry->lazyplt)
2672 + {
2673 + //dinfo->lzplt += LZPLT_NORMAL_SIZE;
2674 + dinfo->num_plts++;
2675 +
2676 +#if 0
2677 + if (dinfo->num_plts > 256)
2678 + dinfo->lzplt += LZPLT_SIZE_SEQ1;
2679 + else
2680 + dinfo->lzplt += LZPLT_SIZE_SEQ2;
2681 +
2682 + DPRINTF("lzplt %d num_plt %d\n", dinfo->lzplt, dinfo->num_plts);
2683 +#endif
2684 + }
2685 +
2686 + if (!dinfo->info->executable || dinfo->info->pie)
2687 + relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
2688 + else
2689 + {
2690 + if (entry->symndx != -1 || UBICOM32FPIC_SYM_LOCAL (dinfo->info, entry->d.h))
2691 + {
2692 + if (entry->symndx != -1
2693 + || entry->d.h->root.type != bfd_link_hash_undefweak)
2694 + fixups += entry->relocs32 + 2 * entry->relocsfdv;
2695 + }
2696 + else
2697 + relocs += entry->relocs32 + entry->relocsfdv;
2698 +
2699 + if (entry->symndx != -1
2700 + || UBICOM32FPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
2701 + {
2702 + if (entry->symndx != -1
2703 + || entry->d.h->root.type != bfd_link_hash_undefweak)
2704 + fixups += entry->relocsfd;
2705 + }
2706 + else
2707 + relocs += entry->relocsfd;
2708 + }
2709 +
2710 + entry->dynrelocs += relocs;
2711 + entry->fixups += fixups;
2712 + dinfo->relocs += relocs;
2713 + dinfo->fixups += fixups;
2714 +
2715 + return 1;
2716 +}
2717 +
2718 +/* Create a Ubicom32 ELF linker hash table. */
2719 +static struct bfd_link_hash_table *
2720 +ubicom32fdpic_elf_link_hash_table_create (bfd *abfd)
2721 +{
2722 + struct ubicom32fdpic_elf_link_hash_table *ret;
2723 + bfd_size_type amt = sizeof (struct ubicom32fdpic_elf_link_hash_table);
2724 +
2725 + ret = bfd_zalloc (abfd, amt);
2726 + if (ret == NULL)
2727 + return NULL;
2728 +
2729 + if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
2730 + _bfd_elf_link_hash_newfunc,
2731 + sizeof (struct elf_link_hash_entry)))
2732 + {
2733 + free (ret);
2734 + return NULL;
2735 + }
2736 +
2737 + return &ret->elf.root;
2738 +}
2739 +
2740 +/* Compute a hash with the key fields of an ubicom32fdpic_relocs_info entry. */
2741 +static hashval_t
2742 +ubicom32fdpic_relocs_info_hash (const void *entry_)
2743 +{
2744 + const struct ubicom32fdpic_relocs_info *entry = entry_;
2745 +
2746 + return (entry->symndx == -1
2747 + ? (long) entry->d.h->root.root.hash
2748 + : entry->symndx + (long) entry->d.abfd->id * 257) + entry->addend;
2749 +}
2750 +
2751 +/* Test whether the key fields of two ubicom32fdpic_relocs_info entries are
2752 + identical. */
2753 +static int
2754 +ubicom32fdpic_relocs_info_eq (const void *entry1, const void *entry2)
2755 +{
2756 + const struct ubicom32fdpic_relocs_info *e1 = entry1;
2757 + const struct ubicom32fdpic_relocs_info *e2 = entry2;
2758 +
2759 + return e1->symndx == e2->symndx && e1->addend == e2->addend
2760 + && (e1->symndx == -1 ? e1->d.h == e2->d.h : e1->d.abfd == e2->d.abfd);
2761 +}
2762 +
2763 +/* Find or create an entry in a hash table HT that matches the key
2764 + fields of the given ENTRY. If it's not found, memory for a new
2765 + entry is allocated in ABFD's obstack. */
2766 +static struct ubicom32fdpic_relocs_info *
2767 +ubicom32fdpic_relocs_info_find (struct htab *ht,
2768 + bfd *abfd,
2769 + const struct ubicom32fdpic_relocs_info *entry,
2770 + enum insert_option insert)
2771 +{
2772 + struct ubicom32fdpic_relocs_info **loc =
2773 + (struct ubicom32fdpic_relocs_info **) htab_find_slot (ht, entry, insert);
2774 +
2775 + if (! loc)
2776 + return NULL;
2777 +
2778 + if (*loc)
2779 + return *loc;
2780 +
2781 + *loc = bfd_zalloc (abfd, sizeof (**loc));
2782 +
2783 + if (! *loc)
2784 + return *loc;
2785 +
2786 + (*loc)->symndx = entry->symndx;
2787 + (*loc)->d = entry->d;
2788 + (*loc)->addend = entry->addend;
2789 + (*loc)->plt_entry = (bfd_vma)-1;
2790 + /* (*loc)->lzplt_entry = (bfd_vma)-1; */
2791 +
2792 + return *loc;
2793 +}
2794 +
2795 +/* Obtain the address of the entry in HT associated with H's symbol +
2796 + addend, creating a new entry if none existed. ABFD is only used
2797 + for memory allocation purposes. */
2798 +inline static struct ubicom32fdpic_relocs_info *
2799 +ubicom32fdpic_relocs_info_for_global (struct htab *ht,
2800 + bfd *abfd,
2801 + struct elf_link_hash_entry *h,
2802 + bfd_vma addend,
2803 + enum insert_option insert)
2804 +{
2805 + struct ubicom32fdpic_relocs_info entry;
2806 +
2807 + entry.symndx = -1;
2808 + entry.d.h = h;
2809 + entry.addend = addend;
2810 +
2811 + return ubicom32fdpic_relocs_info_find (ht, abfd, &entry, insert);
2812 +}
2813 +
2814 +/* Obtain the address of the entry in HT associated with the SYMNDXth
2815 + local symbol of the input bfd ABFD, plus the addend, creating a new
2816 + entry if none existed. */
2817 +inline static struct ubicom32fdpic_relocs_info *
2818 +ubicom32fdpic_relocs_info_for_local (struct htab *ht,
2819 + bfd *abfd,
2820 + long symndx,
2821 + bfd_vma addend,
2822 + enum insert_option insert)
2823 +{
2824 + struct ubicom32fdpic_relocs_info entry;
2825 +
2826 + entry.symndx = symndx;
2827 + entry.d.abfd = abfd;
2828 + entry.addend = addend;
2829 +
2830 + return ubicom32fdpic_relocs_info_find (ht, abfd, &entry, insert);
2831 +}
2832 +
2833 +/* Merge fields set by check_relocs() of two entries that end up being
2834 + mapped to the same (presumably global) symbol. */
2835 +
2836 +inline static void
2837 +ubicom32fdpic_pic_merge_early_relocs_info (struct ubicom32fdpic_relocs_info *e2,
2838 + struct ubicom32fdpic_relocs_info const *e1)
2839 +{
2840 + e2->gotoffset_lo |= e1->gotoffset_lo;
2841 + e2->gotoffset_hi |= e1->gotoffset_hi;
2842 + e2->fd_gotoffset_lo |= e1->fd_gotoffset_lo;
2843 + e2->fd_gotoffset_hi |= e1->fd_gotoffset_hi;
2844 + e2->fd |= e1->fd;
2845 + e2->gotoff |= e1->gotoff;
2846 + e2->call |= e1->call;
2847 + e2->sym |= e1->sym;
2848 +}
2849 +
2850 +/* Add a dynamic relocation to the SRELOC section. */
2851 +
2852 +inline static bfd_vma
2853 +ubicom32fdpic_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
2854 + int reloc_type, long dynindx, bfd_vma addend,
2855 + struct ubicom32fdpic_relocs_info *entry)
2856 +{
2857 + Elf_Internal_Rela outrel;
2858 + bfd_vma reloc_offset;
2859 +
2860 + outrel.r_offset = offset;
2861 + outrel.r_info = ELF32_R_INFO (dynindx, reloc_type);
2862 + outrel.r_addend = addend;
2863 +
2864 + reloc_offset = sreloc->reloc_count * sizeof (Elf32_External_Rel);
2865 + BFD_ASSERT (reloc_offset < sreloc->size);
2866 + bfd_elf32_swap_reloc_out (output_bfd, &outrel,
2867 + sreloc->contents + reloc_offset);
2868 + sreloc->reloc_count++;
2869 +
2870 + /* If the entry's index is zero, this relocation was probably to a
2871 + linkonce section that got discarded. We reserved a dynamic
2872 + relocation, but it was for another entry than the one we got at
2873 + the time of emitting the relocation. Unfortunately there's no
2874 + simple way for us to catch this situation, since the relocation
2875 + is cleared right before calling relocate_section, at which point
2876 + we no longer know what the relocation used to point to. */
2877 + if (entry->symndx)
2878 + {
2879 + BFD_ASSERT (entry->dynrelocs > 0);
2880 + entry->dynrelocs--;
2881 + }
2882 +
2883 + return reloc_offset;
2884 +}
2885 +
2886 +/* Add a fixup to the ROFIXUP section. */
2887 +
2888 +static bfd_vma
2889 +ubicom32fdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
2890 + struct ubicom32fdpic_relocs_info *entry)
2891 +{
2892 + bfd_vma fixup_offset;
2893 +
2894 + if (rofixup->flags & SEC_EXCLUDE)
2895 + return -1;
2896 +
2897 + fixup_offset = rofixup->reloc_count * 4;
2898 + if (rofixup->contents)
2899 + {
2900 + BFD_ASSERT (fixup_offset < rofixup->size);
2901 + bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
2902 + }
2903 + rofixup->reloc_count++;
2904 +
2905 + if (entry && entry->symndx)
2906 + {
2907 + /* See discussion about symndx == 0 in _ubicom32fdpic_add_dyn_reloc
2908 + above. */
2909 + BFD_ASSERT (entry->fixups > 0);
2910 + entry->fixups--;
2911 + }
2912 +
2913 + return fixup_offset;
2914 +}
2915 +
2916 +/* Find the segment number in which OSEC, and output section, is
2917 + located. */
2918 +
2919 +static unsigned
2920 +ubicom32fdpic_osec_to_segment (bfd *output_bfd, asection *osec)
2921 +{
2922 + Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section (output_bfd, osec);
2923 +
2924 + return (p != NULL) ? p - elf_tdata (output_bfd)->phdr : -1;
2925 +}
2926 +
2927 +inline static bfd_boolean
2928 +ubicom32fdpic_osec_readonly_p (bfd *output_bfd, asection *osec)
2929 +{
2930 + unsigned seg = ubicom32fdpic_osec_to_segment (output_bfd, osec);
2931 +
2932 + return ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W);
2933 +}
2934 +
2935 +#if 0
2936 +static bfd_vma plt_trampoline[] = {
2937 + 0x00002400, //ret (a0)
2938 +};
2939 +#endif
2940 +
2941 +/* Generate relocations for GOT entries, function descriptors, and
2942 + code for PLT and lazy PLT entries. */
2943 +
2944 +static bfd_boolean
2945 +ubicom32fdpic_emit_got_relocs_plt_entries (struct ubicom32fdpic_relocs_info *entry,
2946 + bfd *output_bfd,
2947 + struct bfd_link_info *info,
2948 + asection *sec,
2949 + Elf_Internal_Sym *sym,
2950 + bfd_vma addend)
2951 +
2952 +{
2953 + bfd_vma fd_lazy_rel_offset = (bfd_vma)-1;
2954 + int dynindx = -1;
2955 +
2956 + if (entry->done)
2957 + return TRUE;
2958 + entry->done = 1;
2959 +
2960 + if (entry->got_entry || entry->fdgot_entry || entry->fd_entry)
2961 + {
2962 + DPRINTF(" emit %p got %d fdgot %d fd %d addend %d\n", entry, entry->got_entry, entry->fdgot_entry, entry->fd_entry, addend);
2963 + /* If the symbol is dynamic, consider it for dynamic
2964 + relocations, otherwise decay to section + offset. */
2965 + if (entry->symndx == -1 && entry->d.h->dynindx != -1)
2966 + dynindx = entry->d.h->dynindx;
2967 + else
2968 + {
2969 + if (sec->output_section
2970 + && ! bfd_is_abs_section (sec->output_section)
2971 + && ! bfd_is_und_section (sec->output_section))
2972 + dynindx = elf_section_data (sec->output_section)->dynindx;
2973 + else
2974 + dynindx = 0;
2975 + }
2976 + }
2977 +
2978 + /* Generate relocation for GOT entry pointing to the symbol. */
2979 + if (entry->got_entry)
2980 + {
2981 + DPRINTF(" emit got entry %d:%p\n", entry->got_entry, entry);
2982 +
2983 + int idx = dynindx;
2984 + bfd_vma ad = addend;
2985 +
2986 + /* If the symbol is dynamic but binds locally, use
2987 + section+offset. */
2988 + if (sec && (entry->symndx != -1
2989 + || UBICOM32FDPIC_SYM_LOCAL (info, entry->d.h)))
2990 + {
2991 + if (entry->symndx == -1)
2992 + ad += entry->d.h->root.u.def.value;
2993 + else
2994 + ad += sym->st_value;
2995 + ad += sec->output_offset;
2996 + if (sec->output_section && elf_section_data (sec->output_section))
2997 + idx = elf_section_data (sec->output_section)->dynindx;
2998 + else
2999 + idx = 0;
3000 + }
3001 +
3002 + /* If we're linking an executable at a fixed address, we can
3003 + omit the dynamic relocation as long as the symbol is local to
3004 + this module. */
3005 + if (info->executable && !info->pie
3006 + && (entry->symndx != -1
3007 + || UBICOM32FDPIC_SYM_LOCAL (info, entry->d.h)))
3008 + {
3009 + if (sec)
3010 + ad += sec->output_section->vma;
3011 + if (entry->symndx != -1
3012 + || entry->d.h->root.type != bfd_link_hash_undefweak)
3013 + ubicom32fdpic_add_rofixup (output_bfd,
3014 + ubicom32fdpic_gotfixup_section (info),
3015 + ubicom32fdpic_got_section (info)->output_section->vma
3016 + + ubicom32fdpic_got_section (info)->output_offset
3017 + + ubicom32fdpic_got_initial_offset (info)
3018 + + entry->got_entry, entry);
3019 + }
3020 + else
3021 + ubicom32fdpic_add_dyn_reloc (output_bfd, ubicom32fdpic_gotrel_section (info),
3022 + _bfd_elf_section_offset
3023 + (output_bfd, info,
3024 + ubicom32fdpic_got_section (info),
3025 + ubicom32fdpic_got_initial_offset (info)
3026 + + entry->got_entry)
3027 + + ubicom32fdpic_got_section (info)
3028 + ->output_section->vma
3029 + + ubicom32fdpic_got_section (info)->output_offset,
3030 + R_UBICOM32_32, idx, ad, entry);
3031 +
3032 + bfd_put_32 (output_bfd, ad,
3033 + ubicom32fdpic_got_section (info)->contents
3034 + + ubicom32fdpic_got_initial_offset (info)
3035 + + entry->got_entry);
3036 + }
3037 +
3038 + /* Generate relocation for GOT entry pointing to a canonical
3039 + function descriptor. */
3040 + if (entry->fdgot_entry)
3041 + {
3042 + DPRINTF(" emit got fdgot entry %d:%p\n", entry->fdgot_entry, entry);
3043 +
3044 + int reloc, idx;
3045 + bfd_vma ad = 0;
3046 +
3047 + if (! (entry->symndx == -1
3048 + && entry->d.h->root.type == bfd_link_hash_undefweak
3049 + && UBICOM32FDPIC_SYM_LOCAL (info, entry->d.h)))
3050 + {
3051 + /* If the symbol is dynamic and there may be dynamic symbol
3052 + resolution because we are, or are linked with, a shared
3053 + library, emit a FUNCDESC relocation such that the dynamic
3054 + linker will allocate the function descriptor. If the
3055 + symbol needs a non-local function descriptor but binds
3056 + locally (e.g., its visibility is protected, emit a
3057 + dynamic relocation decayed to section+offset. */
3058 + if (entry->symndx == -1
3059 + && ! UBICOM32FDPIC_FUNCDESC_LOCAL (info, entry->d.h)
3060 + && UBICOM32FDPIC_SYM_LOCAL (info, entry->d.h)
3061 + && !(info->executable && !info->pie))
3062 + {
3063 + reloc = R_UBICOM32_FUNCDESC;
3064 + idx = elf_section_data (entry->d.h->root.u.def.section
3065 + ->output_section)->dynindx;
3066 + ad = entry->d.h->root.u.def.section->output_offset
3067 + + entry->d.h->root.u.def.value;
3068 + }
3069 + else if (entry->symndx == -1
3070 + && ! UBICOM32FDPIC_FUNCDESC_LOCAL (info, entry->d.h))
3071 + {
3072 + reloc = R_UBICOM32_FUNCDESC;
3073 + idx = dynindx;
3074 + ad = addend;
3075 + if (ad)
3076 + return FALSE;
3077 + }
3078 + else
3079 + {
3080 + /* Otherwise, we know we have a private function descriptor,
3081 + so reference it directly. */
3082 + if (elf_hash_table (info)->dynamic_sections_created)
3083 + BFD_ASSERT (entry->privfd);
3084 + reloc = R_UBICOM32_32;
3085 + idx = elf_section_data (ubicom32fdpic_got_section (info)
3086 + ->output_section)->dynindx;
3087 + ad = ubicom32fdpic_got_section (info)->output_offset
3088 + + ubicom32fdpic_got_initial_offset (info) + entry->fd_entry;
3089 + }
3090 +
3091 + /* If there is room for dynamic symbol resolution, emit the
3092 + dynamic relocation. However, if we're linking an
3093 + executable at a fixed location, we won't have emitted a
3094 + dynamic symbol entry for the got section, so idx will be
3095 + zero, which means we can and should compute the address
3096 + of the private descriptor ourselves. */
3097 + if (info->executable && !info->pie
3098 + && (entry->symndx != -1
3099 + || UBICOM32FDPIC_FUNCDESC_LOCAL (info, entry->d.h)))
3100 + {
3101 + ad += ubicom32fdpic_got_section (info)->output_section->vma;
3102 + ubicom32fdpic_add_rofixup (output_bfd,
3103 + ubicom32fdpic_gotfixup_section (info),
3104 + ubicom32fdpic_got_section (info)
3105 + ->output_section->vma
3106 + + ubicom32fdpic_got_section (info)
3107 + ->output_offset
3108 + + ubicom32fdpic_got_initial_offset (info)
3109 + + entry->fdgot_entry, entry);
3110 + }
3111 + else
3112 + ubicom32fdpic_add_dyn_reloc (output_bfd,
3113 + ubicom32fdpic_gotrel_section (info),
3114 + _bfd_elf_section_offset
3115 + (output_bfd, info,
3116 + ubicom32fdpic_got_section (info),
3117 + ubicom32fdpic_got_initial_offset (info)
3118 + + entry->fdgot_entry)
3119 + + ubicom32fdpic_got_section (info)
3120 + ->output_section->vma
3121 + + ubicom32fdpic_got_section (info)
3122 + ->output_offset,
3123 + reloc, idx, ad, entry);
3124 + }
3125 +
3126 + bfd_put_32 (output_bfd, ad,
3127 + ubicom32fdpic_got_section (info)->contents
3128 + + ubicom32fdpic_got_initial_offset (info)
3129 + + entry->fdgot_entry);
3130 + }
3131 +
3132 + /* Generate relocation to fill in a private function descriptor in
3133 + the GOT. */
3134 + if (entry->fd_entry)
3135 + {
3136 +
3137 + int idx = dynindx;
3138 + bfd_vma ad = addend;
3139 + bfd_vma ofst;
3140 + long lowword, highword;
3141 +
3142 + /* If the symbol is dynamic but binds locally, use
3143 + section+offset. */
3144 + if (sec && (entry->symndx != -1
3145 + || UBICOM32FDPIC_SYM_LOCAL (info, entry->d.h)))
3146 + {
3147 + if (entry->symndx == -1)
3148 + ad += entry->d.h->root.u.def.value;
3149 + else
3150 + ad += sym->st_value;
3151 + ad += sec->output_offset;
3152 + if (sec->output_section && elf_section_data (sec->output_section))
3153 + idx = elf_section_data (sec->output_section)->dynindx;
3154 + else
3155 + idx = 0;
3156 + }
3157 +
3158 + /* If we're linking an executable at a fixed address, we can
3159 + omit the dynamic relocation as long as the symbol is local to
3160 + this module. */
3161 + if (info->executable && !info->pie
3162 + && (entry->symndx != -1 || UBICOM32FDPIC_SYM_LOCAL (info, entry->d.h)))
3163 + {
3164 + if (sec)
3165 + ad += sec->output_section->vma;
3166 + ofst = 0;
3167 + if (entry->symndx != -1
3168 + || entry->d.h->root.type != bfd_link_hash_undefweak)
3169 + {
3170 + ubicom32fdpic_add_rofixup (output_bfd,
3171 + ubicom32fdpic_gotfixup_section (info),
3172 + ubicom32fdpic_got_section (info)
3173 + ->output_section->vma
3174 + + ubicom32fdpic_got_section (info)
3175 + ->output_offset
3176 + + ubicom32fdpic_got_initial_offset (info)
3177 + + entry->fd_entry, entry);
3178 + ubicom32fdpic_add_rofixup (output_bfd,
3179 + ubicom32fdpic_gotfixup_section (info),
3180 + ubicom32fdpic_got_section (info)
3181 + ->output_section->vma
3182 + + ubicom32fdpic_got_section (info)
3183 + ->output_offset
3184 + + ubicom32fdpic_got_initial_offset (info)
3185 + + entry->fd_entry + 4, entry);
3186 + }
3187 + }
3188 + else
3189 + {
3190 + ofst
3191 + = ubicom32fdpic_add_dyn_reloc (output_bfd,
3192 + entry->lazyplt
3193 + ? ubicom32fdpic_pltrel_section (info)
3194 + : ubicom32fdpic_gotrel_section (info),
3195 + _bfd_elf_section_offset
3196 + (output_bfd, info,
3197 + ubicom32fdpic_got_section (info),
3198 + ubicom32fdpic_got_initial_offset (info)
3199 + + entry->fd_entry)
3200 + + ubicom32fdpic_got_section (info)
3201 + ->output_section->vma
3202 + + ubicom32fdpic_got_section (info)
3203 + ->output_offset,
3204 + R_UBICOM32_FUNCDESC_VALUE, idx, ad, entry);
3205 + }
3206 +
3207 + /* If we've omitted the dynamic relocation, just emit the fixed
3208 + addresses of the symbol and of the local GOT base offset. */
3209 + if (info->executable && !info->pie && sec && sec->output_section)
3210 + {
3211 + lowword = ad;
3212 + highword = ubicom32fdpic_got_section (info)->output_section->vma
3213 + + ubicom32fdpic_got_section (info)->output_offset
3214 + + ubicom32fdpic_got_initial_offset (info);
3215 + }
3216 + else if (entry->lazyplt)
3217 + {
3218 + if (ad)
3219 + return FALSE;
3220 +
3221 + fd_lazy_rel_offset = ofst;
3222 +
3223 + /* A function descriptor used for lazy or local resolving is
3224 + initialized such that its high word contains the output
3225 + section index in which the PLT entries are located, and
3226 + the low word contains the address to the base of the PLT.
3227 + That location contains the PLT trampoline instruction ret 0(a0).
3228 + assigned to that section. */
3229 + lowword = ubicom32fdpic_plt_section (info)->output_offset
3230 + + ubicom32fdpic_plt_section (info)->output_section->vma + entry->plt_trampoline_entry;
3231 + highword = ubicom32fdpic_osec_to_segment
3232 + (output_bfd, ubicom32fdpic_plt_section (info)->output_section);
3233 + }
3234 + else
3235 + {
3236 + /* A function descriptor for a local function gets the index
3237 + of the section. For a non-local function, it's
3238 + disregarded. */
3239 + lowword = ad;
3240 + if (entry->symndx == -1 && entry->d.h->dynindx != -1
3241 + && entry->d.h->dynindx == idx)
3242 + highword = 0;
3243 + else
3244 + highword = ubicom32fdpic_osec_to_segment
3245 + (output_bfd, sec->output_section);
3246 + }
3247 +
3248 + DPRINTF(" emit got fd_entry %d:%p lw 0x%x hw 0x%x fd_l_r_off 0x%x\n", entry->fd_entry, entry, lowword, highword, fd_lazy_rel_offset);
3249 +
3250 +
3251 + bfd_put_32 (output_bfd, lowword,
3252 + ubicom32fdpic_got_section (info)->contents
3253 + + ubicom32fdpic_got_initial_offset (info)
3254 + + entry->fd_entry);
3255 + bfd_put_32 (output_bfd, highword,
3256 + ubicom32fdpic_got_section (info)->contents
3257 + + ubicom32fdpic_got_initial_offset (info)
3258 + + entry->fd_entry + 4);
3259 +
3260 +#if 0
3261 + /* Load the fixup offset here. */
3262 + bfd_put_32 (output_bfd, fd_lazy_rel_offset,
3263 + ubicom32fdpic_got_section (info)->contents
3264 + + ubicom32fdpic_got_initial_offset (info)
3265 + + entry->fd_entry + 8);
3266 +#endif
3267 +
3268 + entry->rel_offset = fd_lazy_rel_offset;
3269 + }
3270 +
3271 + /* Generate code for the PLT entry. */
3272 + if (entry->plt_entry != (bfd_vma) -1)
3273 + {
3274 + static output_trampoline_code = 1;
3275 + bfd_byte *plt_output_code = ubicom32fdpic_plt_section (info)->contents;
3276 + int i;
3277 + bfd_vma *plt_code;
3278 +
3279 + DPRINTF(" emit fd entry %x:%p plt=%2x code=%p\n", entry->fd_entry, entry, entry->plt_entry, plt_output_code);
3280 +
3281 +#if 0
3282 + if (output_trampoline_code)
3283 + {
3284 + /* output the trampoline code.*/
3285 + bfd_put_32 (output_bfd, plt_trampoline[0], plt_output_code);
3286 + }
3287 +#endif
3288 +
3289 + /* output the trampoline entry. */
3290 +
3291 + plt_output_code += entry->plt_trampoline_entry;
3292 + plt_code = plt_trampoline;
3293 + plt_code[0] = (plt_code[0] & 0xFFFF0000) | (entry->rel_offset &0xffff);
3294 + bfd_put_32 (output_bfd, plt_code[0], plt_output_code);
3295 + bfd_put_32 (output_bfd, plt_code[1], plt_output_code + 4);
3296 +
3297 +
3298 + /* output the plt itself. */
3299 + plt_output_code = ubicom32fdpic_plt_section (info)->contents;
3300 + plt_output_code += entry->plt_entry;
3301 + BFD_ASSERT (entry->fd_entry);
3302 +
3303 + if (entry->plt_type == 2)
3304 + {
3305 + bfd_vma data_lo = (entry->fd_entry >> 2) & 0xff;
3306 +
3307 + /* Output seqence 2. */
3308 + plt_code = plt_code_seq2;
3309 +
3310 + /* Code the entry into the PDEC instruction. */
3311 + plt_code[0] &= 0xFFFFF8E0;
3312 + plt_code[0] |= (data_lo & 0x1F);
3313 + plt_code[0] |= (data_lo & 0xE0) << 3;
3314 +
3315 + /* Write out the sequence. */
3316 + for (i = 0; i < NUM_PLT_CODE_WORDS_SEQ2; i++)
3317 + {
3318 + bfd_put_32 (output_bfd, plt_code[i], plt_output_code);
3319 + plt_output_code += 4;
3320 + }
3321 + }
3322 + else if (entry->plt_type == 1)
3323 + {
3324 + /* Outupt sequence 1 */
3325 + plt_code = plt_code_seq1;
3326 +
3327 + /* Code the entry into the movei instruction. */
3328 + plt_code[0] = (plt_code[0] & 0xFFFF0000) | ((entry->fd_entry >> 2) & 0xFFFF);
3329 +
3330 + /* Write out the sequence. */
3331 + for (i = 0; i < NUM_PLT_CODE_WORDS_SEQ1; i++)
3332 + {
3333 + bfd_put_32 (output_bfd, plt_code[i], plt_output_code);
3334 + plt_output_code += 4;
3335 + }
3336 + }
3337 + else
3338 + BFD_ASSERT(0);
3339 +
3340 +#if 0
3341 + /* We have to output 5 words. The very first movei has to be modified with whatever is in fd_entry. */
3342 + plt_code[0] = (plt_code[0] & 0xFFFF0000) | ((entry->fd_entry >> 2) & 0xFFFF);
3343 +
3344 + for (i = 0; i < NUM_PLT_CODE_WORDS; i++)
3345 + {
3346 + bfd_put_32 (output_bfd, plt_code[i], plt_output_code);
3347 + plt_output_code += 4;
3348 + }
3349 +#endif
3350 + }
3351 +
3352 + return TRUE;
3353 +}
3354 +
3355 +\f
3356 +/* Create a .got section, as well as its additional info field. This
3357 + is almost entirely copied from
3358 + elflink.c:_bfd_elf_create_got_section(). */
3359 +
3360 +static bfd_boolean
3361 +ubicom32fdpic_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
3362 +{
3363 + flagword flags, pltflags;
3364 + asection *s;
3365 + struct elf_link_hash_entry *h;
3366 + const struct elf_backend_data *bed = get_elf_backend_data (abfd);
3367 + int ptralign;
3368 + int offset;
3369 +
3370 + /* This function may be called more than once. */
3371 + s = bfd_get_section_by_name (abfd, ".got");
3372 + if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
3373 + return TRUE;
3374 +
3375 + /* Machine specific: although pointers are 32-bits wide, we want the
3376 + GOT to be aligned to a 64-bit boundary, such that function
3377 + descriptors in it can be accessed with 64-bit loads and
3378 + stores. */
3379 + ptralign = 3;
3380 +
3381 + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
3382 + | SEC_LINKER_CREATED);
3383 + pltflags = flags;
3384 +
3385 + s = bfd_make_section_with_flags (abfd, ".got", flags);
3386 + if (s == NULL
3387 + || !bfd_set_section_alignment (abfd, s, ptralign))
3388 + return FALSE;
3389 +
3390 + if (bed->want_got_plt)
3391 + {
3392 + s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
3393 + if (s == NULL
3394 + || !bfd_set_section_alignment (abfd, s, ptralign))
3395 + return FALSE;
3396 + }
3397 +
3398 + if (bed->want_got_sym)
3399 + {
3400 + /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
3401 + (or .got.plt) section. We don't do this in the linker script
3402 + because we don't want to define the symbol if we are not creating
3403 + a global offset table. */
3404 + h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
3405 + elf_hash_table (info)->hgot = h;
3406 + if (h == NULL)
3407 + return FALSE;
3408 +
3409 + /* Machine-specific: we want the symbol for executables as
3410 + well. */
3411 + if (! bfd_elf_link_record_dynamic_symbol (info, h))
3412 + return FALSE;
3413 + }
3414 +
3415 + /* The first bit of the global offset table is the header. */
3416 + s->size += bed->got_header_size;
3417 +
3418 + /* This is the machine-specific part. Create and initialize section
3419 + data for the got. */
3420 + if (IS_FDPIC (abfd))
3421 + {
3422 + ubicom32fdpic_got_section (info) = s;
3423 + ubicom32fdpic_relocs_info (info) = htab_try_create (1,
3424 + ubicom32fdpic_relocs_info_hash,
3425 + ubicom32fdpic_relocs_info_eq,
3426 + (htab_del) NULL);
3427 + if (! ubicom32fdpic_relocs_info (info))
3428 + return FALSE;
3429 +
3430 + s = bfd_make_section_with_flags (abfd, ".rel.got",
3431 + (flags | SEC_READONLY));
3432 + if (s == NULL
3433 + || ! bfd_set_section_alignment (abfd, s, 2))
3434 + return FALSE;
3435 +
3436 + ubicom32fdpic_gotrel_section (info) = s;
3437 +
3438 + /* Machine-specific. */
3439 + s = bfd_make_section_with_flags (abfd, ".rofixup",
3440 + (flags | SEC_READONLY));
3441 + if (s == NULL
3442 + || ! bfd_set_section_alignment (abfd, s, 2))
3443 + return FALSE;
3444 +
3445 + ubicom32fdpic_gotfixup_section (info) = s;
3446 + offset = -2048;
3447 + flags = BSF_GLOBAL;
3448 + }
3449 + else
3450 + {
3451 + offset = 2048;
3452 + flags = BSF_GLOBAL | BSF_WEAK;
3453 + }
3454 +
3455 + return TRUE;
3456 +}
3457 +
3458 +/* Make sure the got and plt sections exist, and that our pointers in
3459 + the link hash table point to them. */
3460 +
3461 +static bfd_boolean
3462 +ubicom32fdpic_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
3463 +{ flagword flags, pltflags;
3464 + asection *s;
3465 + const struct elf_backend_data *bed = get_elf_backend_data (abfd);
3466 +
3467 + /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
3468 + .rel[a].bss sections. */
3469 + DPRINTF(" ubicom32fdpic_elf_create_dynamic_sections %p %p\n", abfd, info);
3470 +
3471 + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
3472 + | SEC_LINKER_CREATED);
3473 +
3474 + pltflags = flags;
3475 + pltflags |= SEC_CODE;
3476 + if (bed->plt_not_loaded)
3477 + pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);