1 /* BFD back-end for Motorolla MCore COFF/PE
2 Copyright 1999 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 #include "coff/mcore.h"
25 #include "coff/internal.h"
32 #define BADMAG(x) MCOREBADMAG(x)
35 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
38 /* This file is compiled more than once, but we only compile the
39 final_link routine once. */
40 extern boolean mcore_bfd_coff_final_link
41 PARAMS ((bfd *, struct bfd_link_info *));
43 static struct bfd_link_hash_table * coff_mcore_link_hash_table_create
45 static bfd_reloc_status_type mcore_coff_unsupported_reloc
46 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
47 static boolean coff_mcore_relocate_section
48 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
49 struct internal_reloc *, struct internal_syment *, asection **));
50 static reloc_howto_type * mcore_coff_reloc_type_lookup
51 PARAMS ((bfd *, bfd_reloc_code_real_type));
52 static reloc_howto_type * coff_mcore_rtype_to_howto
53 PARAMS ((bfd *, asection *, struct internal_reloc *,
54 struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
55 static const bfd_target * pe_object_p
60 /* The NT loader points the toc register to &toc + 32768, in order to
61 use the complete range of a 16-bit displacement. We have to adjust
62 for this when we fix up loads displaced off the toc reg. */
63 #define TOC_LOAD_ADJUSTMENT (-32768)
64 #define TOC_SECTION_NAME ".private.toc"
66 /* The main body of code is in coffcode.h. */
67 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
69 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
70 from smaller values. Start with zero, widen, *then* decrement. */
71 #define MINUS_ONE (((bfd_vma)0) - 1)
74 static reloc_howto_type mcore_coff_howto_table[] =
77 HOWTO (IMAGE_REL_MCORE_ABSOLUTE,/* type */
79 0, /* size (0 = byte, 1 = short, 2 = long) */
81 false, /* pc_relative */
83 complain_overflow_dont, /* dont complain_on_overflow */
84 NULL, /* special_function */
85 "ABSOLUTE", /* name */
86 false, /* partial_inplace */
89 false), /* pcrel_offset */
91 HOWTO (IMAGE_REL_MCORE_ADDR32,/* type */
93 2, /* size (0 = byte, 1 = short, 2 = long) */
95 false, /* pc_relative */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 NULL, /* special_function */
100 true, /* partial_inplace */
101 0xffffffff, /* src_mask */
102 0xffffffff, /* dst_mask */
103 false), /* pcrel_offset */
105 /* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions.
106 Should not appear in object files. */
107 HOWTO (IMAGE_REL_MCORE_PCREL_IMM8BY4, /* type */
109 1, /* size (0 = byte, 1 = short, 2 = long) */
111 true, /* pc_relative */
113 complain_overflow_bitfield, /* complain_on_overflow */
114 mcore_coff_unsupported_reloc, /* special_function */
115 "IMM8BY4", /* name */
116 false, /* partial_inplace */
119 true), /* pcrel_offset */
121 /* bsr/bt/bf/br instructions; 11 bits + 1 zero bit
122 Span 2k instructions == 4k bytes.
123 Only useful pieces at the relocated address are the opcode (5 bits) */
124 HOWTO (IMAGE_REL_MCORE_PCREL_IMM11BY2,/* type */
126 1, /* size (0 = byte, 1 = short, 2 = long) */
128 true, /* pc_relative */
130 complain_overflow_signed, /* complain_on_overflow */
131 NULL, /* special_function */
132 "IMM11BY2", /* name */
133 false, /* partial_inplace */
135 0x7ff, /* dst_mask */
136 true), /* pcrel_offset */
138 /* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported. */
139 HOWTO (IMAGE_REL_MCORE_PCREL_IMM4BY2, /* type */
141 1, /* size (0 = byte, 1 = short, 2 = long) */
143 true, /* pc_relative */
145 complain_overflow_bitfield, /* complain_on_overflow */
146 mcore_coff_unsupported_reloc, /* special_function */
147 "IMM4BY2", /* name */
148 false, /* partial_inplace */
151 true), /* pcrel_offset */
153 /* 32-bit pc-relative. Eventually this will help support PIC code. */
154 HOWTO (IMAGE_REL_MCORE_PCREL_32,/* type */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
158 true, /* pc_relative */
160 complain_overflow_bitfield, /* complain_on_overflow */
161 NULL, /* special_function */
162 "PCREL_32", /* name */
163 false, /* partial_inplace */
165 0xffffffff, /* dst_mask */
166 true), /* pcrel_offset */
168 /* Like PCREL_IMM11BY2, this relocation indicates that there is a
169 'jsri' at the specified address. There is a separate relocation
170 entry for the literal pool entry that it references, but we
171 might be able to change the jsri to a bsr if the target turns out
172 to be close enough [even though we won't reclaim the literal pool
173 entry, we'll get some runtime efficiency back]. Note that this
174 is a relocation that we are allowed to safely ignore. */
175 HOWTO (IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2,/* type */
177 1, /* size (0 = byte, 1 = short, 2 = long) */
179 true, /* pc_relative */
181 complain_overflow_signed, /* complain_on_overflow */
182 NULL, /* special_function */
183 "JSR_IMM11BY2", /* name */
184 false, /* partial_inplace */
186 0x7ff, /* dst_mask */
187 true), /* pcrel_offset */
189 HOWTO (IMAGE_REL_MCORE_RVA, /* type */
191 2, /* size (0 = byte, 1 = short, 2 = long) */
193 false, /* pc_relative */
195 complain_overflow_signed, /* complain_on_overflow */
196 NULL, /* special_function */
197 "MCORE_RVA", /* name */
198 true, /* partial_inplace */
199 0xffffffff, /* src_mask */
200 0xffffffff, /* dst_mask */
201 true) /* pcrel_offset */
204 /* Extend the coff_link_hash_table structure with a few M*Core specific fields.
205 This allows us to store global data here without actually creating any
206 global variables, which is a no-no in the BFD world. */
207 typedef struct coff_mcore_link_hash_table
209 /* The original coff_link_hash_table structure. MUST be first field. */
210 struct coff_link_hash_table root;
212 bfd * bfd_of_toc_owner;
213 long int global_toc_size;
214 long int import_table_size;
215 long int first_thunk_address;
220 /* Get the MCore coff linker hash table from a link_info structure. */
221 #define coff_mcore_hash_table(info) \
222 ((mcore_hash_table *) ((info)->hash))
224 /* Create an MCore coff linker hash table. */
225 static struct bfd_link_hash_table *
226 coff_mcore_link_hash_table_create (abfd)
229 mcore_hash_table * ret;
231 ret = ((mcore_hash_table *) bfd_alloc (abfd, sizeof (* ret)));
232 if (ret == (mcore_hash_table *) NULL)
235 if (! _bfd_coff_link_hash_table_init
236 (& ret->root, abfd, _bfd_coff_link_hash_newfunc))
238 bfd_release (abfd, ret);
239 return (struct bfd_link_hash_table *) NULL;
242 ret->bfd_of_toc_owner = NULL;
243 ret->global_toc_size = 0;
244 ret->import_table_size = 0;
245 ret->first_thunk_address = 0;
248 return & ret->root.root;
252 static bfd_reloc_status_type
253 mcore_coff_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
254 output_bfd, error_message)
256 arelent * reloc_entry;
257 asymbol * symbol ATTRIBUTE_UNUSED;
258 PTR data ATTRIBUTE_UNUSED;
259 asection * input_section ATTRIBUTE_UNUSED;
260 bfd * output_bfd ATTRIBUTE_UNUSED;
261 char ** error_message ATTRIBUTE_UNUSED;
263 BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
265 _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
266 bfd_get_filename (abfd),
267 reloc_entry->howto->name,
268 reloc_entry->howto->type);
270 return bfd_reloc_notsupported;
274 /* A cheesy little macro to make the code a little more readable. */
275 #define HOW2MAP(bfd_rtype, mcore_rtype) \
276 case bfd_rtype: return & mcore_coff_howto_table [mcore_rtype]
278 static reloc_howto_type *
279 mcore_coff_reloc_type_lookup (abfd, code)
280 bfd * abfd ATTRIBUTE_UNUSED;
281 bfd_reloc_code_real_type code;
285 HOW2MAP (BFD_RELOC_32, IMAGE_REL_MCORE_ADDR32);
286 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM8BY4, IMAGE_REL_MCORE_PCREL_IMM8BY4);
287 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM11BY2, IMAGE_REL_MCORE_PCREL_IMM11BY2);
288 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM4BY2, IMAGE_REL_MCORE_PCREL_IMM4BY2);
289 HOW2MAP (BFD_RELOC_32_PCREL, IMAGE_REL_MCORE_PCREL_32);
290 HOW2MAP (BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2);
291 HOW2MAP (BFD_RELOC_RVA, IMAGE_REL_MCORE_RVA);
300 #define RTYPE2HOWTO(cache_ptr, dst) \
301 (cache_ptr)->howto = mcore_coff_howto_table + (dst)->r_type;
303 static reloc_howto_type *
304 coff_mcore_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
305 bfd * abfd ATTRIBUTE_UNUSED;
307 struct internal_reloc * rel;
308 struct coff_link_hash_entry * h ATTRIBUTE_UNUSED;
309 struct internal_syment * sym;
312 reloc_howto_type * howto;
315 if (rel->r_type >= NUM_ELEM (mcore_coff_howto_table))
318 howto = mcore_coff_howto_table + rel->r_type;
320 if (rel->r_type == IMAGE_REL_MCORE_RVA)
321 * addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
323 if (howto->pc_relative)
325 * addendp = sec->vma - 2; /* XXX guess - is this right ? */
327 /* If the symbol is defined, then the generic code is going to
328 add back the symbol value in order to cancel out an
329 adjustment it made to the addend. However, we set the addend
330 to 0 at the start of this function. We need to adjust here,
331 to avoid the adjustment the generic code will make. FIXME:
332 This is getting a bit hackish. */
333 if (sym != NULL && sym->n_scnum != 0)
334 * addendp -= sym->n_value;
342 /* Return true if this relocation should appear in the output .reloc section.
343 This function is referenced in pe_mkobject in peicode.h. */
345 in_reloc_p (abfd, howto)
346 bfd * abfd ATTRIBUTE_UNUSED;
347 reloc_howto_type * howto;
349 return ! howto->pc_relative && howto->type != IMAGE_REL_MCORE_RVA;
353 /* The reloc processing routine for the optimized COFF linker. */
355 coff_mcore_relocate_section (output_bfd, info, input_bfd, input_section,
356 contents, relocs, syms, sections)
358 struct bfd_link_info * info;
360 asection * input_section;
362 struct internal_reloc * relocs;
363 struct internal_syment * syms;
364 asection ** sections;
366 struct internal_reloc * rel;
367 struct internal_reloc * relend;
371 /* If we are performing a relocateable link, we don't need to do a
372 thing. The caller will take care of adjusting the reloc
373 addresses and symbol indices. */
374 if (info->relocateable)
377 /* Check if we have the same endianess */
378 if ( input_bfd->xvec->byteorder != output_bfd->xvec->byteorder
379 && output_bfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
381 (*_bfd_error_handler)
382 (_("%s: compiled for a %s endian system and target is %s endian.\n"),
383 bfd_get_filename (input_bfd),
384 bfd_big_endian (input_bfd) ? "big" : "little",
385 bfd_big_endian (output_bfd) ? "big" : "little");
387 bfd_set_error (bfd_error_wrong_format);
395 relend = rel + input_section->reloc_count;
397 for (; rel < relend; rel++)
400 struct internal_syment * sym;
403 bfd_reloc_status_type rstat;
405 unsigned short r_type = rel->r_type;
406 reloc_howto_type * howto = NULL;
407 struct coff_link_hash_entry * h;
408 const char * my_name;
410 symndx = rel->r_symndx;
411 loc = contents + rel->r_vaddr - input_section->vma;
420 h = obj_coff_sym_hashes (input_bfd)[symndx];
424 /* Get the howto and initialise the addend. */
425 howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
438 asection * sec = sections[symndx];
441 + sec->output_section->vma
442 + sec->output_offset);
445 my_name = "*unknown*";
446 else if ( sym->_n._n_n._n_zeroes == 0
447 && sym->_n._n_n._n_offset != 0)
448 my_name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
451 static char buf [SYMNMLEN + 1];
453 strncpy (buf, sym->_n._n_name, SYMNMLEN);
454 buf[SYMNMLEN] = '\0';
461 if ( h->root.type == bfd_link_hash_defined
462 || h->root.type == bfd_link_hash_defweak)
464 asection * sec = h->root.u.def.section;
466 val = (h->root.u.def.value
467 + sec->output_section->vma
468 + sec->output_offset);
472 if (! ((*info->callbacks->undefined_symbol)
473 (info, h->root.root.string, input_bfd, input_section,
474 rel->r_vaddr - input_section->vma)))
478 my_name = h->root.root.string;
481 rstat = bfd_reloc_ok;
483 /* Each case must do its own relocation, setting rstat appropriately. */
487 _bfd_error_handler (_("%s: unsupported relocation type 0x%02x"),
488 bfd_get_filename (input_bfd), r_type);
489 bfd_set_error (bfd_error_bad_value);
492 case IMAGE_REL_MCORE_ABSOLUTE:
494 _("Warning: unsupported reloc %s <file %s, section %s>\n"),
496 bfd_get_filename (input_bfd),
497 input_section->name);
499 fprintf (stderr,"sym %ld (%s), r_vaddr %ld (%lx)\n",
500 rel->r_symndx, my_name, (long) rel->r_vaddr,
501 (unsigned long) rel->r_vaddr);
504 case IMAGE_REL_MCORE_PCREL_IMM8BY4:
505 case IMAGE_REL_MCORE_PCREL_IMM11BY2:
506 case IMAGE_REL_MCORE_PCREL_IMM4BY2:
507 case IMAGE_REL_MCORE_PCREL_32:
508 case IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2:
509 case IMAGE_REL_MCORE_ADDR32:
510 case IMAGE_REL_MCORE_RVA:
511 rstat = _bfd_relocate_contents (howto, input_bfd, val, loc);
523 case bfd_reloc_overflow:
524 if (! ((*info->callbacks->reloc_overflow)
525 (info, my_name, howto->name,
526 (bfd_vma) 0, input_bfd,
527 input_section, rel->r_vaddr - input_section->vma)))
536 /* Tailor coffcode.h -- macro heaven. */
538 /* We use the special COFF backend linker, with our own special touch. */
540 #define coff_bfd_reloc_type_lookup mcore_coff_reloc_type_lookup
541 #define coff_relocate_section coff_mcore_relocate_section
542 #define coff_rtype_to_howto coff_mcore_rtype_to_howto
544 #define SELECT_RELOC(internal, howto) {internal.r_type = howto->type;}
546 #define COFF_PAGE_SIZE 0x1000
548 #include "coffcode.h"
550 static const bfd_target *
554 #ifdef COFF_IMAGE_WITH_PE
555 /* We need to hack badly to handle a PE image correctly. In PE
556 images created by the GNU linker, the offset to the COFF header
557 is always the size. However, this is not the case in images
558 generated by other PE linkers. The PE format stores a four byte
559 offset to the PE signature just before the COFF header at
560 location 0x3c of the file. We pick up that offset, verify that
561 the PE signature is there, and then set ourselves up to read in
564 bfd_byte ext_offset[4];
566 bfd_byte ext_signature[4];
567 unsigned long signature;
569 if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0
570 || bfd_read (ext_offset, 1, 4, abfd) != 4)
572 if (bfd_get_error () != bfd_error_system_call)
573 bfd_set_error (bfd_error_wrong_format);
577 offset = bfd_h_get_32 (abfd, ext_offset);
579 if (bfd_seek (abfd, offset, SEEK_SET) != 0
580 || bfd_read (ext_signature, 1, 4, abfd) != 4)
582 if (bfd_get_error () != bfd_error_system_call)
583 bfd_set_error (bfd_error_wrong_format);
588 signature = bfd_h_get_32 (abfd, ext_signature);
590 if (signature != 0x4550)
592 bfd_set_error (bfd_error_wrong_format);
596 /* Here is the hack. coff_object_p wants to read filhsz bytes to
597 pick up the COFF header. We adjust so that that will work. 20
598 is the size of the mips COFF filehdr. */
599 if (bfd_seek (abfd, (bfd_tell (abfd) - bfd_coff_filhsz (abfd) + 20),
602 if (bfd_get_error () != bfd_error_system_call)
603 bfd_set_error (bfd_error_wrong_format);
610 return coff_object_p (abfd);
613 /* Forward declaration to initialise alterbative_target field. */
614 extern const bfd_target TARGET_LITTLE_SYM;
616 /* The transfer vectors that lead the outside world to all of the above. */
617 CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, (SEC_LINK_ONCE | SEC_LINK_DUPLICATES), 0, & TARGET_LITTLE_SYM)
618 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, (SEC_LINK_ONCE | SEC_LINK_DUPLICATES), 0, & TARGET_BIG_SYM)