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