1 /* BFD back-end for Intel i860 COFF files.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002,
3    2003, 2004, 2005 Free Software Foundation, Inc.
4    Created mostly by substituting "860" for "386" in coff-i386.c
5    Harry Dolan <dolan@ssd.intel.com>, October 1995
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
22 
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "libbfd.h"
26 
27 #include "coff/i860.h"
28 
29 #include "coff/internal.h"
30 
31 #include "libcoff.h"
32 
33 
34 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
35 /* The page size is a guess based on ELF.  */
36 
37 #define COFF_PAGE_SIZE 0x1000
38 
39 /* For some reason when using i860 COFF the value stored in the .text
40    section for a reference to a common symbol is the value itself plus
41    any desired offset.  Ian Taylor, Cygnus Support.  */
42 
43 /* If we are producing relocatable output, we need to do some
44    adjustments to the object file that are not done by the
45    bfd_perform_relocation function.  This function is called by every
46    reloc type to make any required adjustments.  */
47 
48 static bfd_reloc_status_type
49 coff_i860_reloc (bfd *abfd,
50 		 arelent *reloc_entry,
51 		 asymbol *symbol,
52 		 void *data,
53 		 asection *input_section ATTRIBUTE_UNUSED,
54 		 bfd *output_bfd,
55 		 char **error_message ATTRIBUTE_UNUSED)
56 {
57   symvalue diff;
58 
59   if (output_bfd == (bfd *) NULL)
60     return bfd_reloc_continue;
61 
62   if (bfd_is_com_section (symbol->section))
63     {
64       /* We are relocating a common symbol.  The current value in the
65 	 object file is ORIG + OFFSET, where ORIG is the value of the
66 	 common symbol as seen by the object file when it was compiled
67 	 (this may be zero if the symbol was undefined) and OFFSET is
68 	 the offset into the common symbol (normally zero, but may be
69 	 non-zero when referring to a field in a common structure).
70 	 ORIG is the negative of reloc_entry->addend, which is set by
71 	 the CALC_ADDEND macro below.  We want to replace the value in
72 	 the object file with NEW + OFFSET, where NEW is the value of
73 	 the common symbol which we are going to put in the final
74 	 object file.  NEW is symbol->value.  */
75       diff = symbol->value + reloc_entry->addend;
76     }
77   else
78     {
79       /* For some reason bfd_perform_relocation always effectively
80 	 ignores the addend for a COFF target when producing
81 	 relocatable output.  This seems to be always wrong for 860
82 	 COFF, so we handle the addend here instead.  */
83       diff = reloc_entry->addend;
84     }
85 
86 #define DOIT(x) \
87   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
88 
89     if (diff != 0)
90       {
91 	reloc_howto_type *howto = reloc_entry->howto;
92 	unsigned char *addr = (unsigned char *) data + reloc_entry->address;
93 
94 	switch (howto->size)
95 	  {
96 	  case 0:
97 	    {
98 	      char x = bfd_get_8 (abfd, addr);
99 	      DOIT (x);
100 	      bfd_put_8 (abfd, x, addr);
101 	    }
102 	    break;
103 
104 	  case 1:
105 	    {
106 	      short x = bfd_get_16 (abfd, addr);
107 	      DOIT (x);
108 	      bfd_put_16 (abfd, (bfd_vma) x, addr);
109 	    }
110 	    break;
111 
112 	  case 2:
113 	    {
114 	      long x = bfd_get_32 (abfd, addr);
115 	      DOIT (x);
116 	      bfd_put_32 (abfd, (bfd_vma) x, addr);
117 	    }
118 	    break;
119 
120 	  default:
121 	    abort ();
122 	  }
123       }
124 
125   /* Now let bfd_perform_relocation finish everything up.  */
126   return bfd_reloc_continue;
127 }
128 
129 /* This is just a temporary measure until we teach bfd to generate
130    these relocations.  */
131 
132 static bfd_reloc_status_type
133 coff_i860_reloc_nyi (bfd *abfd ATTRIBUTE_UNUSED,
134 		     arelent *reloc_entry,
135 		     asymbol *symbol ATTRIBUTE_UNUSED,
136 		     void *data ATTRIBUTE_UNUSED,
137 		     asection *input_section ATTRIBUTE_UNUSED,
138 		     bfd *output_bfd ATTRIBUTE_UNUSED,
139 		     char **error_message ATTRIBUTE_UNUSED)
140 {
141   reloc_howto_type *howto = reloc_entry->howto;
142   fprintf (stderr, _("Relocation `%s' not yet implemented\n"), howto->name);
143   return bfd_reloc_notsupported;
144 }
145 
146 #ifndef PCRELOFFSET
147 #define PCRELOFFSET FALSE
148 #endif
149 
150 static reloc_howto_type howto_table[] =
151 {
152   EMPTY_HOWTO (0),
153   EMPTY_HOWTO (1),
154   EMPTY_HOWTO (2),
155   EMPTY_HOWTO (3),
156   EMPTY_HOWTO (4),
157   EMPTY_HOWTO (5),
158   HOWTO (R_DIR32,               /* type */
159 	 0,	                /* rightshift */
160 	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
161 	 32,	                /* bitsize */
162 	 FALSE,	                /* pc_relative */
163 	 0,	                /* bitpos */
164 	 complain_overflow_bitfield, /* complain_on_overflow */
165 	 coff_i860_reloc,       /* special_function */
166 	 "dir32",               /* name */
167 	 TRUE,	                /* partial_inplace */
168 	 0xffffffff,            /* src_mask */
169 	 0xffffffff,            /* dst_mask */
170 	 TRUE),                /* pcrel_offset */
171   /* {7}, */
172   HOWTO (R_IMAGEBASE,            /* type */
173 	 0,	                /* rightshift */
174 	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
175 	 32,	                /* bitsize */
176 	 FALSE,	                /* pc_relative */
177 	 0,	                /* bitpos */
178 	 complain_overflow_bitfield, /* complain_on_overflow */
179 	 coff_i860_reloc,       /* special_function */
180 	 "rva32",	           /* name */
181 	 TRUE,	                /* partial_inplace */
182 	 0xffffffff,            /* src_mask */
183 	 0xffffffff,            /* dst_mask */
184 	 FALSE),                /* pcrel_offset */
185   EMPTY_HOWTO (010),
186   EMPTY_HOWTO (011),
187   EMPTY_HOWTO (012),
188   EMPTY_HOWTO (013),
189   EMPTY_HOWTO (014),
190   EMPTY_HOWTO (015),
191   EMPTY_HOWTO (016),
192   HOWTO (R_RELBYTE,		/* type */
193 	 0,			/* rightshift */
194 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
195 	 8,			/* bitsize */
196 	 FALSE,			/* pc_relative */
197 	 0,			/* bitpos */
198 	 complain_overflow_bitfield, /* complain_on_overflow */
199 	 coff_i860_reloc,	/* special_function */
200 	 "8",			/* name */
201 	 TRUE,			/* partial_inplace */
202 	 0x000000ff,		/* src_mask */
203 	 0x000000ff,		/* dst_mask */
204 	 PCRELOFFSET),		/* pcrel_offset */
205   HOWTO (R_RELWORD,		/* type */
206 	 0,			/* rightshift */
207 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
208 	 16,			/* bitsize */
209 	 FALSE,			/* pc_relative */
210 	 0,			/* bitpos */
211 	 complain_overflow_bitfield, /* complain_on_overflow */
212 	 coff_i860_reloc,	/* special_function */
213 	 "16",			/* name */
214 	 TRUE,			/* partial_inplace */
215 	 0x0000ffff,		/* src_mask */
216 	 0x0000ffff,		/* dst_mask */
217 	 PCRELOFFSET),		/* pcrel_offset */
218   HOWTO (R_RELLONG,		/* type */
219 	 0,			/* rightshift */
220 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
221 	 32,			/* bitsize */
222 	 FALSE,			/* pc_relative */
223 	 0,			/* bitpos */
224 	 complain_overflow_bitfield, /* complain_on_overflow */
225 	 coff_i860_reloc,	/* special_function */
226 	 "32",			/* name */
227 	 TRUE,			/* partial_inplace */
228 	 0xffffffff,		/* src_mask */
229 	 0xffffffff,		/* dst_mask */
230 	 PCRELOFFSET),		/* pcrel_offset */
231   HOWTO (R_PCRBYTE,		/* type */
232 	 0,			/* rightshift */
233 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
234 	 8,			/* bitsize */
235 	 TRUE,			/* pc_relative */
236 	 0,			/* bitpos */
237 	 complain_overflow_signed, /* complain_on_overflow */
238 	 coff_i860_reloc,	/* special_function */
239 	 "DISP8",		/* name */
240 	 TRUE,			/* partial_inplace */
241 	 0x000000ff,		/* src_mask */
242 	 0x000000ff,		/* dst_mask */
243 	 PCRELOFFSET),		/* pcrel_offset */
244   HOWTO (R_PCRWORD,		/* type */
245 	 0,			/* rightshift */
246 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
247 	 16,			/* bitsize */
248 	 TRUE,			/* pc_relative */
249 	 0,			/* bitpos */
250 	 complain_overflow_signed, /* complain_on_overflow */
251 	 coff_i860_reloc,	/* special_function */
252 	 "DISP16",		/* name */
253 	 TRUE,			/* partial_inplace */
254 	 0x0000ffff,		/* src_mask */
255 	 0x0000ffff,		/* dst_mask */
256 	 PCRELOFFSET),		/* pcrel_offset */
257   HOWTO (R_PCRLONG,		/* type */
258 	 0,			/* rightshift */
259 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
260 	 32,			/* bitsize */
261 	 TRUE,			/* pc_relative */
262 	 0,			/* bitpos */
263 	 complain_overflow_signed, /* complain_on_overflow */
264 	 coff_i860_reloc,	/* special_function */
265 	 "DISP32",		/* name */
266 	 TRUE,			/* partial_inplace */
267 	 0xffffffff,		/* src_mask */
268 	 0xffffffff,		/* dst_mask */
269 	 PCRELOFFSET),		/* pcrel_offset */
270   EMPTY_HOWTO (0x15),
271   EMPTY_HOWTO (0x16),
272   EMPTY_HOWTO (0x17),
273   EMPTY_HOWTO (0x18),
274   EMPTY_HOWTO (0x19),
275   EMPTY_HOWTO (0x1a),
276   EMPTY_HOWTO (0x1b),
277   HOWTO (COFF860_R_PAIR,	/* type */
278 	 0,			/* rightshift */
279 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
280 	 16,			/* bitsize */
281 	 FALSE,			/* pc_relative */
282 	 0,			/* bitpos */
283 	 complain_overflow_dont, /* complain_on_overflow */
284 	 coff_i860_reloc_nyi,	/* special_function */
285 	 "PAIR",		/* name */
286 	 FALSE,			/* partial_inplace */
287 	 0xffff,		/* src_mask */
288 	 0xffff,		/* dst_mask */
289 	 FALSE),	        /* pcrel_offset */
290   EMPTY_HOWTO (0x1d),
291   HOWTO (COFF860_R_HIGH,	/* type */
292 	 16,			/* rightshift */
293 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
294 	 16,			/* bitsize */
295 	 FALSE,			/* pc_relative */
296 	 0,			/* bitpos */
297 	 complain_overflow_dont, /* complain_on_overflow */
298 	 coff_i860_reloc,	/* special_function */
299 	 "HIGH",		/* name */
300 	 FALSE,			/* partial_inplace */
301 	 0xffff,		/* src_mask */
302 	 0xffff,		/* dst_mask */
303 	 FALSE),	        /* pcrel_offset */
304   HOWTO (COFF860_R_LOW0,        /* type */
305 	 0,			/* rightshift */
306 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
307 	 16,			/* bitsize */
308 	 FALSE,			/* pc_relative */
309 	 0,			/* bitpos */
310 	 complain_overflow_dont, /* complain_on_overflow */
311 	 coff_i860_reloc,	/* special_function */
312 	 "LOW0",		/* name */
313 	 FALSE,			/* partial_inplace */
314 	 0xffff,		/* src_mask */
315 	 0xffff,		/* dst_mask */
316 	 FALSE),	        /* pcrel_offset */
317   HOWTO (COFF860_R_LOW1,        /* type */
318 	 0,			/* rightshift */
319 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
320 	 16,			/* bitsize */
321 	 FALSE,			/* pc_relative */
322 	 0,			/* bitpos */
323 	 complain_overflow_dont, /* complain_on_overflow */
324 	 coff_i860_reloc,	/* special_function */
325 	 "LOW1",		/* name */
326 	 FALSE,			/* partial_inplace */
327 	 0xfffe,		/* src_mask */
328 	 0xfffe,		/* dst_mask */
329 	 FALSE),	        /* pcrel_offset */
330   HOWTO (COFF860_R_LOW2,        /* type */
331 	 0,			/* rightshift */
332 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
333 	 16,			/* bitsize */
334 	 FALSE,			/* pc_relative */
335 	 0,			/* bitpos */
336 	 complain_overflow_dont, /* complain_on_overflow */
337 	 coff_i860_reloc,	/* special_function */
338 	 "LOW2",		/* name */
339 	 FALSE,			/* partial_inplace */
340 	 0xfffc,		/* src_mask */
341 	 0xfffc,		/* dst_mask */
342 	 FALSE),	        /* pcrel_offset */
343   HOWTO (COFF860_R_LOW3,        /* type */
344 	 0,			/* rightshift */
345 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
346 	 16,			/* bitsize */
347 	 FALSE,			/* pc_relative */
348 	 0,			/* bitpos */
349 	 complain_overflow_dont, /* complain_on_overflow */
350 	 coff_i860_reloc,	/* special_function */
351 	 "LOW3",		/* name */
352 	 FALSE,			/* partial_inplace */
353 	 0xfff8,		/* src_mask */
354 	 0xfff8,		/* dst_mask */
355 	 FALSE),	        /* pcrel_offset */
356   HOWTO (COFF860_R_LOW4,        /* type */
357 	 0,			/* rightshift */
358 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
359 	 16,			/* bitsize */
360 	 FALSE,			/* pc_relative */
361 	 0,			/* bitpos */
362 	 complain_overflow_dont, /* complain_on_overflow */
363 	 coff_i860_reloc,	/* special_function */
364 	 "LOW4",		/* name */
365 	 FALSE,			/* partial_inplace */
366 	 0xfff0,		/* src_mask */
367 	 0xfff0,		/* dst_mask */
368 	 FALSE),	        /* pcrel_offset */
369   HOWTO (COFF860_R_SPLIT0,      /* type */
370 	 0,			/* rightshift */
371 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
372 	 16,			/* bitsize */
373 	 FALSE,			/* pc_relative */
374 	 0,			/* bitpos */
375 	 complain_overflow_dont, /* complain_on_overflow */
376 	 coff_i860_reloc_nyi,	/* special_function */
377 	 "SPLIT0",		/* name */
378 	 FALSE,			/* partial_inplace */
379 	 0x1f07ff,		/* src_mask */
380 	 0x1f07ff,		/* dst_mask */
381 	 FALSE),	        /* pcrel_offset */
382   HOWTO (COFF860_R_SPLIT1,      /* type */
383 	 0,			/* rightshift */
384 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
385 	 16,			/* bitsize */
386 	 FALSE,			/* pc_relative */
387 	 0,			/* bitpos */
388 	 complain_overflow_dont, /* complain_on_overflow */
389 	 coff_i860_reloc_nyi,	/* special_function */
390 	 "SPLIT1",		/* name */
391 	 FALSE,			/* partial_inplace */
392 	 0x1f07fe,		/* src_mask */
393 	 0x1f07fe,		/* dst_mask */
394 	 FALSE),	        /* pcrel_offset */
395   HOWTO (COFF860_R_SPLIT2,      /* type */
396 	 0,			/* rightshift */
397 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
398 	 16,			/* bitsize */
399 	 FALSE,			/* pc_relative */
400 	 0,			/* bitpos */
401 	 complain_overflow_dont, /* complain_on_overflow */
402 	 coff_i860_reloc_nyi,	/* special_function */
403 	 "SPLIT2",		/* name */
404 	 FALSE,			/* partial_inplace */
405 	 0x1f07fc,		/* src_mask */
406 	 0x1f07fc,		/* dst_mask */
407 	 FALSE),	        /* pcrel_offset */
408   HOWTO (COFF860_R_HIGHADJ,     /* type */
409 	 0,			/* rightshift */
410 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
411 	 16,			/* bitsize */
412 	 FALSE,			/* pc_relative */
413 	 0,			/* bitpos */
414 	 complain_overflow_dont, /* complain_on_overflow */
415 	 coff_i860_reloc_nyi,	/* special_function */
416 	 "HIGHADJ",		/* name */
417 	 FALSE,			/* partial_inplace */
418 	 0xffff,		/* src_mask */
419 	 0xffff,		/* dst_mask */
420 	 FALSE),	        /* pcrel_offset */
421   HOWTO (COFF860_R_BRADDR,      /* type */
422 	 2,			/* rightshift */
423 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
424 	 26,			/* bitsize */
425 	 TRUE,			/* pc_relative */
426 	 0,			/* bitpos */
427 	 complain_overflow_bitfield, /* complain_on_overflow */
428 	 coff_i860_reloc_nyi,	/* special_function */
429 	 "BRADDR",		/* name */
430 	 FALSE,			/* partial_inplace */
431 	 0x3ffffff,		/* src_mask */
432 	 0x3ffffff,		/* dst_mask */
433 	 TRUE)		        /* pcrel_offset */
434 };
435 
436 /* Turn a howto into a reloc number.  */
437 
438 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
439 #define BADMAG(x) I860BADMAG(x)
440 #define I860 1			/* Customize coffcode.h */
441 
442 #define RTYPE2HOWTO(cache_ptr, dst)					\
443   ((cache_ptr)->howto =							\
444    ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])	\
445     ? howto_table + (dst)->r_type					\
446     : NULL))
447 
448 /* For 860 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
449    library.  On some other COFF targets STYP_BSS is normally
450    STYP_NOLOAD.  */
451 #define BSS_NOLOAD_IS_SHARED_LIBRARY
452 
453 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
454    the object file contains the value of the common symbol.  By the
455    time this is called, the linker may be using a different symbol
456    from a different object file with a different value.  Therefore, we
457    hack wildly to locate the original symbol from this file so that we
458    can make the correct adjustment.  This macro sets coffsym to the
459    symbol from the original file, and uses it to set the addend value
460    correctly.  If this is not a common symbol, the usual addend
461    calculation is done, except that an additional tweak is needed for
462    PC relative relocs.
463    FIXME: This macro refers to symbols and asect; these are from the
464    calling function, not the macro arguments.  */
465 
466 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)
467 
468 /* We use the special COFF backend linker.  */
469 #define coff_relocate_section _bfd_coff_generic_relocate_section
470 
471 static reloc_howto_type *
472 coff_i860_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
473 			  asection *sec,
474 			  struct internal_reloc *rel,
475 			  struct coff_link_hash_entry *h,
476 			  struct internal_syment *sym,
477 			  bfd_vma *addendp)
478 {
479 
480   reloc_howto_type *howto;
481 
482   if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
483     {
484       bfd_set_error (bfd_error_bad_value);
485       return NULL;
486     }
487 
488   howto = howto_table + rel->r_type;
489 
490   if (howto->pc_relative)
491     *addendp += sec->vma;
492 
493   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
494     {
495       /* This is a common symbol.  The section contents include the
496 	 size (sym->n_value) as an addend.  The relocate_section
497 	 function will be adding in the final value of the symbol.  We
498 	 need to subtract out the current size in order to get the
499 	 correct result.  */
500 
501       BFD_ASSERT (h != NULL);
502 
503       /* I think we *do* want to bypass this.  If we don't, I have seen some data
504 	 parameters get the wrong relocation address.  If I link two versions
505 	 with and without this section bypassed and then do a binary comparison,
506 	 the addresses which are different can be looked up in the map.  The
507 	 case in which this section has been bypassed has addresses which correspond
508 	 to values I can find in the map.  */
509       *addendp -= sym->n_value;
510     }
511 
512   /* If the output symbol is common (in which case this must be a
513      relocatable link), we need to add in the final size of the
514      common symbol.  */
515   if (h != NULL && h->root.type == bfd_link_hash_common)
516     *addendp += h->root.u.c.size;
517 
518   return howto;
519 }
520 
521 static reloc_howto_type *
522 coff_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
523 			     bfd_reloc_code_real_type code)
524 {
525   switch (code)
526     {
527     case BFD_RELOC_32:
528       return howto_table + R_DIR32;
529     case BFD_RELOC_860_PC26:
530       return howto_table + COFF860_R_BRADDR;
531     case BFD_RELOC_860_PC16:
532       /* ??? How to handle PC16 for COFF?  SPLIT0 is close for now.  */
533       return howto_table + COFF860_R_SPLIT0;
534     case BFD_RELOC_860_LOW0:
535       return howto_table + COFF860_R_LOW0;
536     case BFD_RELOC_860_SPLIT0:
537       return howto_table + COFF860_R_SPLIT0;
538     case BFD_RELOC_860_LOW1:
539       return howto_table + COFF860_R_LOW1;
540     case BFD_RELOC_860_SPLIT1:
541       return howto_table + COFF860_R_SPLIT1;
542     case BFD_RELOC_860_LOW2:
543       return howto_table + COFF860_R_LOW2;
544     case BFD_RELOC_860_SPLIT2:
545       return howto_table + COFF860_R_SPLIT2;
546     case BFD_RELOC_860_LOW3:
547       return howto_table + COFF860_R_LOW3;
548     case BFD_RELOC_860_HIGHADJ:
549       return howto_table + COFF860_R_HIGHADJ;
550     case BFD_RELOC_860_HIGH:
551       return howto_table + COFF860_R_HIGH;
552     default:
553       BFD_FAIL ();
554       return 0;
555     }
556 }
557 
558 /* This is called from coff_slurp_reloc_table for each relocation
559    entry.  This special handling is due to the `PAIR' relocation
560    which has a different meaning for the `r_symndx' field.  */
561 
562 static void
563 i860_reloc_processing (arelent *cache_ptr, struct internal_reloc *dst,
564 		       asymbol **symbols, bfd *abfd, asection *asect)
565 {
566   if (dst->r_type == COFF860_R_PAIR)
567     {
568       /* Handle the PAIR relocation specially.  */
569       cache_ptr->howto = howto_table + dst->r_type;
570       cache_ptr->address = dst->r_vaddr;
571       cache_ptr->addend = dst->r_symndx;
572       cache_ptr->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
573     }
574   else
575     {
576       /* For every other relocation, do exactly what coff_slurp_reloc_table
577          would do (which this code is taken directly from).  */
578       asymbol *ptr = NULL;
579       cache_ptr->address = dst->r_vaddr;
580 
581       if (dst->r_symndx != -1)
582 	{
583 	  if (dst->r_symndx < 0 || dst->r_symndx >= obj_conv_table_size (abfd))
584 	    {
585 	      (*_bfd_error_handler)
586 		(_("%B: warning: illegal symbol index %ld in relocs"),
587 		 abfd, dst->r_symndx);
588 	      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
589 	      ptr = NULL;
590 	    }
591 	  else
592 	    {
593 	      cache_ptr->sym_ptr_ptr = (symbols
594 					+ obj_convert (abfd)[dst->r_symndx]);
595 	      ptr = *(cache_ptr->sym_ptr_ptr);
596 	    }
597 	}
598       else
599 	{
600 	  cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
601 	  ptr = NULL;
602 	}
603 
604       /* The symbols definitions that we have read in have been
605 	 relocated as if their sections started at 0. But the offsets
606 	 refering to the symbols in the raw data have not been
607 	 modified, so we have to have a negative addend to compensate.
608 
609 	 Note that symbols which used to be common must be left alone.  */
610 
611       /* Calculate any reloc addend by looking at the symbol.  */
612       CALC_ADDEND (abfd, ptr, (*dst), cache_ptr);
613 
614       cache_ptr->address -= asect->vma;
615 
616       /* Fill in the cache_ptr->howto field from dst->r_type.  */
617       RTYPE2HOWTO (cache_ptr, dst);
618     }
619 }
620 
621 #define coff_rtype_to_howto		coff_i860_rtype_to_howto
622 #define coff_bfd_reloc_type_lookup	coff_i860_reloc_type_lookup
623 
624 #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
625   i860_reloc_processing (relent, reloc, symbols, abfd, section)
626 
627 #include "coffcode.h"
628 
629 static const bfd_target *
630 i3coff_object_p(bfd *a)
631 {
632   return coff_object_p (a);
633 }
634 
635 const bfd_target
636 #ifdef TARGET_SYM
637   TARGET_SYM =
638 #else
639   i860coff_vec =
640 #endif
641 {
642 #ifdef TARGET_NAME
643   TARGET_NAME,
644 #else
645   "coff-i860",			/* name */
646 #endif
647   bfd_target_coff_flavour,
648   BFD_ENDIAN_LITTLE,		/* data byte order is little */
649   BFD_ENDIAN_LITTLE,		/* header byte order is little */
650 
651   (HAS_RELOC | EXEC_P |		/* object flags */
652    HAS_LINENO | HAS_DEBUG |
653    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
654 
655   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
656   '_',				/* leading underscore */
657   '/',				/* ar_pad_char */
658   15,				/* ar_max_namelen */
659 
660   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
661      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
662      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
663   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
664      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
665      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
666 
667 /* Note that we allow an object file to be treated as a core file as well.  */
668     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
669        bfd_generic_archive_p, i3coff_object_p},
670     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
671        bfd_false},
672     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
673        _bfd_write_archive_contents, bfd_false},
674 
675      BFD_JUMP_TABLE_GENERIC (coff),
676      BFD_JUMP_TABLE_COPY (coff),
677      BFD_JUMP_TABLE_CORE (_bfd_nocore),
678      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
679      BFD_JUMP_TABLE_SYMBOLS (coff),
680      BFD_JUMP_TABLE_RELOCS (coff),
681      BFD_JUMP_TABLE_WRITE (coff),
682      BFD_JUMP_TABLE_LINK (coff),
683      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
684 
685   NULL,
686 
687   COFF_SWAP_TABLE
688 };
689