OSDN Git Service

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