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

Last change on this file since 1973 was 1973, checked in by Silvan Scherrer, 8 years ago

binutils: update trunk to version 2.27

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