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