1 /* BFD back-end for Intel 386 COFF files.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Written by Cygnus Support.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26 #include "coff/i386.h"
28 #include "coff/internal.h"
36 static bfd_reloc_status_type coff_i386_reloc
37 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38 static reloc_howto_type *coff_i386_rtype_to_howto
39 PARAMS ((bfd *, asection *, struct internal_reloc *,
40 struct coff_link_hash_entry *, struct internal_syment *,
44 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
45 /* The page size is a guess based on ELF. */
47 #define COFF_PAGE_SIZE 0x1000
49 /* For some reason when using i386 COFF the value stored in the .text
50 section for a reference to a common symbol is the value itself plus
51 any desired offset. Ian Taylor, Cygnus Support. */
53 /* If we are producing relocateable output, we need to do some
54 adjustments to the object file that are not done by the
55 bfd_perform_relocation function. This function is called by every
56 reloc type to make any required adjustments. */
58 static bfd_reloc_status_type
59 coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
65 asection *input_section;
71 if (output_bfd == (bfd *) NULL)
72 return bfd_reloc_continue;
75 if (bfd_is_com_section (symbol->section))
77 /* We are relocating a common symbol. The current value in the
78 object file is ORIG + OFFSET, where ORIG is the value of the
79 common symbol as seen by the object file when it was compiled
80 (this may be zero if the symbol was undefined) and OFFSET is
81 the offset into the common symbol (normally zero, but may be
82 non-zero when referring to a field in a common structure).
83 ORIG is the negative of reloc_entry->addend, which is set by
84 the CALC_ADDEND macro below. We want to replace the value in
85 the object file with NEW + OFFSET, where NEW is the value of
86 the common symbol which we are going to put in the final
87 object file. NEW is symbol->value. */
88 diff = symbol->value + reloc_entry->addend;
92 /* For some reason bfd_perform_relocation always effectively
93 ignores the addend for a COFF target when producing
94 relocateable output. This seems to be always wrong for 386
95 COFF, so we handle the addend here instead. */
96 diff = reloc_entry->addend;
101 if (reloc_entry->howto->type == 7)
103 /* diff -= coff_data(output_bfd)->link_info->pe_info.image_base.value;*/
109 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
113 reloc_howto_type *howto = reloc_entry->howto;
114 unsigned char *addr = (unsigned char *) data + reloc_entry->address;
120 char x = bfd_get_8 (abfd, addr);
122 bfd_put_8 (abfd, x, addr);
128 short x = bfd_get_16 (abfd, addr);
130 bfd_put_16 (abfd, x, addr);
136 long x = bfd_get_32 (abfd, addr);
138 bfd_put_32 (abfd, x, addr);
147 /* Now let bfd_perform_relocation finish everything up. */
148 return bfd_reloc_continue;
152 /* Return true if this relocation should
153 appear in the output .reloc section. */
155 static boolean in_reloc_p(abfd, howto)
157 reloc_howto_type *howto;
159 return ! howto->pc_relative && howto->type != R_IMAGEBASE;
164 #define PCRELOFFSET false
167 static reloc_howto_type howto_table[] =
175 HOWTO (R_DIR32, /* type */
177 2, /* size (0 = byte, 1 = short, 2 = long) */
179 false, /* pc_relative */
181 complain_overflow_bitfield, /* complain_on_overflow */
182 coff_i386_reloc, /* special_function */
184 true, /* partial_inplace */
185 0xffffffff, /* src_mask */
186 0xffffffff, /* dst_mask */
187 true), /* pcrel_offset */
189 HOWTO (R_IMAGEBASE, /* type */
191 2, /* size (0 = byte, 1 = short, 2 = long) */
193 false, /* pc_relative */
195 complain_overflow_bitfield, /* complain_on_overflow */
196 coff_i386_reloc, /* special_function */
198 true, /* partial_inplace */
199 0xffffffff, /* src_mask */
200 0xffffffff, /* dst_mask */
201 false), /* pcrel_offset */
209 HOWTO (R_RELBYTE, /* type */
211 0, /* size (0 = byte, 1 = short, 2 = long) */
213 false, /* pc_relative */
215 complain_overflow_bitfield, /* complain_on_overflow */
216 coff_i386_reloc, /* special_function */
218 true, /* partial_inplace */
219 0x000000ff, /* src_mask */
220 0x000000ff, /* dst_mask */
221 PCRELOFFSET), /* pcrel_offset */
222 HOWTO (R_RELWORD, /* type */
224 1, /* size (0 = byte, 1 = short, 2 = long) */
226 false, /* pc_relative */
228 complain_overflow_bitfield, /* complain_on_overflow */
229 coff_i386_reloc, /* special_function */
231 true, /* partial_inplace */
232 0x0000ffff, /* src_mask */
233 0x0000ffff, /* dst_mask */
234 PCRELOFFSET), /* pcrel_offset */
235 HOWTO (R_RELLONG, /* type */
237 2, /* size (0 = byte, 1 = short, 2 = long) */
239 false, /* pc_relative */
241 complain_overflow_bitfield, /* complain_on_overflow */
242 coff_i386_reloc, /* special_function */
244 true, /* partial_inplace */
245 0xffffffff, /* src_mask */
246 0xffffffff, /* dst_mask */
247 PCRELOFFSET), /* pcrel_offset */
248 HOWTO (R_PCRBYTE, /* type */
250 0, /* size (0 = byte, 1 = short, 2 = long) */
252 true, /* pc_relative */
254 complain_overflow_signed, /* complain_on_overflow */
255 coff_i386_reloc, /* special_function */
257 true, /* partial_inplace */
258 0x000000ff, /* src_mask */
259 0x000000ff, /* dst_mask */
260 PCRELOFFSET), /* pcrel_offset */
261 HOWTO (R_PCRWORD, /* type */
263 1, /* size (0 = byte, 1 = short, 2 = long) */
265 true, /* pc_relative */
267 complain_overflow_signed, /* complain_on_overflow */
268 coff_i386_reloc, /* special_function */
270 true, /* partial_inplace */
271 0x0000ffff, /* src_mask */
272 0x0000ffff, /* dst_mask */
273 PCRELOFFSET), /* pcrel_offset */
274 HOWTO (R_PCRLONG, /* type */
276 2, /* size (0 = byte, 1 = short, 2 = long) */
278 true, /* pc_relative */
280 complain_overflow_signed, /* complain_on_overflow */
281 coff_i386_reloc, /* special_function */
283 true, /* partial_inplace */
284 0xffffffff, /* src_mask */
285 0xffffffff, /* dst_mask */
286 PCRELOFFSET) /* pcrel_offset */
289 /* Turn a howto into a reloc nunmber */
291 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
292 #define BADMAG(x) I386BADMAG(x)
293 #define I386 1 /* Customize coffcode.h */
295 #define RTYPE2HOWTO(cache_ptr, dst) \
296 (cache_ptr)->howto = howto_table + (dst)->r_type;
298 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
299 library. On some other COFF targets STYP_BSS is normally
301 #define BSS_NOLOAD_IS_SHARED_LIBRARY
303 /* Compute the addend of a reloc. If the reloc is to a common symbol,
304 the object file contains the value of the common symbol. By the
305 time this is called, the linker may be using a different symbol
306 from a different object file with a different value. Therefore, we
307 hack wildly to locate the original symbol from this file so that we
308 can make the correct adjustment. This macro sets coffsym to the
309 symbol from the original file, and uses it to set the addend value
310 correctly. If this is not a common symbol, the usual addend
311 calculation is done, except that an additional tweak is needed for
313 FIXME: This macro refers to symbols and asect; these are from the
314 calling function, not the macro arguments. */
316 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
318 coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
319 if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
320 coffsym = (obj_symbols (abfd) \
321 + (cache_ptr->sym_ptr_ptr - symbols)); \
323 coffsym = coff_symbol_from (abfd, ptr); \
324 if (coffsym != (coff_symbol_type *) NULL \
325 && coffsym->native->u.syment.n_scnum == 0) \
326 cache_ptr->addend = - coffsym->native->u.syment.n_value; \
327 else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
328 && ptr->section != (asection *) NULL) \
329 cache_ptr->addend = - (ptr->section->vma + ptr->value); \
331 cache_ptr->addend = 0; \
332 if (ptr && howto_table[reloc.r_type].pc_relative) \
333 cache_ptr->addend += asect->vma; \
336 /* We use the special COFF backend linker. */
337 #define coff_relocate_section _bfd_coff_generic_relocate_section
339 static reloc_howto_type *
340 coff_i386_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
343 struct internal_reloc *rel;
344 struct coff_link_hash_entry *h;
345 struct internal_syment *sym;
349 reloc_howto_type *howto;
351 howto = howto_table + rel->r_type;
357 if (howto->pc_relative)
358 *addendp += sec->vma;
360 if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
362 /* This is a common symbol. The section contents include the
363 size (sym->n_value) as an addend. The relocate_section
364 function will be adding in the final value of the symbol. We
365 need to subtract out the current size in order to get the
368 BFD_ASSERT (h != NULL);
372 /* I think we *do* want to bypass this. If we don't, I have seen some data
373 parameters get the wrong relcation address. If I link two versions
374 with and without this section bypassed and then do a binary comparison,
375 the addresses which are different can be looked up in the map. The
376 case in which this section has been bypassed has addresses which correspond
377 to values I can find in the map */
378 *addendp -= sym->n_value;
382 /* If the output symbol is common (in which case this must be a
383 relocateable link), we need to add in the final size of the
385 if (h != NULL && h->root.type == bfd_link_hash_common)
386 *addendp += h->root.u.c.size;
390 if (howto->pc_relative)
393 if (rel->r_type == R_IMAGEBASE)
395 *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
403 #define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
406 static reloc_howto_type *
407 coff_i386_reloc_type_lookup (abfd, code)
409 bfd_reloc_code_real_type code;
414 return howto_table +R_IMAGEBASE;
416 return howto_table + R_DIR32;
417 case BFD_RELOC_32_PCREL:
418 return howto_table + R_PCRLONG;
427 #define coff_rtype_to_howto coff_i386_rtype_to_howto
429 #include "coffcode.h"
431 static const bfd_target *
435 return coff_object_p(a);
448 "coff-i386", /* name */
450 bfd_target_coff_flavour,
451 BFD_ENDIAN_LITTLE, /* data byte order is little */
452 BFD_ENDIAN_LITTLE, /* header byte order is little */
454 (HAS_RELOC | EXEC_P | /* object flags */
455 HAS_LINENO | HAS_DEBUG |
456 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
458 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
459 #ifdef TARGET_UNDERSCORE
460 TARGET_UNDERSCORE, /* leading underscore */
462 0, /* leading underscore */
464 '/', /* ar_pad_char */
465 15, /* ar_max_namelen */
467 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
468 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
469 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
470 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
471 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
472 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
474 /* Note that we allow an object file to be treated as a core file as well. */
475 {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
476 bfd_generic_archive_p, i3coff_object_p},
477 {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
479 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
480 _bfd_write_archive_contents, bfd_false},
482 BFD_JUMP_TABLE_GENERIC (coff),
483 BFD_JUMP_TABLE_COPY (coff),
484 BFD_JUMP_TABLE_CORE (_bfd_nocore),
485 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
486 BFD_JUMP_TABLE_SYMBOLS (coff),
487 BFD_JUMP_TABLE_RELOCS (coff),
488 BFD_JUMP_TABLE_WRITE (coff),
489 BFD_JUMP_TABLE_LINK (coff),
490 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),