OSDN Git Service

2002-03-01 David O'Brien <obrien@FreeBSD.org>
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf32-i860.c
1 /* Intel i860 specific support for 32-bit ELF.
2    Copyright 1993, 1995, 1999, 2000, 2001 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
699     = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
700 }
701 \f
702 /* Specialized relocation handler for R_860_SPLITn.  These relocations
703    involves a 16-bit field that is split into two contiguous parts.  */
704 static bfd_reloc_status_type
705 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
706      bfd *input_bfd;
707      Elf_Internal_Rela *rello;
708      bfd_byte *contents;
709      bfd_vma value;
710 {
711   bfd_vma insn;
712   reloc_howto_type *howto;
713   howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
714   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
715
716   /* Relocate.  */
717   value += rello->r_addend;
718
719   /* Separate the fields and insert.  */
720   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
721   insn = (insn & ~howto->dst_mask) | value;
722
723   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
724   return bfd_reloc_ok;
725 }
726
727 /* Specialized relocation handler for R_860_PC16.  This relocation
728    involves a 16-bit, PC-relative field that is split into two contiguous
729    parts.  */
730 static bfd_reloc_status_type
731 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
732      bfd *input_bfd;
733      asection *input_section;
734      Elf_Internal_Rela *rello;
735      bfd_byte *contents;
736      bfd_vma value;
737 {
738   bfd_vma insn;
739   reloc_howto_type *howto;
740   howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
741   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
742
743   /* Adjust for PC-relative relocation.  */
744   value -= (input_section->output_section->vma
745             + input_section->output_offset);
746   value -= rello->r_offset;
747
748   /* Relocate.  */
749   value += rello->r_addend;
750
751   /* Separate the fields and insert.  */
752   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
753   insn = (insn & ~howto->dst_mask) | value;
754
755   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
756   return bfd_reloc_ok;
757
758 }
759
760 /* Specialized relocation handler for R_860_PC26.  This relocation
761    involves a 26-bit, PC-relative field which must be adjusted by 4.  */
762 static bfd_reloc_status_type
763 elf32_i860_relocate_pc26 (input_bfd, input_section, rello, contents, value)
764      bfd *input_bfd;
765      asection *input_section;
766      Elf_Internal_Rela *rello;
767      bfd_byte *contents;
768      bfd_vma value;
769 {
770   bfd_vma insn;
771   reloc_howto_type *howto;
772   howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
773   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
774
775   /* Adjust for PC-relative relocation.  */
776   value -= (input_section->output_section->vma
777             + input_section->output_offset);
778   value -= rello->r_offset;
779
780   /* Relocate.  */
781   value += rello->r_addend;
782
783   /* Adjust value by 4 and insert the field.  */
784   value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
785   insn = (insn & ~howto->dst_mask) | value;
786
787   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
788   return bfd_reloc_ok;
789
790 }
791
792 /* Specialized relocation handler for R_860_HIGHADJ.  */
793 static bfd_reloc_status_type
794 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
795      bfd *input_bfd;
796      Elf_Internal_Rela *rel;
797      bfd_byte *contents;
798      bfd_vma value;
799 {
800   bfd_vma insn;
801
802   insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
803
804   value += ((rel->r_addend & 0x8000) << 1);
805   value += rel->r_addend;
806   value = ((value >> 16) & 0xffff);
807
808   insn = (insn & 0xffff0000) | value;
809
810   bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
811   return bfd_reloc_ok;
812 }
813
814 /* Perform a single relocation.  By default we use the standard BFD
815    routines. However, we handle some specially.  */
816 static bfd_reloc_status_type
817 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
818      reloc_howto_type *  howto;
819      bfd *               input_bfd;
820      asection *          input_section;
821      bfd_byte *          contents;
822      Elf_Internal_Rela * rel;
823      bfd_vma             relocation;
824 {
825   return _bfd_final_link_relocate (howto, input_bfd, input_section,
826                                    contents, rel->r_offset, relocation,
827                                    rel->r_addend);
828 }
829
830 /* Relocate an i860 ELF section.
831
832    This is boiler-plate code copied from fr30.
833    There is some attempt to make this function usable for many architectures,
834    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
835    if only to serve as a learning tool.
836
837    The RELOCATE_SECTION function is called by the new ELF backend linker
838    to handle the relocations for a section.
839
840    The relocs are always passed as Rela structures; if the section
841    actually uses Rel structures, the r_addend field will always be
842    zero.
843
844    This function is responsible for adjusting the section contents as
845    necessary, and (if using Rela relocs and generating a relocateable
846    output file) adjusting the reloc addend as necessary.
847
848    This function does not have to worry about setting the reloc
849    address or the reloc symbol index.
850
851    LOCAL_SYMS is a pointer to the swapped in local symbols.
852
853    LOCAL_SECTIONS is an array giving the section in the input file
854    corresponding to the st_shndx field of each local symbol.
855
856    The global hash table entry for the global symbols can be found
857    via elf_sym_hashes (input_bfd).
858
859    When generating relocateable output, this function must handle
860    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
861    going to be the section symbol corresponding to the output
862    section, which means that the addend must be adjusted
863    accordingly.  */
864 static boolean
865 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
866                              contents, relocs, local_syms, local_sections)
867      bfd *                   output_bfd ATTRIBUTE_UNUSED;
868      struct bfd_link_info *  info;
869      bfd *                   input_bfd;
870      asection *              input_section;
871      bfd_byte *              contents;
872      Elf_Internal_Rela *     relocs;
873      Elf_Internal_Sym *      local_syms;
874      asection **             local_sections;
875 {
876   Elf_Internal_Shdr *           symtab_hdr;
877   struct elf_link_hash_entry ** sym_hashes;
878   Elf_Internal_Rela *           rel;
879   Elf_Internal_Rela *           relend;
880
881   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
882   sym_hashes = elf_sym_hashes (input_bfd);
883   relend     = relocs + input_section->reloc_count;
884
885   for (rel = relocs; rel < relend; rel ++)
886     {
887       reloc_howto_type *           howto;
888       unsigned long                r_symndx;
889       Elf_Internal_Sym *           sym;
890       asection *                   sec;
891       struct elf_link_hash_entry * h;
892       bfd_vma                      relocation;
893       bfd_reloc_status_type        r;
894       const char *                 name = NULL;
895       int                          r_type;
896
897       r_type = ELF32_R_TYPE (rel->r_info);
898
899 #if 0
900       if (   r_type == R_860_GNU_VTINHERIT
901           || r_type == R_860_GNU_VTENTRY)
902         continue;
903 #endif
904
905       r_symndx = ELF32_R_SYM (rel->r_info);
906
907       if (info->relocateable)
908         {
909           /* This is a relocateable link.  We don't have to change
910              anything, unless the reloc is against a section symbol,
911              in which case we have to adjust according to where the
912              section symbol winds up in the output section.  */
913           if (r_symndx < symtab_hdr->sh_info)
914             {
915               sym = local_syms + r_symndx;
916
917               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
918                 {
919                   sec = local_sections [r_symndx];
920                   rel->r_addend += sec->output_offset + sym->st_value;
921                 }
922             }
923
924           continue;
925         }
926
927       /* This is a final link.  */
928       howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
929       h     = NULL;
930       sym   = NULL;
931       sec   = NULL;
932
933       if (r_symndx < symtab_hdr->sh_info)
934         {
935           sym = local_syms + r_symndx;
936           sec = local_sections [r_symndx];
937           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
938
939           name = bfd_elf_string_from_elf_section
940             (input_bfd, symtab_hdr->sh_link, sym->st_name);
941           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
942         }
943       else
944         {
945           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
946
947           while (h->root.type == bfd_link_hash_indirect
948                  || h->root.type == bfd_link_hash_warning)
949             h = (struct elf_link_hash_entry *) h->root.u.i.link;
950
951           name = h->root.root.string;
952
953           if (h->root.type == bfd_link_hash_defined
954               || h->root.type == bfd_link_hash_defweak)
955             {
956               sec = h->root.u.def.section;
957               relocation = (h->root.u.def.value
958                             + sec->output_section->vma
959                             + sec->output_offset);
960             }
961           else if (h->root.type == bfd_link_hash_undefweak)
962             {
963               relocation = 0;
964             }
965           else
966             {
967               if (! ((*info->callbacks->undefined_symbol)
968                      (info, h->root.root.string, input_bfd,
969                       input_section, rel->r_offset, true)))
970                 return false;
971               relocation = 0;
972             }
973         }
974
975       switch (r_type)
976         {
977         default:
978           r = i860_final_link_relocate (howto, input_bfd, input_section,
979                                         contents, rel, relocation);
980           break;
981
982         case R_860_HIGHADJ:
983           r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
984                                            relocation);
985           break;
986
987         case R_860_PC16:
988           r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
989                                         contents, relocation);
990           break;
991
992         case R_860_PC26:
993           r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
994                                         contents, relocation);
995           break;
996
997         case R_860_SPLIT0:
998         case R_860_SPLIT1:
999         case R_860_SPLIT2:
1000           r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1001                                           relocation);
1002           break;
1003
1004         /* We do not yet handle GOT/PLT/Dynamic relocations.  */
1005         case R_860_COPY:
1006         case R_860_GLOB_DAT:
1007         case R_860_JUMP_SLOT:
1008         case R_860_RELATIVE:
1009         case R_860_PLT26:
1010         case R_860_LOGOT0:
1011         case R_860_SPGOT0:
1012         case R_860_LOGOT1:
1013         case R_860_SPGOT1:
1014         case R_860_LOGOTOFF0:
1015         case R_860_SPGOTOFF0:
1016         case R_860_LOGOTOFF1:
1017         case R_860_SPGOTOFF1:
1018         case R_860_LOGOTOFF2:
1019         case R_860_LOGOTOFF3:
1020         case R_860_LOPC:
1021         case R_860_HAGOT:
1022         case R_860_HAGOTOFF:
1023         case R_860_HAPC:
1024         case R_860_HIGOT:
1025         case R_860_HIGOTOFF:
1026           r = bfd_reloc_notsupported;
1027           break;
1028         }
1029
1030       if (r != bfd_reloc_ok)
1031         {
1032           const char * msg = (const char *) NULL;
1033
1034           switch (r)
1035             {
1036             case bfd_reloc_overflow:
1037               r = info->callbacks->reloc_overflow
1038                 (info, name, howto->name, (bfd_vma) 0,
1039                  input_bfd, input_section, rel->r_offset);
1040               break;
1041
1042             case bfd_reloc_undefined:
1043               r = info->callbacks->undefined_symbol
1044                 (info, name, input_bfd, input_section, rel->r_offset, true);
1045               break;
1046
1047             case bfd_reloc_outofrange:
1048               msg = _("internal error: out of range error");
1049               break;
1050
1051             case bfd_reloc_notsupported:
1052               msg = _("internal error: unsupported relocation error");
1053               break;
1054
1055             case bfd_reloc_dangerous:
1056               msg = _("internal error: dangerous relocation");
1057               break;
1058
1059             default:
1060               msg = _("internal error: unknown error");
1061               break;
1062             }
1063
1064           if (msg)
1065             r = info->callbacks->warning
1066               (info, msg, name, input_bfd, input_section, rel->r_offset);
1067
1068           if (! r)
1069             return false;
1070         }
1071     }
1072
1073   return true;
1074 }
1075
1076 /* Return whether a symbol name implies a local label.  SVR4/860 compilers
1077    generate labels of the form ".ep.function_name" to denote the end of a
1078    function prolog. These should be local.
1079    ??? Do any other SVR4 compilers have this convention? If so, this should
1080    be added to the generic routine.  */
1081 static boolean
1082 elf32_i860_is_local_label_name (abfd, name)
1083      bfd *abfd;
1084      const char *name;
1085 {
1086   if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1087     return true;
1088
1089   return _bfd_elf_is_local_label_name (abfd, name);
1090 }
1091 \f
1092 #define TARGET_BIG_SYM          bfd_elf32_i860_vec
1093 #define TARGET_BIG_NAME         "elf32-i860"
1094 #define TARGET_LITTLE_SYM       bfd_elf32_i860_little_vec
1095 #define TARGET_LITTLE_NAME      "elf32-i860-little"
1096 #define ELF_ARCH                bfd_arch_i860
1097 #define ELF_MACHINE_CODE        EM_860
1098 #define ELF_MAXPAGESIZE         4096
1099
1100 #define elf_info_to_howto_rel                   NULL
1101 #define elf_info_to_howto                       elf32_i860_info_to_howto_rela
1102 #define elf_backend_relocate_section            elf32_i860_relocate_section
1103 #define bfd_elf32_bfd_reloc_type_lookup         elf32_i860_reloc_type_lookup
1104 #define bfd_elf32_bfd_is_local_label_name       elf32_i860_is_local_label_name
1105
1106 #include "elf32-target.h"