2001-01-23 Kazu Hirata <kazu@hxi.com>
[external/binutils.git] / bfd / elf32-i860.c
1 /* Intel i860 specific support for 32-bit ELF.
2    Copyright 1993, 2000 Free Software Foundation, Inc.
3
4    Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/i860.h"
27
28 /* Prototypes.  */
29 static reloc_howto_type *lookup_howto
30   PARAMS ((unsigned int));
31
32 static reloc_howto_type *elf32_i860_reloc_type_lookup
33   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
34
35 static void elf32_i860_info_to_howto_rela
36   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
37
38 static bfd_reloc_status_type elf32_i860_relocate_splitn
39   PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
40
41 static bfd_reloc_status_type elf32_i860_relocate_pc16
42   PARAMS ((bfd *,  asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
43
44 static bfd_reloc_status_type elf32_i860_relocate_pc26
45   PARAMS ((bfd *,  asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
46
47 static bfd_reloc_status_type elf32_i860_relocate_highadj
48   PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
49
50 static boolean elf32_i860_relocate_section
51   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
52            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
53
54 static bfd_reloc_status_type i860_final_link_relocate
55   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
56            Elf_Internal_Rela *, bfd_vma));
57
58 static boolean elf32_i860_is_local_label_name
59   PARAMS ((bfd *, const char *));
60
61 /* This howto table is preliminary.  */
62 static reloc_howto_type elf32_i860_howto_table [] =
63 {
64   /* This relocation does nothing.  */
65   HOWTO (R_860_NONE,            /* type */
66          0,                     /* rightshift */
67          2,                     /* size (0 = byte, 1 = short, 2 = long) */
68          32,                    /* bitsize */
69          false,                 /* pc_relative */
70          0,                     /* bitpos */
71          complain_overflow_bitfield, /* complain_on_overflow */
72          bfd_elf_generic_reloc, /* special_function */
73          "R_860_NONE",          /* name */
74          false,                 /* partial_inplace */
75          0,                     /* src_mask */
76          0,                     /* dst_mask */
77          false),                /* pcrel_offset */
78
79   /* A 32-bit absolute relocation.  */
80   HOWTO (R_860_32,              /* type */
81          0,                     /* rightshift */
82          2,                     /* size (0 = byte, 1 = short, 2 = long) */
83          32,                    /* bitsize */
84          false,                 /* pc_relative */
85          0,                     /* bitpos */
86          complain_overflow_bitfield, /* complain_on_overflow */
87          bfd_elf_generic_reloc, /* special_function */
88          "R_860_32",            /* name */
89          false,                 /* partial_inplace */
90          0xffffffff,            /* src_mask */
91          0xffffffff,            /* dst_mask */
92          false),                /* pcrel_offset */
93
94   HOWTO (R_860_COPY,            /* type */
95          0,                     /* rightshift */
96          2,                     /* size (0 = byte, 1 = short, 2 = long) */
97          32,                    /* bitsize */
98          false,                 /* pc_relative */
99          0,                     /* bitpos */
100          complain_overflow_bitfield, /* complain_on_overflow */
101          bfd_elf_generic_reloc, /* special_function */
102          "R_860_COPY",          /* name */
103          true,                  /* partial_inplace */
104          0xffffffff,            /* src_mask */
105          0xffffffff,            /* dst_mask */
106          false),                /* pcrel_offset */
107
108   HOWTO (R_860_GLOB_DAT,        /* type */
109          0,                     /* rightshift */
110          2,                     /* size (0 = byte, 1 = short, 2 = long) */
111          32,                    /* bitsize */
112          false,                 /* pc_relative */
113          0,                     /* bitpos */
114          complain_overflow_bitfield, /* complain_on_overflow */
115          bfd_elf_generic_reloc, /* special_function */
116          "R_860_GLOB_DAT",      /* name */
117          true,                  /* partial_inplace */
118          0xffffffff,            /* src_mask */
119          0xffffffff,            /* dst_mask */
120          false),                /* pcrel_offset */
121
122   HOWTO (R_860_JUMP_SLOT,       /* type */
123          0,                     /* rightshift */
124          2,                     /* size (0 = byte, 1 = short, 2 = long) */
125          32,                    /* bitsize */
126          false,                 /* pc_relative */
127          0,                     /* bitpos */
128          complain_overflow_bitfield, /* complain_on_overflow */
129          bfd_elf_generic_reloc, /* special_function */
130          "R_860_JUMP_SLOT",     /* name */
131          true,                  /* partial_inplace */
132          0xffffffff,            /* src_mask */
133          0xffffffff,            /* dst_mask */
134          false),                /* pcrel_offset */
135
136   HOWTO (R_860_RELATIVE,        /* type */
137          0,                     /* rightshift */
138          2,                     /* size (0 = byte, 1 = short, 2 = long) */
139          32,                    /* bitsize */
140          false,                 /* pc_relative */
141          0,                     /* bitpos */
142          complain_overflow_bitfield, /* complain_on_overflow */
143          bfd_elf_generic_reloc, /* special_function */
144          "R_860_RELATIVE",      /* name */
145          true,                  /* partial_inplace */
146          0xffffffff,            /* src_mask */
147          0xffffffff,            /* dst_mask */
148          false),                /* pcrel_offset */
149
150   /* A 26-bit PC-relative relocation.  */
151   HOWTO (R_860_PC26,            /* type */
152          2,                     /* rightshift */
153          2,                     /* size (0 = byte, 1 = short, 2 = long) */
154          26,                    /* bitsize */
155          true,                  /* pc_relative */
156          0,                     /* bitpos */
157          complain_overflow_bitfield, /* complain_on_overflow */
158          bfd_elf_generic_reloc, /* special_function */
159          "R_860_PC26",          /* name */
160          false,                 /* partial_inplace */
161          0x3ffffff,             /* src_mask */
162          0x3ffffff,             /* dst_mask */
163          true),                 /* pcrel_offset */
164
165   HOWTO (R_860_PLT26,           /* type */
166          0,                     /* rightshift */
167          2,                     /* size (0 = byte, 1 = short, 2 = long) */
168          26,                    /* bitsize */
169          true,                  /* pc_relative */
170          0,                     /* bitpos */
171          complain_overflow_bitfield, /* complain_on_overflow */
172          bfd_elf_generic_reloc, /* special_function */
173          "R_860_PLT26",         /* name */
174          true,                  /* partial_inplace */
175          0xffffffff,            /* src_mask */
176          0xffffffff,            /* dst_mask */
177          true),                 /* pcrel_offset */
178
179   /* A 16-bit PC-relative relocation.  */
180   HOWTO (R_860_PC16,            /* type */
181          2,                     /* rightshift */
182          2,                     /* size (0 = byte, 1 = short, 2 = long) */
183          16,                    /* bitsize */
184          true,                  /* pc_relative */
185          0,                     /* bitpos */
186          complain_overflow_bitfield, /* complain_on_overflow */
187          bfd_elf_generic_reloc, /* special_function */
188          "R_860_PC16",          /* name */
189          false,                 /* partial_inplace */
190          0x1f07ff,              /* src_mask */
191          0x1f07ff,              /* dst_mask */
192          true),                 /* pcrel_offset */
193
194   HOWTO (R_860_LOW0,            /* type */
195          0,                     /* rightshift */
196          2,                     /* size (0 = byte, 1 = short, 2 = long) */
197          16,                    /* bitsize */
198          false,                 /* pc_relative */
199          0,                     /* bitpos */
200          complain_overflow_dont, /* complain_on_overflow */
201          bfd_elf_generic_reloc, /* special_function */
202          "R_860_LOW0",          /* name */
203          false,                 /* partial_inplace */
204          0xffff,                /* src_mask */
205          0xffff,                /* dst_mask */
206          false),                /* pcrel_offset */
207
208   HOWTO (R_860_SPLIT0,          /* type */
209          0,                     /* rightshift */
210          2,                     /* size (0 = byte, 1 = short, 2 = long) */
211          16,                    /* bitsize */
212          false,                 /* pc_relative */
213          0,                     /* bitpos */
214          complain_overflow_dont, /* complain_on_overflow */
215          bfd_elf_generic_reloc, /* special_function */
216          "R_860_SPLIT0",        /* name */
217          false,                 /* partial_inplace */
218          0x1f07ff,              /* src_mask */
219          0x1f07ff,              /* dst_mask */
220          false),                /* pcrel_offset */
221
222   HOWTO (R_860_LOW1,            /* type */
223          0,                     /* rightshift */
224          2,                     /* size (0 = byte, 1 = short, 2 = long) */
225          16,                    /* bitsize */
226          false,                 /* pc_relative */
227          0,                     /* bitpos */
228          complain_overflow_dont, /* complain_on_overflow */
229          bfd_elf_generic_reloc, /* special_function */
230          "R_860_LOW1",          /* name */
231          false,                 /* partial_inplace */
232          0xfffe,                /* src_mask */
233          0xfffe,                /* dst_mask */
234          false),                /* pcrel_offset */
235
236   HOWTO (R_860_SPLIT1,          /* type */
237          0,                     /* rightshift */
238          2,                     /* size (0 = byte, 1 = short, 2 = long) */
239          16,                    /* bitsize */
240          false,                 /* pc_relative */
241          0,                     /* bitpos */
242          complain_overflow_dont, /* complain_on_overflow */
243          bfd_elf_generic_reloc, /* special_function */
244          "R_860_SPLIT1",        /* name */
245          false,                 /* partial_inplace */
246          0x1f07fe,              /* src_mask */
247          0x1f07fe,              /* dst_mask */
248          false),                /* pcrel_offset */
249
250   HOWTO (R_860_LOW2,            /* type */
251          0,                     /* rightshift */
252          2,                     /* size (0 = byte, 1 = short, 2 = long) */
253          16,                    /* bitsize */
254          false,                 /* pc_relative */
255          0,                     /* bitpos */
256          complain_overflow_dont, /* complain_on_overflow */
257          bfd_elf_generic_reloc, /* special_function */
258          "R_860_LOW2",          /* name */
259          false,                 /* partial_inplace */
260          0xfffc,                /* src_mask */
261          0xfffc,                /* dst_mask */
262          false),                /* pcrel_offset */
263
264   HOWTO (R_860_SPLIT2,          /* type */
265          0,                     /* rightshift */
266          2,                     /* size (0 = byte, 1 = short, 2 = long) */
267          16,                    /* bitsize */
268          false,                 /* pc_relative */
269          0,                     /* bitpos */
270          complain_overflow_dont, /* complain_on_overflow */
271          bfd_elf_generic_reloc, /* special_function */
272          "R_860_SPLIT2",        /* name */
273          false,                 /* partial_inplace */
274          0x1f07fc,              /* src_mask */
275          0x1f07fc,              /* dst_mask */
276          false),                /* pcrel_offset */
277
278   HOWTO (R_860_LOW3,            /* type */
279          0,                     /* rightshift */
280          2,                     /* size (0 = byte, 1 = short, 2 = long) */
281          16,                    /* bitsize */
282          false,                 /* pc_relative */
283          0,                     /* bitpos */
284          complain_overflow_dont, /* complain_on_overflow */
285          bfd_elf_generic_reloc, /* special_function */
286          "R_860_LOW3",          /* name */
287          false,                 /* partial_inplace */
288          0xfff8,                /* src_mask */
289          0xfff8,                /* dst_mask */
290          false),                /* pcrel_offset */
291
292   HOWTO (R_860_LOGOT0,          /* type */
293          0,                     /* rightshift */
294          2,                     /* size (0 = byte, 1 = short, 2 = long) */
295          16,                    /* bitsize */
296          false,                 /* pc_relative */
297          0,                     /* bitpos */
298          complain_overflow_dont, /* complain_on_overflow */
299          bfd_elf_generic_reloc, /* special_function */
300          "R_860_LOGOT0",        /* name */
301          false,                 /* partial_inplace */
302          0,                     /* src_mask */
303          0xffff,                /* dst_mask */
304          true),                 /* pcrel_offset */
305
306   HOWTO (R_860_SPGOT0,          /* type */
307          0,                     /* rightshift */
308          2,                     /* size (0 = byte, 1 = short, 2 = long) */
309          16,                    /* bitsize */
310          false,                 /* pc_relative */
311          0,                     /* bitpos */
312          complain_overflow_dont, /* complain_on_overflow */
313          bfd_elf_generic_reloc, /* special_function */
314          "R_860_SPGOT0",        /* name */
315          false,                 /* partial_inplace */
316          0,                     /* src_mask */
317          0xffff,                /* dst_mask */
318          true),                 /* pcrel_offset */
319
320   HOWTO (R_860_LOGOT1,          /* type */
321          0,                     /* rightshift */
322          2,                     /* size (0 = byte, 1 = short, 2 = long) */
323          16,                    /* bitsize */
324          false,                 /* pc_relative */
325          0,                     /* bitpos */
326          complain_overflow_dont, /* complain_on_overflow */
327          bfd_elf_generic_reloc, /* special_function */
328          "R_860_LOGOT1",        /* name */
329          false,                 /* partial_inplace */
330          0,                     /* src_mask */
331          0xffff,                /* dst_mask */
332          true),                 /* pcrel_offset */
333
334   HOWTO (R_860_SPGOT1,          /* type */
335          0,                     /* rightshift */
336          2,                     /* size (0 = byte, 1 = short, 2 = long) */
337          16,                    /* bitsize */
338          false,                 /* pc_relative */
339          0,                     /* bitpos */
340          complain_overflow_dont, /* complain_on_overflow */
341          bfd_elf_generic_reloc, /* special_function */
342          "R_860_SPGOT1",        /* name */
343          false,                 /* partial_inplace */
344          0,                     /* src_mask */
345          0xffff,                /* dst_mask */
346          true),                 /* pcrel_offset */
347
348   HOWTO (R_860_LOGOTOFF0,        /* type */
349          0,                     /* rightshift */
350          2,                     /* size (0 = byte, 1 = short, 2 = long) */
351          32,                    /* bitsize */
352          false,                 /* pc_relative */
353          0,                     /* bitpos */
354          complain_overflow_dont, /* complain_on_overflow */
355          bfd_elf_generic_reloc, /* special_function */
356          "R_860_LOGOTOFF0",     /* name */
357          true,                  /* partial_inplace */
358          0xffffffff,            /* src_mask */
359          0xffffffff,            /* dst_mask */
360          false),                /* pcrel_offset */
361
362   HOWTO (R_860_SPGOTOFF0,        /* type */
363          0,                     /* rightshift */
364          2,                     /* size (0 = byte, 1 = short, 2 = long) */
365          32,                    /* bitsize */
366          false,                 /* pc_relative */
367          0,                     /* bitpos */
368          complain_overflow_dont, /* complain_on_overflow */
369          bfd_elf_generic_reloc, /* special_function */
370          "R_860_SPGOTOFF0",     /* name */
371          true,                  /* partial_inplace */
372          0xffffffff,            /* src_mask */
373          0xffffffff,            /* dst_mask */
374          false),                /* pcrel_offset */
375
376   HOWTO (R_860_LOGOTOFF1,        /* type */
377          0,                     /* rightshift */
378          2,                     /* size (0 = byte, 1 = short, 2 = long) */
379          32,                    /* bitsize */
380          false,                 /* pc_relative */
381          0,                     /* bitpos */
382          complain_overflow_dont, /* complain_on_overflow */
383          bfd_elf_generic_reloc, /* special_function */
384          "R_860_LOGOTOFF1",     /* name */
385          true,                  /* partial_inplace */
386          0xffffffff,            /* src_mask */
387          0xffffffff,            /* dst_mask */
388          false),                /* pcrel_offset */
389
390   HOWTO (R_860_SPGOTOFF1,       /* type */
391          0,                     /* rightshift */
392          2,                     /* size (0 = byte, 1 = short, 2 = long) */
393          32,                    /* bitsize */
394          false,                 /* pc_relative */
395          0,                     /* bitpos */
396          complain_overflow_dont, /* complain_on_overflow */
397          bfd_elf_generic_reloc, /* special_function */
398          "R_860_SPGOTOFF1",     /* name */
399          true,                  /* partial_inplace */
400          0xffffffff,            /* src_mask */
401          0xffffffff,            /* dst_mask */
402          false),                /* pcrel_offset */
403
404   HOWTO (R_860_LOGOTOFF2,        /* type */
405          0,                     /* rightshift */
406          2,                     /* size (0 = byte, 1 = short, 2 = long) */
407          32,                    /* bitsize */
408          false,                 /* pc_relative */
409          0,                     /* bitpos */
410          complain_overflow_dont, /* complain_on_overflow */
411          bfd_elf_generic_reloc, /* special_function */
412          "R_860_LOGOTOFF2",     /* name */
413          true,                  /* partial_inplace */
414          0xffffffff,            /* src_mask */
415          0xffffffff,            /* dst_mask */
416          false),                /* pcrel_offset */
417
418   HOWTO (R_860_LOGOTOFF3,        /* type */
419          0,                     /* rightshift */
420          2,                     /* size (0 = byte, 1 = short, 2 = long) */
421          32,                    /* bitsize */
422          false,                 /* pc_relative */
423          0,                     /* bitpos */
424          complain_overflow_dont, /* complain_on_overflow */
425          bfd_elf_generic_reloc, /* special_function */
426          "R_860_LOGOTOFF3",     /* name */
427          true,                  /* partial_inplace */
428          0xffffffff,            /* src_mask */
429          0xffffffff,            /* dst_mask */
430          false),                /* pcrel_offset */
431
432   HOWTO (R_860_LOPC,            /* type */
433          0,                     /* rightshift */
434          2,                     /* size (0 = byte, 1 = short, 2 = long) */
435          16,                    /* bitsize */
436          true,                  /* pc_relative */
437          0,                     /* bitpos */
438          complain_overflow_bitfield, /* complain_on_overflow */
439          bfd_elf_generic_reloc, /* special_function */
440          "R_860_LOPC",          /* name */
441          false,                 /* partial_inplace */
442          0xffff,                /* src_mask */
443          0xffff,                /* dst_mask */
444          true),                 /* pcrel_offset */
445
446   HOWTO (R_860_HIGHADJ,         /* type */
447          0,                     /* rightshift */
448          2,                     /* size (0 = byte, 1 = short, 2 = long) */
449          16,                    /* bitsize */
450          false,                 /* pc_relative */
451          0,                     /* bitpos */
452          complain_overflow_dont, /* complain_on_overflow */
453          bfd_elf_generic_reloc, /* special_function */
454          "R_860_HIGHADJ",       /* name */
455          false,                 /* partial_inplace */
456          0xffff,                /* src_mask */
457          0xffff,                /* dst_mask */
458          false),                /* pcrel_offset */
459
460   HOWTO (R_860_HAGOT,           /* type */
461          0,                     /* rightshift */
462          2,                     /* size (0 = byte, 1 = short, 2 = long) */
463          16,                    /* bitsize */
464          false,                 /* pc_relative */
465          0,                     /* bitpos */
466          complain_overflow_dont, /* complain_on_overflow */
467          bfd_elf_generic_reloc, /* special_function */
468          "R_860_HAGOT",         /* name */
469          false,                 /* partial_inplace */
470          0,                     /* src_mask */
471          0xffff,                /* dst_mask */
472          true),                 /* pcrel_offset */
473
474   HOWTO (R_860_HAGOTOFF,        /* type */
475          0,                     /* rightshift */
476          2,                     /* size (0 = byte, 1 = short, 2 = long) */
477          32,                    /* bitsize */
478          false,                 /* pc_relative */
479          0,                     /* bitpos */
480          complain_overflow_dont, /* complain_on_overflow */
481          bfd_elf_generic_reloc, /* special_function */
482          "R_860_HAGOTOFF",      /* name */
483          true,                  /* partial_inplace */
484          0xffffffff,            /* src_mask */
485          0xffffffff,            /* dst_mask */
486          false),                /* pcrel_offset */
487
488   HOWTO (R_860_HAPC,            /* type */
489          0,                     /* rightshift */
490          2,                     /* size (0 = byte, 1 = short, 2 = long) */
491          16,                    /* bitsize */
492          true,                  /* pc_relative */
493          0,                     /* bitpos */
494          complain_overflow_bitfield, /* complain_on_overflow */
495          bfd_elf_generic_reloc, /* special_function */
496          "R_860_HAPC",          /* name */
497          false,                 /* partial_inplace */
498          0xffff,                /* src_mask */
499          0xffff,                /* dst_mask */
500          true),                 /* pcrel_offset */
501
502   HOWTO (R_860_HIGH,            /* type */
503          16,                    /* rightshift */
504          2,                     /* size (0 = byte, 1 = short, 2 = long) */
505          16,                    /* bitsize */
506          false,                 /* pc_relative */
507          0,                     /* bitpos */
508          complain_overflow_dont, /* complain_on_overflow */
509          bfd_elf_generic_reloc, /* special_function */
510          "R_860_HIGH",          /* name */
511          false,                 /* partial_inplace */
512          0xffff,                /* src_mask */
513          0xffff,                /* dst_mask */
514          false),                /* pcrel_offset */
515
516   HOWTO (R_860_HIGOT,           /* type */
517          0,                     /* rightshift */
518          2,                     /* size (0 = byte, 1 = short, 2 = long) */
519          16,                    /* bitsize */
520          false,                 /* pc_relative */
521          0,                     /* bitpos */
522          complain_overflow_dont, /* complain_on_overflow */
523          bfd_elf_generic_reloc, /* special_function */
524          "R_860_HIGOT",         /* name */
525          false,                 /* partial_inplace */
526          0,                     /* src_mask */
527          0xffff,                /* dst_mask */
528          true),                 /* pcrel_offset */
529
530   HOWTO (R_860_HIGOTOFF,        /* type */
531          0,                     /* rightshift */
532          2,                     /* size (0 = byte, 1 = short, 2 = long) */
533          32,                    /* bitsize */
534          false,                 /* pc_relative */
535          0,                     /* bitpos */
536          complain_overflow_dont, /* complain_on_overflow */
537          bfd_elf_generic_reloc, /* special_function */
538          "R_860_HIGOTOFF",      /* name */
539          true,                  /* partial_inplace */
540          0xffffffff,            /* src_mask */
541          0xffffffff,            /* dst_mask */
542          false),                /* pcrel_offset */
543 };
544 \f
545 static unsigned char elf_code_to_howto_index[R_860_max + 1];
546
547 static reloc_howto_type *
548 lookup_howto (rtype)
549      unsigned int rtype;
550 {
551   static int initialized = 0;
552   int i;
553   int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
554                         / sizeof (elf32_i860_howto_table[0]));
555
556   if (! initialized)
557     {
558       initialized = 1;
559       memset (elf_code_to_howto_index, 0xff,
560               sizeof (elf_code_to_howto_index));
561       for (i = 0; i < howto_tbl_size; i++)
562         elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
563     }
564
565   BFD_ASSERT (rtype <= R_860_max);
566   i = elf_code_to_howto_index[rtype];
567   if (i >= howto_tbl_size)
568     return 0;
569   return elf32_i860_howto_table + i;
570 }
571
572 /* Given a BFD reloc, return the matching HOWTO structure.  */
573 static reloc_howto_type *
574 elf32_i860_reloc_type_lookup (abfd, code)
575      bfd * abfd ATTRIBUTE_UNUSED;
576      bfd_reloc_code_real_type code;
577 {
578   unsigned int rtype;
579
580   switch (code)
581     {
582     case BFD_RELOC_NONE:
583       rtype = R_860_NONE;
584       break;
585     case BFD_RELOC_32:
586       rtype = R_860_32;
587       break;
588     case BFD_RELOC_860_COPY:
589       rtype = R_860_COPY;
590       break;
591     case BFD_RELOC_860_GLOB_DAT:
592       rtype = R_860_GLOB_DAT;
593       break;
594     case BFD_RELOC_860_JUMP_SLOT:
595       rtype = R_860_JUMP_SLOT;
596       break;
597     case BFD_RELOC_860_RELATIVE:
598       rtype = R_860_RELATIVE;
599       break;
600     case BFD_RELOC_860_PC26:
601       rtype = R_860_PC26;
602       break;
603     case BFD_RELOC_860_PLT26:
604       rtype = R_860_PLT26;
605       break;
606     case BFD_RELOC_860_PC16:
607       rtype = R_860_PC16;
608       break;
609     case BFD_RELOC_860_LOW0:
610       rtype = R_860_LOW0;
611       break;
612     case BFD_RELOC_860_SPLIT0:
613       rtype = R_860_SPLIT0;
614       break;
615     case BFD_RELOC_860_LOW1:
616       rtype = R_860_LOW1;
617       break;
618     case BFD_RELOC_860_SPLIT1:
619       rtype = R_860_SPLIT1;
620       break;
621     case BFD_RELOC_860_LOW2:
622       rtype = R_860_LOW2;
623       break;
624     case BFD_RELOC_860_SPLIT2:
625       rtype = R_860_SPLIT2;
626       break;
627     case BFD_RELOC_860_LOW3:
628       rtype = R_860_LOW3;
629       break;
630     case BFD_RELOC_860_LOGOT0:
631       rtype = R_860_LOGOT0;
632       break;
633     case BFD_RELOC_860_SPGOT0:
634       rtype = R_860_SPGOT0;
635       break;
636     case BFD_RELOC_860_LOGOT1:
637       rtype = R_860_LOGOT1;
638       break;
639     case BFD_RELOC_860_SPGOT1:
640       rtype = R_860_SPGOT1;
641       break;
642     case BFD_RELOC_860_LOGOTOFF0:
643       rtype = R_860_LOGOTOFF0;
644       break;
645     case BFD_RELOC_860_SPGOTOFF0:
646       rtype = R_860_SPGOTOFF0;
647       break;
648     case BFD_RELOC_860_LOGOTOFF1:
649       rtype = R_860_LOGOTOFF1;
650       break;
651     case BFD_RELOC_860_SPGOTOFF1:
652       rtype = R_860_SPGOTOFF1;
653       break;
654     case BFD_RELOC_860_LOGOTOFF2:
655       rtype = R_860_LOGOTOFF2;
656       break;
657     case BFD_RELOC_860_LOGOTOFF3:
658       rtype = R_860_LOGOTOFF3;
659       break;
660     case BFD_RELOC_860_LOPC:
661       rtype = R_860_LOPC;
662       break;
663     case BFD_RELOC_860_HIGHADJ:
664       rtype = R_860_HIGHADJ;
665       break;
666     case BFD_RELOC_860_HAGOT:
667       rtype = R_860_HAGOT;
668       break;
669     case BFD_RELOC_860_HAGOTOFF:
670       rtype = R_860_HAGOTOFF;
671       break;
672     case BFD_RELOC_860_HAPC:
673       rtype = R_860_HAPC;
674       break;
675     case BFD_RELOC_860_HIGH:
676       rtype = R_860_HIGH;
677       break;
678     case BFD_RELOC_860_HIGOT:
679       rtype = R_860_HIGOT;
680       break;
681     case BFD_RELOC_860_HIGOTOFF:
682       rtype = R_860_HIGOTOFF;
683       break;
684     default:
685       rtype = 0;
686       break;
687     }
688   return lookup_howto (rtype);
689 }
690
691 /* Given a ELF reloc, return the matching HOWTO structure.  */
692 static void
693 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
694      bfd *abfd ATTRIBUTE_UNUSED;
695      arelent *bfd_reloc;
696      Elf64_Internal_Rela *elf_reloc;
697 {
698   bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
699 }
700 \f
701 /* Specialized relocation handler for R_860_SPLITn.  These relocations
702    involves a 16-bit field that is split into two contiguous parts.  */
703 static bfd_reloc_status_type
704 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
705      bfd *input_bfd;
706      Elf_Internal_Rela *rello;
707      bfd_byte *contents;
708      bfd_vma value;
709 {
710   bfd_vma insn;
711   reloc_howto_type *howto;
712   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
713   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
714
715   /* Relocate.  */
716   value += rello->r_addend;
717
718   /* Separate the fields and insert.  */
719   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
720   insn = (insn & ~howto->dst_mask) | value;
721
722   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
723   return bfd_reloc_ok;
724 }
725
726 /* Specialized relocation handler for R_860_PC16.  This relocation
727    involves a 16-bit, PC-relative field that is split into two contiguous
728    parts.  */
729 static bfd_reloc_status_type
730 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
731      bfd *input_bfd;
732      asection *input_section;
733      Elf_Internal_Rela *rello;
734      bfd_byte *contents;
735      bfd_vma value;
736 {
737   bfd_vma insn;
738   reloc_howto_type *howto;
739   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
740   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
741
742   /* Adjust for PC-relative relocation.  */
743   value -= (input_section->output_section->vma
744             + input_section->output_offset);
745   value -= rello->r_offset;
746
747   /* Relocate.  */
748   value += rello->r_addend;
749
750   /* Separate the fields and insert.  */
751   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
752   insn = (insn & ~howto->dst_mask) | value;
753
754   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
755   return bfd_reloc_ok;
756
757 }
758
759 /* Specialized relocation handler for R_860_PC26.  This relocation
760    involves a 26-bit, PC-relative field which must be adjusted by 4.  */
761 static bfd_reloc_status_type
762 elf32_i860_relocate_pc26 (input_bfd, input_section, rello, contents, value)
763      bfd *input_bfd;
764      asection *input_section;
765      Elf_Internal_Rela *rello;
766      bfd_byte *contents;
767      bfd_vma value;
768 {
769   bfd_vma insn;
770   reloc_howto_type *howto;
771   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
772   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
773
774   /* Adjust for PC-relative relocation.  */
775   value -= (input_section->output_section->vma
776             + input_section->output_offset);
777   value -= rello->r_offset;
778
779   /* Relocate.  */
780   value += rello->r_addend;
781
782   /* Adjust value by 4 and insert the field.  */
783   value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
784   insn = (insn & ~howto->dst_mask) | value;
785
786   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
787   return bfd_reloc_ok;
788
789 }
790
791 /* Specialized relocation handler for R_860_HIGHADJ.  */
792 static bfd_reloc_status_type
793 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
794      bfd *input_bfd;
795      Elf_Internal_Rela *rel;
796      bfd_byte *contents;
797      bfd_vma value;
798 {
799   bfd_vma insn;
800
801   insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
802
803   value += ((rel->r_addend & 0x8000) << 1);
804   value += rel->r_addend;
805   value = ((value >> 16) & 0xffff);
806
807   insn = (insn & 0xffff0000) | value;
808
809   bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
810   return bfd_reloc_ok;
811 }
812
813 /* Perform a single relocation.  By default we use the standard BFD
814    routines. However, we handle some specially.  */
815 static bfd_reloc_status_type
816 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
817      reloc_howto_type *  howto;
818      bfd *               input_bfd;
819      asection *          input_section;
820      bfd_byte *          contents;
821      Elf_Internal_Rela * rel;
822      bfd_vma             relocation;
823 {
824   return _bfd_final_link_relocate (howto, input_bfd, input_section,
825                                    contents, rel->r_offset, relocation,
826                                    rel->r_addend);
827 }
828
829 /* Relocate an i860 ELF section.
830
831    This is boiler-plate code copied from fr30.
832    There is some attempt to make this function usable for many architectures,
833    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
834    if only to serve as a learning tool.
835
836    The RELOCATE_SECTION function is called by the new ELF backend linker
837    to handle the relocations for a section.
838
839    The relocs are always passed as Rela structures; if the section
840    actually uses Rel structures, the r_addend field will always be
841    zero.
842
843    This function is responsible for adjusting the section contents as
844    necessary, and (if using Rela relocs and generating a relocateable
845    output file) adjusting the reloc addend as necessary.
846
847    This function does not have to worry about setting the reloc
848    address or the reloc symbol index.
849
850    LOCAL_SYMS is a pointer to the swapped in local symbols.
851
852    LOCAL_SECTIONS is an array giving the section in the input file
853    corresponding to the st_shndx field of each local symbol.
854
855    The global hash table entry for the global symbols can be found
856    via elf_sym_hashes (input_bfd).
857
858    When generating relocateable output, this function must handle
859    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
860    going to be the section symbol corresponding to the output
861    section, which means that the addend must be adjusted
862    accordingly.  */
863 static boolean
864 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
865                              contents, relocs, local_syms, local_sections)
866      bfd *                   output_bfd ATTRIBUTE_UNUSED;
867      struct bfd_link_info *  info;
868      bfd *                   input_bfd;
869      asection *              input_section;
870      bfd_byte *              contents;
871      Elf_Internal_Rela *     relocs;
872      Elf_Internal_Sym *      local_syms;
873      asection **             local_sections;
874 {
875   Elf_Internal_Shdr *           symtab_hdr;
876   struct elf_link_hash_entry ** sym_hashes;
877   Elf_Internal_Rela *           rel;
878   Elf_Internal_Rela *           relend;
879
880   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
881   sym_hashes = elf_sym_hashes (input_bfd);
882   relend     = relocs + input_section->reloc_count;
883
884   for (rel = relocs; rel < relend; rel ++)
885     {
886       reloc_howto_type *           howto;
887       unsigned long                r_symndx;
888       Elf_Internal_Sym *           sym;
889       asection *                   sec;
890       struct elf_link_hash_entry * h;
891       bfd_vma                      relocation;
892       bfd_reloc_status_type        r;
893       const char *                 name = NULL;
894       int                          r_type;
895
896       r_type = ELF32_R_TYPE (rel->r_info);
897
898 #if 0
899       if (   r_type == R_860_GNU_VTINHERIT
900           || r_type == R_860_GNU_VTENTRY)
901         continue;
902 #endif
903
904       r_symndx = ELF32_R_SYM (rel->r_info);
905
906       if (info->relocateable)
907         {
908           /* This is a relocateable link.  We don't have to change
909              anything, unless the reloc is against a section symbol,
910              in which case we have to adjust according to where the
911              section symbol winds up in the output section.  */
912           if (r_symndx < symtab_hdr->sh_info)
913             {
914               sym = local_syms + r_symndx;
915
916               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
917                 {
918                   sec = local_sections [r_symndx];
919                   rel->r_addend += sec->output_offset + sym->st_value;
920                 }
921             }
922
923           continue;
924         }
925
926       /* This is a final link.  */
927       howto  = lookup_howto (ELF32_R_TYPE (rel->r_info));
928       h      = NULL;
929       sym    = NULL;
930       sec    = NULL;
931
932       if (r_symndx < symtab_hdr->sh_info)
933         {
934           sym = local_syms + r_symndx;
935           sec = local_sections [r_symndx];
936           relocation = (sec->output_section->vma
937                         + sec->output_offset
938                         + sym->st_value);
939
940           name = bfd_elf_string_from_elf_section
941             (input_bfd, symtab_hdr->sh_link, sym->st_name);
942           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
943         }
944       else
945         {
946           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
947
948           while (h->root.type == bfd_link_hash_indirect
949                  || h->root.type == bfd_link_hash_warning)
950             h = (struct elf_link_hash_entry *) h->root.u.i.link;
951
952           name = h->root.root.string;
953
954           if (h->root.type == bfd_link_hash_defined
955               || h->root.type == bfd_link_hash_defweak)
956             {
957               sec = h->root.u.def.section;
958               relocation = (h->root.u.def.value
959                             + sec->output_section->vma
960                             + sec->output_offset);
961             }
962           else if (h->root.type == bfd_link_hash_undefweak)
963             {
964               relocation = 0;
965             }
966           else
967             {
968               if (! ((*info->callbacks->undefined_symbol)
969                      (info, h->root.root.string, input_bfd,
970                       input_section, rel->r_offset, true)))
971                 return false;
972               relocation = 0;
973             }
974         }
975
976       switch (r_type)
977         {
978         default:
979           r = i860_final_link_relocate (howto, input_bfd, input_section,
980                                         contents, rel, relocation);
981           break;
982
983         case R_860_HIGHADJ:
984           r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
985                                            relocation);
986           break;
987
988         case R_860_PC16:
989           r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
990                                         contents, relocation);
991           break;
992
993         case R_860_PC26:
994           r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
995                                         contents, relocation);
996           break;
997
998         case R_860_SPLIT0:
999         case R_860_SPLIT1:
1000         case R_860_SPLIT2:
1001           r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1002                                           relocation);
1003           break;
1004
1005         /* We do not yet handle GOT/PLT/Dynamic relocations.  */
1006         case R_860_COPY:
1007         case R_860_GLOB_DAT:
1008         case R_860_JUMP_SLOT:
1009         case R_860_RELATIVE:
1010         case R_860_PLT26:
1011         case R_860_LOGOT0:
1012         case R_860_SPGOT0:
1013         case R_860_LOGOT1:
1014         case R_860_SPGOT1:
1015         case R_860_LOGOTOFF0:
1016         case R_860_SPGOTOFF0:
1017         case R_860_LOGOTOFF1:
1018         case R_860_SPGOTOFF1:
1019         case R_860_LOGOTOFF2:
1020         case R_860_LOGOTOFF3:
1021         case R_860_LOPC:
1022         case R_860_HAGOT:
1023         case R_860_HAGOTOFF:
1024         case R_860_HAPC:
1025         case R_860_HIGOT:
1026         case R_860_HIGOTOFF:
1027           r = bfd_reloc_notsupported;
1028           break;
1029         }
1030
1031       if (r != bfd_reloc_ok)
1032         {
1033           const char * msg = (const char *) NULL;
1034
1035           switch (r)
1036             {
1037             case bfd_reloc_overflow:
1038               r = info->callbacks->reloc_overflow
1039                 (info, name, howto->name, (bfd_vma) 0,
1040                  input_bfd, input_section, rel->r_offset);
1041               break;
1042
1043             case bfd_reloc_undefined:
1044               r = info->callbacks->undefined_symbol
1045                 (info, name, input_bfd, input_section, rel->r_offset, true);
1046               break;
1047
1048             case bfd_reloc_outofrange:
1049               msg = _("internal error: out of range error");
1050               break;
1051
1052             case bfd_reloc_notsupported:
1053               msg = _("internal error: unsupported relocation error");
1054               break;
1055
1056             case bfd_reloc_dangerous:
1057               msg = _("internal error: dangerous relocation");
1058               break;
1059
1060             default:
1061               msg = _("internal error: unknown error");
1062               break;
1063             }
1064
1065           if (msg)
1066             r = info->callbacks->warning
1067               (info, msg, name, input_bfd, input_section, rel->r_offset);
1068
1069           if (! r)
1070             return false;
1071         }
1072     }
1073
1074   return true;
1075 }
1076
1077 /* Return whether a symbol name implies a local label.  SVR4/860 compilers
1078    generate labels of the form ".ep.function_name" to denote the end of a
1079    function prolog. These should be local.
1080    ??? Do any other SVR4 compilers have this convention? If so, this should
1081    be added to the generic routine.  */
1082 static boolean
1083 elf32_i860_is_local_label_name (abfd, name)
1084      bfd *abfd;
1085      const char *name;
1086 {
1087   if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1088     return true;
1089
1090   return _bfd_elf_is_local_label_name (abfd, name);
1091 }
1092 \f
1093 #define TARGET_BIG_SYM          bfd_elf32_i860_vec
1094 #define TARGET_BIG_NAME         "elf32-i860"
1095 #define TARGET_LITTLE_SYM       bfd_elf32_i860_little_vec
1096 #define TARGET_LITTLE_NAME      "elf32-i860-little"
1097 #define ELF_ARCH                bfd_arch_i860
1098 #define ELF_MACHINE_CODE        EM_860
1099 #define ELF_MAXPAGESIZE         4096
1100
1101 #define elf_info_to_howto_rel                   NULL
1102 #define elf_info_to_howto                       elf32_i860_info_to_howto_rela
1103 #define elf_backend_relocate_section            elf32_i860_relocate_section
1104 #define bfd_elf32_bfd_reloc_type_lookup         elf32_i860_reloc_type_lookup
1105 #define bfd_elf32_bfd_is_local_label_name       elf32_i860_is_local_label_name
1106
1107 #include "elf32-target.h"