source: trunk/binutils/bfd/coff-mcore.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 18.9 KB
Line 
1/* BFD back-end for Motorola MCore COFF/PE
2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24#include "coff/mcore.h"
25#include "coff/internal.h"
26#include "coff/pe.h"
27#include "libcoff.h"
28
29#ifdef BADMAG
30#undef BADMAG
31#endif
32#define BADMAG(x) MCOREBADMAG(x)
33
34#ifndef NUM_ELEM
35#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
36#endif
37
38/* This file is compiled more than once, but we only compile the
39 final_link routine once. */
40extern bfd_boolean mcore_bfd_coff_final_link
41 PARAMS ((bfd *, struct bfd_link_info *));
42#if 0
43static struct bfd_link_hash_table *coff_mcore_link_hash_table_create
44 PARAMS ((bfd *));
45#endif
46static bfd_reloc_status_type mcore_coff_unsupported_reloc
47 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
48static bfd_boolean coff_mcore_relocate_section
49 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50 struct internal_reloc *, struct internal_syment *, asection **));
51static reloc_howto_type *mcore_coff_reloc_type_lookup
52 PARAMS ((bfd *, bfd_reloc_code_real_type));
53static reloc_howto_type *coff_mcore_rtype_to_howto
54 PARAMS ((bfd *, asection *, struct internal_reloc *,
55 struct coff_link_hash_entry *, struct internal_syment *,
56 bfd_vma *));
57static void mcore_emit_base_file_entry
58 PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_vma));
59static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
60
61
62/* The NT loader points the toc register to &toc + 32768, in order to
63 use the complete range of a 16-bit displacement. We have to adjust
64 for this when we fix up loads displaced off the toc reg. */
65#define TOC_LOAD_ADJUSTMENT (-32768)
66#define TOC_SECTION_NAME ".private.toc"
67
68/* The main body of code is in coffcode.h. */
69#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
70
71/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
72 from smaller values. Start with zero, widen, *then* decrement. */
73#define MINUS_ONE (((bfd_vma)0) - 1)
74
75
76static reloc_howto_type mcore_coff_howto_table[] =
77{
78 /* Unused: */
79 HOWTO (IMAGE_REL_MCORE_ABSOLUTE,/* type */
80 0, /* rightshift */
81 0, /* size (0 = byte, 1 = short, 2 = long) */
82 0, /* bitsize */
83 FALSE, /* pc_relative */
84 0, /* bitpos */
85 complain_overflow_dont, /* dont complain_on_overflow */
86 NULL, /* special_function */
87 "ABSOLUTE", /* name */
88 FALSE, /* partial_inplace */
89 0x00, /* src_mask */
90 0x00, /* dst_mask */
91 FALSE), /* pcrel_offset */
92
93 HOWTO (IMAGE_REL_MCORE_ADDR32,/* type */
94 0, /* rightshift */
95 2, /* size (0 = byte, 1 = short, 2 = long) */
96 32, /* bitsize */
97 FALSE, /* pc_relative */
98 0, /* bitpos */
99 complain_overflow_bitfield, /* complain_on_overflow */
100 NULL, /* special_function */
101 "ADDR32", /* name */
102 TRUE, /* partial_inplace */
103 0xffffffff, /* src_mask */
104 0xffffffff, /* dst_mask */
105 FALSE), /* pcrel_offset */
106
107 /* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions.
108 Should not appear in object files. */
109 HOWTO (IMAGE_REL_MCORE_PCREL_IMM8BY4, /* type */
110 2, /* rightshift */
111 1, /* size (0 = byte, 1 = short, 2 = long) */
112 8, /* bitsize */
113 TRUE, /* pc_relative */
114 0, /* bitpos */
115 complain_overflow_bitfield, /* complain_on_overflow */
116 mcore_coff_unsupported_reloc, /* special_function */
117 "IMM8BY4", /* name */
118 FALSE, /* partial_inplace */
119 0, /* src_mask */
120 0, /* dst_mask */
121 TRUE), /* pcrel_offset */
122
123 /* bsr/bt/bf/br instructions; 11 bits + 1 zero bit
124 Span 2k instructions == 4k bytes.
125 Only useful pieces at the relocated address are the opcode (5 bits) */
126 HOWTO (IMAGE_REL_MCORE_PCREL_IMM11BY2,/* type */
127 1, /* rightshift */
128 1, /* size (0 = byte, 1 = short, 2 = long) */
129 11, /* bitsize */
130 TRUE, /* pc_relative */
131 0, /* bitpos */
132 complain_overflow_signed, /* complain_on_overflow */
133 NULL, /* special_function */
134 "IMM11BY2", /* name */
135 FALSE, /* partial_inplace */
136 0x0, /* src_mask */
137 0x7ff, /* dst_mask */
138 TRUE), /* pcrel_offset */
139
140 /* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported. */
141 HOWTO (IMAGE_REL_MCORE_PCREL_IMM4BY2, /* type */
142 1, /* rightshift */
143 1, /* size (0 = byte, 1 = short, 2 = long) */
144 4, /* bitsize */
145 TRUE, /* pc_relative */
146 0, /* bitpos */
147 complain_overflow_bitfield, /* complain_on_overflow */
148 mcore_coff_unsupported_reloc, /* special_function */
149 "IMM4BY2", /* name */
150 FALSE, /* partial_inplace */
151 0, /* src_mask */
152 0, /* dst_mask */
153 TRUE), /* pcrel_offset */
154
155 /* 32-bit pc-relative. Eventually this will help support PIC code. */
156 HOWTO (IMAGE_REL_MCORE_PCREL_32,/* type */
157 0, /* rightshift */
158 2, /* size (0 = byte, 1 = short, 2 = long) */
159 32, /* bitsize */
160 TRUE, /* pc_relative */
161 0, /* bitpos */
162 complain_overflow_bitfield, /* complain_on_overflow */
163 NULL, /* special_function */
164 "PCREL_32", /* name */
165 FALSE, /* partial_inplace */
166 0x0, /* src_mask */
167 0xffffffff, /* dst_mask */
168 TRUE), /* pcrel_offset */
169
170 /* Like PCREL_IMM11BY2, this relocation indicates that there is a
171 'jsri' at the specified address. There is a separate relocation
172 entry for the literal pool entry that it references, but we
173 might be able to change the jsri to a bsr if the target turns out
174 to be close enough [even though we won't reclaim the literal pool
175 entry, we'll get some runtime efficiency back]. Note that this
176 is a relocation that we are allowed to safely ignore. */
177 HOWTO (IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2,/* type */
178 1, /* rightshift */
179 1, /* size (0 = byte, 1 = short, 2 = long) */
180 11, /* bitsize */
181 TRUE, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_signed, /* complain_on_overflow */
184 NULL, /* special_function */
185 "JSR_IMM11BY2", /* name */
186 FALSE, /* partial_inplace */
187 0x0, /* src_mask */
188 0x7ff, /* dst_mask */
189 TRUE), /* pcrel_offset */
190
191 HOWTO (IMAGE_REL_MCORE_RVA, /* type */
192 0, /* rightshift */
193 2, /* size (0 = byte, 1 = short, 2 = long) */
194 32, /* bitsize */
195 FALSE, /* pc_relative */
196 0, /* bitpos */
197 complain_overflow_signed, /* complain_on_overflow */
198 NULL, /* special_function */
199 "MCORE_RVA", /* name */
200 TRUE, /* partial_inplace */
201 0xffffffff, /* src_mask */
202 0xffffffff, /* dst_mask */
203 TRUE) /* pcrel_offset */
204};
205
206
207/* Extend the coff_link_hash_table structure with a few M*Core specific fields.
208 This allows us to store global data here without actually creating any
209 global variables, which is a no-no in the BFD world. */
210typedef struct coff_mcore_link_hash_table
211{
212 /* The original coff_link_hash_table structure. MUST be first field. */
213 struct coff_link_hash_table root;
214
215 bfd * bfd_of_toc_owner;
216 long int global_toc_size;
217 long int import_table_size;
218 long int first_thunk_address;
219 long int thunk_size;
220}
221mcore_hash_table;
222
223/* Get the MCore coff linker hash table from a link_info structure. */
224#define coff_mcore_hash_table(info) \
225 ((mcore_hash_table *) ((info)->hash))
226
227#if 0
228/* Create an MCore coff linker hash table. */
229
230static struct bfd_link_hash_table *
231coff_mcore_link_hash_table_create (abfd)
232 bfd * abfd;
233{
234 mcore_hash_table * ret;
235
236 ret = (mcore_hash_table *) bfd_malloc ((bfd_size_type) sizeof (* ret));
237 if (ret == (mcore_hash_table *) NULL)
238 return NULL;
239
240 if (! _bfd_coff_link_hash_table_init
241 (& ret->root, abfd, _bfd_coff_link_hash_newfunc))
242 {
243 free (ret);
244 return (struct bfd_link_hash_table *) NULL;
245 }
246
247 ret->bfd_of_toc_owner = NULL;
248 ret->global_toc_size = 0;
249 ret->import_table_size = 0;
250 ret->first_thunk_address = 0;
251 ret->thunk_size = 0;
252
253 return & ret->root.root;
254}
255#endif
256
257
258/* Add an entry to the base file. */
259
260static void
261mcore_emit_base_file_entry (info, output_bfd, input_section, reloc_offset)
262 struct bfd_link_info * info;
263 bfd * output_bfd;
264 asection * input_section;
265 bfd_vma reloc_offset;
266{
267 bfd_vma addr = reloc_offset
268 - input_section->vma
269 + input_section->output_offset
270 + input_section->output_section->vma;
271
272 if (coff_data (output_bfd)->pe)
273 addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
274
275 fwrite (&addr, 1, sizeof (addr), (FILE *) info->base_file);
276}
277
278
279static bfd_reloc_status_type
280mcore_coff_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
281 output_bfd, error_message)
282 bfd * abfd;
283 arelent * reloc_entry;
284 asymbol * symbol ATTRIBUTE_UNUSED;
285 PTR data ATTRIBUTE_UNUSED;
286 asection * input_section ATTRIBUTE_UNUSED;
287 bfd * output_bfd ATTRIBUTE_UNUSED;
288 char ** error_message ATTRIBUTE_UNUSED;
289{
290 BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
291
292 _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
293 bfd_archive_filename (abfd),
294 reloc_entry->howto->name,
295 reloc_entry->howto->type);
296
297 return bfd_reloc_notsupported;
298}
299
300
301/* A cheesy little macro to make the code a little more readable. */
302#define HOW2MAP(bfd_rtype, mcore_rtype) \
303 case bfd_rtype: return & mcore_coff_howto_table [mcore_rtype]
304
305static reloc_howto_type *
306mcore_coff_reloc_type_lookup (abfd, code)
307 bfd * abfd ATTRIBUTE_UNUSED;
308 bfd_reloc_code_real_type code;
309{
310 switch (code)
311 {
312 HOW2MAP (BFD_RELOC_32, IMAGE_REL_MCORE_ADDR32);
313 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM8BY4, IMAGE_REL_MCORE_PCREL_IMM8BY4);
314 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM11BY2, IMAGE_REL_MCORE_PCREL_IMM11BY2);
315 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM4BY2, IMAGE_REL_MCORE_PCREL_IMM4BY2);
316 HOW2MAP (BFD_RELOC_32_PCREL, IMAGE_REL_MCORE_PCREL_32);
317 HOW2MAP (BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2);
318 HOW2MAP (BFD_RELOC_RVA, IMAGE_REL_MCORE_RVA);
319 default:
320 return NULL;
321 }
322 /*NOTREACHED*/
323}
324
325#undef HOW2MAP
326
327#define RTYPE2HOWTO(cache_ptr, dst) \
328 (cache_ptr)->howto = mcore_coff_howto_table + (dst)->r_type;
329
330static reloc_howto_type *
331coff_mcore_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
332 bfd * abfd ATTRIBUTE_UNUSED;
333 asection * sec;
334 struct internal_reloc * rel;
335 struct coff_link_hash_entry * h ATTRIBUTE_UNUSED;
336 struct internal_syment * sym;
337 bfd_vma * addendp;
338{
339 reloc_howto_type * howto;
340
341 if (rel->r_type >= NUM_ELEM (mcore_coff_howto_table))
342 return NULL;
343
344 howto = mcore_coff_howto_table + rel->r_type;
345
346 if (rel->r_type == IMAGE_REL_MCORE_RVA)
347 * addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
348
349 else if (howto->pc_relative)
350 {
351 * addendp = sec->vma - 2; /* XXX guess - is this right ? */
352
353 /* If the symbol is defined, then the generic code is going to
354 add back the symbol value in order to cancel out an
355 adjustment it made to the addend. However, we set the addend
356 to 0 at the start of this function. We need to adjust here,
357 to avoid the adjustment the generic code will make. FIXME:
358 This is getting a bit hackish. */
359 if (sym != NULL && sym->n_scnum != 0)
360 * addendp -= sym->n_value;
361 }
362 else
363 * addendp = 0;
364
365 return howto;
366}
367
368/* Return TRUE if this relocation should appear in the output .reloc section.
369 This function is referenced in pe_mkobject in peicode.h. */
370
371static bfd_boolean
372in_reloc_p (abfd, howto)
373 bfd * abfd ATTRIBUTE_UNUSED;
374 reloc_howto_type * howto;
375{
376 return ! howto->pc_relative && howto->type != IMAGE_REL_MCORE_RVA;
377}
378
379
380/* The reloc processing routine for the optimized COFF linker. */
381static bfd_boolean
382coff_mcore_relocate_section (output_bfd, info, input_bfd, input_section,
383 contents, relocs, syms, sections)
384 bfd * output_bfd;
385 struct bfd_link_info * info;
386 bfd * input_bfd;
387 asection * input_section;
388 bfd_byte * contents;
389 struct internal_reloc * relocs;
390 struct internal_syment * syms;
391 asection ** sections;
392{
393 struct internal_reloc * rel;
394 struct internal_reloc * relend;
395 bfd_boolean hihalf;
396 bfd_vma hihalf_val;
397
398 /* If we are performing a relocateable link, we don't need to do a
399 thing. The caller will take care of adjusting the reloc
400 addresses and symbol indices. */
401 if (info->relocateable)
402 return TRUE;
403
404 /* Check if we have the same endianess */
405 if ( input_bfd->xvec->byteorder != output_bfd->xvec->byteorder
406 && output_bfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
407 {
408 (*_bfd_error_handler)
409 (_("%s: compiled for a %s system and target is %s.\n"),
410 bfd_archive_filename (input_bfd),
411 bfd_big_endian (input_bfd) ? _("big endian") : _("little endian"),
412 bfd_big_endian (output_bfd) ? _("big endian") : _("little endian"));
413
414 bfd_set_error (bfd_error_wrong_format);
415 return FALSE;
416 }
417
418 hihalf = FALSE;
419 hihalf_val = 0;
420
421 rel = relocs;
422 relend = rel + input_section->reloc_count;
423
424 for (; rel < relend; rel++)
425 {
426 long symndx;
427 struct internal_syment * sym;
428 bfd_vma val;
429 bfd_vma addend;
430 bfd_reloc_status_type rstat;
431 bfd_byte * loc;
432 unsigned short r_type = rel->r_type;
433 reloc_howto_type * howto = NULL;
434 struct coff_link_hash_entry * h;
435 const char * my_name;
436
437 symndx = rel->r_symndx;
438 loc = contents + rel->r_vaddr - input_section->vma;
439
440 if (symndx == -1)
441 {
442 h = NULL;
443 sym = NULL;
444 }
445 else
446 {
447 h = obj_coff_sym_hashes (input_bfd)[symndx];
448 sym = syms + symndx;
449 }
450
451 addend = 0;
452
453 /* Get the howto and initialise the addend. */
454 howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
455 sym, & addend);
456 if (howto == NULL)
457 return FALSE;
458
459 val = 0;
460
461 if (h == NULL)
462 {
463 if (symndx == -1)
464 my_name = "*ABS*";
465 else
466 {
467 asection * sec = sections[symndx];
468
469 val = (sym->n_value
470 + sec->output_section->vma
471 + sec->output_offset);
472
473 if (sym == NULL)
474 my_name = "*unknown*";
475 else if ( sym->_n._n_n._n_zeroes == 0
476 && sym->_n._n_n._n_offset != 0)
477 my_name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
478 else
479 {
480 static char buf [SYMNMLEN + 1];
481
482 strncpy (buf, sym->_n._n_name, SYMNMLEN);
483 buf[SYMNMLEN] = '\0';
484 my_name = buf;
485 }
486 }
487 }
488 else
489 {
490 if ( h->root.type == bfd_link_hash_defined
491 || h->root.type == bfd_link_hash_defweak)
492 {
493 asection * sec = h->root.u.def.section;
494
495 val = (h->root.u.def.value
496 + sec->output_section->vma
497 + sec->output_offset);
498 }
499 else
500 {
501 if (! ((*info->callbacks->undefined_symbol)
502 (info, h->root.root.string, input_bfd, input_section,
503 rel->r_vaddr - input_section->vma, TRUE)))
504 return FALSE;
505 }
506
507 my_name = h->root.root.string;
508 }
509
510 rstat = bfd_reloc_ok;
511
512 /* Each case must do its own relocation, setting rstat appropriately. */
513 switch (r_type)
514 {
515 default:
516 _bfd_error_handler (_("%s: unsupported relocation type 0x%02x"),
517 bfd_archive_filename (input_bfd), r_type);
518 bfd_set_error (bfd_error_bad_value);
519 return FALSE;
520
521 case IMAGE_REL_MCORE_ABSOLUTE:
522 fprintf (stderr,
523 _("Warning: unsupported reloc %s <file %s, section %s>\n"),
524 howto->name,
525 bfd_archive_filename (input_bfd),
526 input_section->name);
527
528 fprintf (stderr,"sym %ld (%s), r_vaddr %ld (%lx)\n",
529 rel->r_symndx, my_name, (long) rel->r_vaddr,
530 (unsigned long) rel->r_vaddr);
531 break;
532
533 case IMAGE_REL_MCORE_PCREL_IMM8BY4:
534 case IMAGE_REL_MCORE_PCREL_IMM11BY2:
535 case IMAGE_REL_MCORE_PCREL_IMM4BY2:
536 case IMAGE_REL_MCORE_PCREL_32:
537 case IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2:
538 case IMAGE_REL_MCORE_ADDR32:
539 /* XXX fixme - shouldn't this be like the code for the RVA reloc ? */
540 rstat = _bfd_relocate_contents (howto, input_bfd, val, loc);
541 break;
542
543 case IMAGE_REL_MCORE_RVA:
544 rstat = _bfd_final_link_relocate
545 (howto, input_bfd,
546 input_section, contents, rel->r_vaddr - input_section->vma,
547 val, addend);
548 break;
549 }
550
551 if (info->base_file)
552 {
553 /* Emit a reloc if the backend thinks it needs it. */
554 if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
555 mcore_emit_base_file_entry (info, output_bfd, input_section, rel->r_vaddr);
556 }
557
558 switch (rstat)
559 {
560 default:
561 abort ();
562
563 case bfd_reloc_ok:
564 break;
565
566 case bfd_reloc_overflow:
567 if (! ((*info->callbacks->reloc_overflow)
568 (info, my_name, howto->name,
569 (bfd_vma) 0, input_bfd,
570 input_section, rel->r_vaddr - input_section->vma)))
571 return FALSE;
572 }
573 }
574
575 return TRUE;
576}
577
578
579/* Tailor coffcode.h -- macro heaven. */
580
581/* We use the special COFF backend linker, with our own special touch. */
582
583#define coff_bfd_reloc_type_lookup mcore_coff_reloc_type_lookup
584#define coff_relocate_section coff_mcore_relocate_section
585#define coff_rtype_to_howto coff_mcore_rtype_to_howto
586
587#define SELECT_RELOC(internal, howto) {internal.r_type = howto->type;}
588
589/* Make sure that the 'r_offset' field is copied properly
590 so that identical binaries will compare the same. */
591#define SWAP_IN_RELOC_OFFSET H_GET_32
592#define SWAP_OUT_RELOC_OFFSET H_PUT_32
593
594#define COFF_PAGE_SIZE 0x1000
595
596#include "coffcode.h"
597
598
599/* Forward declaration to initialise alterbative_target field. */
600extern const bfd_target TARGET_LITTLE_SYM;
601
602/* The transfer vectors that lead the outside world to all of the above. */
603CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED,
604 (SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
605 0, & TARGET_LITTLE_SYM)
606CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED,
607 (SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
608 0, & TARGET_BIG_SYM)
Note: See TracBrowser for help on using the repository browser.