2000-11-10 Kazu Hirata <kazu@hxi.com>
[platform/upstream/binutils.git] / bfd / coff-i860.c
1 /* BFD back-end for Intel 860 COFF files.
2    Copyright 1990, 91, 92, 93, 94, 95, 97, 1999 Free Software Foundation, Inc.
3    Created mostly by substituting "860" for "386" in coff-i386.c
4    Harry Dolan <dolan@ssd.intel.com>, October 1995
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
26 #include "coff/i860.h"
27
28 #include "coff/internal.h"
29
30 #include "libcoff.h"
31
32 static bfd_reloc_status_type coff_i860_reloc
33   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
34 static reloc_howto_type *coff_i860_rtype_to_howto
35   PARAMS ((bfd *, asection *, struct internal_reloc *,
36            struct coff_link_hash_entry *, struct internal_syment *,
37            bfd_vma *));
38
39 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
40 /* The page size is a guess based on ELF.  */
41
42 #define COFF_PAGE_SIZE 0x1000
43
44 /* For some reason when using i860 COFF the value stored in the .text
45    section for a reference to a common symbol is the value itself plus
46    any desired offset.  Ian Taylor, Cygnus Support.  */
47
48 /* If we are producing relocateable output, we need to do some
49    adjustments to the object file that are not done by the
50    bfd_perform_relocation function.  This function is called by every
51    reloc type to make any required adjustments.  */
52
53 static bfd_reloc_status_type
54 coff_i860_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
55                  error_message)
56      bfd *abfd;
57      arelent *reloc_entry;
58      asymbol *symbol;
59      PTR data;
60      asection *input_section ATTRIBUTE_UNUSED;
61      bfd *output_bfd;
62      char **error_message ATTRIBUTE_UNUSED;
63 {
64   symvalue diff;
65
66   if (output_bfd == (bfd *) NULL)
67     return bfd_reloc_continue;
68
69   if (bfd_is_com_section (symbol->section))
70     {
71       /* We are relocating a common symbol.  The current value in the
72          object file is ORIG + OFFSET, where ORIG is the value of the
73          common symbol as seen by the object file when it was compiled
74          (this may be zero if the symbol was undefined) and OFFSET is
75          the offset into the common symbol (normally zero, but may be
76          non-zero when referring to a field in a common structure).
77          ORIG is the negative of reloc_entry->addend, which is set by
78          the CALC_ADDEND macro below.  We want to replace the value in
79          the object file with NEW + OFFSET, where NEW is the value of
80          the common symbol which we are going to put in the final
81          object file.  NEW is symbol->value.  */
82       diff = symbol->value + reloc_entry->addend;
83     }
84   else
85     {
86       /* For some reason bfd_perform_relocation always effectively
87          ignores the addend for a COFF target when producing
88          relocateable output.  This seems to be always wrong for 860
89          COFF, so we handle the addend here instead.  */
90       diff = reloc_entry->addend;
91     }
92
93 #define DOIT(x) \
94   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
95
96     if (diff != 0)
97       {
98         reloc_howto_type *howto = reloc_entry->howto;
99         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
100
101         switch (howto->size)
102           {
103           case 0:
104             {
105               char x = bfd_get_8 (abfd, addr);
106               DOIT (x);
107               bfd_put_8 (abfd, x, addr);
108             }
109             break;
110
111           case 1:
112             {
113               short x = bfd_get_16 (abfd, addr);
114               DOIT (x);
115               bfd_put_16 (abfd, x, addr);
116             }
117             break;
118
119           case 2:
120             {
121               long x = bfd_get_32 (abfd, addr);
122               DOIT (x);
123               bfd_put_32 (abfd, x, addr);
124             }
125             break;
126
127           default:
128             abort ();
129           }
130       }
131
132   /* Now let bfd_perform_relocation finish everything up.  */
133   return bfd_reloc_continue;
134 }
135
136 #ifndef PCRELOFFSET
137 #define PCRELOFFSET false
138 #endif
139
140 static reloc_howto_type howto_table[] =
141 {
142   EMPTY_HOWTO (0),
143   EMPTY_HOWTO (1),
144   EMPTY_HOWTO (2),
145   EMPTY_HOWTO (3),
146   EMPTY_HOWTO (4),
147   EMPTY_HOWTO (5),
148   HOWTO (R_DIR32,               /* type */
149          0,                     /* rightshift */
150          2,                     /* size (0 = byte, 1 = short, 2 = long) */
151          32,                    /* bitsize */
152          false,                 /* pc_relative */
153          0,                     /* bitpos */
154          complain_overflow_bitfield, /* complain_on_overflow */
155          coff_i860_reloc,       /* special_function */
156          "dir32",               /* name */
157          true,                  /* partial_inplace */
158          0xffffffff,            /* src_mask */
159          0xffffffff,            /* dst_mask */
160          true),                /* pcrel_offset */
161   /* {7}, */
162   HOWTO (R_IMAGEBASE,            /* type */
163          0,                     /* rightshift */
164          2,                     /* size (0 = byte, 1 = short, 2 = long) */
165          32,                    /* bitsize */
166          false,                 /* pc_relative */
167          0,                     /* bitpos */
168          complain_overflow_bitfield, /* complain_on_overflow */
169          coff_i860_reloc,       /* special_function */
170          "rva32",                  /* name */
171          true,                  /* partial_inplace */
172          0xffffffff,            /* src_mask */
173          0xffffffff,            /* dst_mask */
174          false),                /* pcrel_offset */
175   EMPTY_HOWTO (010),
176   EMPTY_HOWTO (011),
177   EMPTY_HOWTO (012),
178   EMPTY_HOWTO (013),
179   EMPTY_HOWTO (014),
180   EMPTY_HOWTO (015),
181   EMPTY_HOWTO (016),
182   HOWTO (R_RELBYTE,             /* type */
183          0,                     /* rightshift */
184          0,                     /* size (0 = byte, 1 = short, 2 = long) */
185          8,                     /* bitsize */
186          false,                 /* pc_relative */
187          0,                     /* bitpos */
188          complain_overflow_bitfield, /* complain_on_overflow */
189          coff_i860_reloc,       /* special_function */
190          "8",                   /* name */
191          true,                  /* partial_inplace */
192          0x000000ff,            /* src_mask */
193          0x000000ff,            /* dst_mask */
194          PCRELOFFSET),          /* pcrel_offset */
195   HOWTO (R_RELWORD,             /* type */
196          0,                     /* rightshift */
197          1,                     /* size (0 = byte, 1 = short, 2 = long) */
198          16,                    /* bitsize */
199          false,                 /* pc_relative */
200          0,                     /* bitpos */
201          complain_overflow_bitfield, /* complain_on_overflow */
202          coff_i860_reloc,       /* special_function */
203          "16",                  /* name */
204          true,                  /* partial_inplace */
205          0x0000ffff,            /* src_mask */
206          0x0000ffff,            /* dst_mask */
207          PCRELOFFSET),          /* pcrel_offset */
208   HOWTO (R_RELLONG,             /* type */
209          0,                     /* rightshift */
210          2,                     /* size (0 = byte, 1 = short, 2 = long) */
211          32,                    /* bitsize */
212          false,                 /* pc_relative */
213          0,                     /* bitpos */
214          complain_overflow_bitfield, /* complain_on_overflow */
215          coff_i860_reloc,       /* special_function */
216          "32",                  /* name */
217          true,                  /* partial_inplace */
218          0xffffffff,            /* src_mask */
219          0xffffffff,            /* dst_mask */
220          PCRELOFFSET),          /* pcrel_offset */
221   HOWTO (R_PCRBYTE,             /* type */
222          0,                     /* rightshift */
223          0,                     /* size (0 = byte, 1 = short, 2 = long) */
224          8,                     /* bitsize */
225          true,                  /* pc_relative */
226          0,                     /* bitpos */
227          complain_overflow_signed, /* complain_on_overflow */
228          coff_i860_reloc,       /* special_function */
229          "DISP8",               /* name */
230          true,                  /* partial_inplace */
231          0x000000ff,            /* src_mask */
232          0x000000ff,            /* dst_mask */
233          PCRELOFFSET),          /* pcrel_offset */
234   HOWTO (R_PCRWORD,             /* type */
235          0,                     /* rightshift */
236          1,                     /* size (0 = byte, 1 = short, 2 = long) */
237          16,                    /* bitsize */
238          true,                  /* pc_relative */
239          0,                     /* bitpos */
240          complain_overflow_signed, /* complain_on_overflow */
241          coff_i860_reloc,       /* special_function */
242          "DISP16",              /* name */
243          true,                  /* partial_inplace */
244          0x0000ffff,            /* src_mask */
245          0x0000ffff,            /* dst_mask */
246          PCRELOFFSET),          /* pcrel_offset */
247   HOWTO (R_PCRLONG,             /* type */
248          0,                     /* rightshift */
249          2,                     /* size (0 = byte, 1 = short, 2 = long) */
250          32,                    /* bitsize */
251          true,                  /* pc_relative */
252          0,                     /* bitpos */
253          complain_overflow_signed, /* complain_on_overflow */
254          coff_i860_reloc,       /* special_function */
255          "DISP32",              /* name */
256          true,                  /* partial_inplace */
257          0xffffffff,            /* src_mask */
258          0xffffffff,            /* dst_mask */
259          PCRELOFFSET)           /* pcrel_offset */
260 };
261
262 /* Turn a howto into a reloc  nunmber */
263
264 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
265 #define BADMAG(x) I860BADMAG(x)
266 #define I860 1                  /* Customize coffcode.h */
267
268 #define RTYPE2HOWTO(cache_ptr, dst) \
269             (cache_ptr)->howto = howto_table + (dst)->r_type;
270
271 /* For 860 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
272    library.  On some other COFF targets STYP_BSS is normally
273    STYP_NOLOAD.  */
274 #define BSS_NOLOAD_IS_SHARED_LIBRARY
275
276 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
277    the object file contains the value of the common symbol.  By the
278    time this is called, the linker may be using a different symbol
279    from a different object file with a different value.  Therefore, we
280    hack wildly to locate the original symbol from this file so that we
281    can make the correct adjustment.  This macro sets coffsym to the
282    symbol from the original file, and uses it to set the addend value
283    correctly.  If this is not a common symbol, the usual addend
284    calculation is done, except that an additional tweak is needed for
285    PC relative relocs.
286    FIXME: This macro refers to symbols and asect; these are from the
287    calling function, not the macro arguments.  */
288
289 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
290   {                                                             \
291     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
292     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
293       coffsym = (obj_symbols (abfd)                             \
294                  + (cache_ptr->sym_ptr_ptr - symbols));         \
295     else if (ptr)                                               \
296       coffsym = coff_symbol_from (abfd, ptr);                   \
297     if (coffsym != (coff_symbol_type *) NULL                    \
298         && coffsym->native->u.syment.n_scnum == 0)              \
299       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
300     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
301              && ptr->section != (asection *) NULL)              \
302       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
303     else                                                        \
304       cache_ptr->addend = 0;                                    \
305     if (ptr && howto_table[reloc.r_type].pc_relative)           \
306       cache_ptr->addend += asect->vma;                          \
307   }
308
309 /* We use the special COFF backend linker.  */
310 #define coff_relocate_section _bfd_coff_generic_relocate_section
311
312 static reloc_howto_type *
313 coff_i860_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
314      bfd *abfd ATTRIBUTE_UNUSED;
315      asection *sec;
316      struct internal_reloc *rel;
317      struct coff_link_hash_entry *h;
318      struct internal_syment *sym;
319      bfd_vma *addendp;
320 {
321
322   reloc_howto_type *howto;
323
324   howto = howto_table + rel->r_type;
325
326   if (howto->pc_relative)
327     *addendp += sec->vma;
328
329   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
330     {
331       /* This is a common symbol.  The section contents include the
332          size (sym->n_value) as an addend.  The relocate_section
333          function will be adding in the final value of the symbol.  We
334          need to subtract out the current size in order to get the
335          correct result.  */
336
337       BFD_ASSERT (h != NULL);
338
339       /* I think we *do* want to bypass this.  If we don't, I have seen some data
340          parameters get the wrong relcation address.  If I link two versions
341          with and without this section bypassed and then do a binary comparison,
342          the addresses which are different can be looked up in the map.  The
343          case in which this section has been bypassed has addresses which correspond
344          to values I can find in the map */
345       *addendp -= sym->n_value;
346     }
347
348   /* If the output symbol is common (in which case this must be a
349      relocateable link), we need to add in the final size of the
350      common symbol.  */
351   if (h != NULL && h->root.type == bfd_link_hash_common)
352     *addendp += h->root.u.c.size;
353
354   return howto;
355 }
356
357 #define coff_rtype_to_howto coff_i860_rtype_to_howto
358
359 #include "coffcode.h"
360
361 static const bfd_target *
362 i3coff_object_p(a)
363      bfd *a;
364 {
365   return coff_object_p(a);
366 }
367
368 const bfd_target
369 #ifdef TARGET_SYM
370   TARGET_SYM =
371 #else
372   i860coff_vec =
373 #endif
374 {
375 #ifdef TARGET_NAME
376   TARGET_NAME,
377 #else
378   "coff-i860",                  /* name */
379 #endif
380   bfd_target_coff_flavour,
381   BFD_ENDIAN_LITTLE,            /* data byte order is little */
382   BFD_ENDIAN_LITTLE,            /* header byte order is little */
383
384   (HAS_RELOC | EXEC_P |         /* object flags */
385    HAS_LINENO | HAS_DEBUG |
386    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
387
388   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
389   '_',                          /* leading underscore */
390   '/',                          /* ar_pad_char */
391   15,                           /* ar_max_namelen */
392
393   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
394      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
395      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
396   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
397      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
398      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
399
400 /* Note that we allow an object file to be treated as a core file as well.  */
401     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
402        bfd_generic_archive_p, i3coff_object_p},
403     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
404        bfd_false},
405     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
406        _bfd_write_archive_contents, bfd_false},
407
408      BFD_JUMP_TABLE_GENERIC (coff),
409      BFD_JUMP_TABLE_COPY (coff),
410      BFD_JUMP_TABLE_CORE (_bfd_nocore),
411      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
412      BFD_JUMP_TABLE_SYMBOLS (coff),
413      BFD_JUMP_TABLE_RELOCS (coff),
414      BFD_JUMP_TABLE_WRITE (coff),
415      BFD_JUMP_TABLE_LINK (coff),
416      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
417
418   NULL,
419
420   COFF_SWAP_TABLE
421 };