1
/* BFD back-end for Motorola MCore COFF/PE
2
Copyright 1999, 2000, 2001, 2002 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
46
static bfd_reloc_status_type mcore_coff_unsupported_reloc
47
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
48
static boolean coff_mcore_relocate_section
49
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50
struct internal_reloc *, struct internal_syment *, asection **));
51
static reloc_howto_type * mcore_coff_reloc_type_lookup
52
PARAMS ((bfd *, bfd_reloc_code_real_type));
53
static reloc_howto_type * coff_mcore_rtype_to_howto
54
PARAMS ((bfd *, asection *, struct internal_reloc *,
55
struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
56
static void mcore_emit_base_file_entry
57
PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_vma));
58
static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
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 2
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)
73
static reloc_howto_type mcore_coff_howto_table[] =
76
HOWTO (IMAGE_REL_MCORE_ABSOLUTE,/* type */
78
0, /* size (0 = byte, 1 = short, 2 = long) */
80
false, /* pc_relative */
82
complain_overflow_dont, /* dont complain_on_overflow */
83
NULL, /* special_function */
84
"ABSOLUTE", /* name */
85
false, /* partial_inplace */
88
false), /* pcrel_offset */
90
HOWTO (IMAGE_REL_MCORE_ADDR32,/* type */
92
2, /* size (0 = byte, 1 = short, 2 = long) */
94
false, /* pc_relative */
96
complain_overflow_bitfield, /* complain_on_overflow */
97
NULL, /* special_function */
99
true, /* partial_inplace */
100
0xffffffff, /* src_mask */
101
0xffffffff, /* dst_mask */
102
false), /* pcrel_offset */
104
/* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions.
105
Should not appear in object files. */
106
HOWTO (IMAGE_REL_MCORE_PCREL_IMM8BY4, /* type */
108
1, /* size (0 = byte, 1 = short, 2 = long) */
110
true, /* pc_relative */
112
complain_overflow_bitfield, /* complain_on_overflow */
113
mcore_coff_unsupported_reloc, /* special_function */
114
"IMM8BY4", /* name */
115
false, /* partial_inplace */
118
true), /* pcrel_offset */
120
/* bsr/bt/bf/br instructions; 11 bits + 1 zero bit
121
Span 2k instructions == 4k bytes.
122
Only useful pieces at the relocated address are the opcode (5 bits) */
123
HOWTO (IMAGE_REL_MCORE_PCREL_IMM11BY2,/* type */
125
1, /* size (0 = byte, 1 = short, 2 = long) */
127
true, /* pc_relative */
129
complain_overflow_signed, /* complain_on_overflow */
130
NULL, /* special_function */
131
"IMM11BY2", /* name */
132
false, /* partial_inplace */
134
0x7ff, /* dst_mask */
135
true), /* pcrel_offset */
137
/* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported. */
138
HOWTO (IMAGE_REL_MCORE_PCREL_IMM4BY2, /* type */
140
1, /* size (0 = byte, 1 = short, 2 = long) */
142
true, /* pc_relative */
144
complain_overflow_bitfield, /* complain_on_overflow */
145
mcore_coff_unsupported_reloc, /* special_function */
146
"IMM4BY2", /* name */
147
false, /* partial_inplace */
150
true), /* pcrel_offset */
152
/* 32-bit pc-relative. Eventually this will help support PIC code. */
153
HOWTO (IMAGE_REL_MCORE_PCREL_32,/* type */
155
2, /* size (0 = byte, 1 = short, 2 = long) */
157
true, /* pc_relative */
159
complain_overflow_bitfield, /* complain_on_overflow */
160
NULL, /* special_function */
161
"PCREL_32", /* name */
162
false, /* partial_inplace */
164
0xffffffff, /* dst_mask */
165
true), /* pcrel_offset */
167
/* Like PCREL_IMM11BY2, this relocation indicates that there is a
168
'jsri' at the specified address. There is a separate relocation
169
entry for the literal pool entry that it references, but we
170
might be able to change the jsri to a bsr if the target turns out
171
to be close enough [even though we won't reclaim the literal pool
172
entry, we'll get some runtime efficiency back]. Note that this
173
is a relocation that we are allowed to safely ignore. */
174
HOWTO (IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2,/* type */
176
1, /* size (0 = byte, 1 = short, 2 = long) */
178
true, /* pc_relative */
180
complain_overflow_signed, /* complain_on_overflow */
181
NULL, /* special_function */
182
"JSR_IMM11BY2", /* name */
183
false, /* partial_inplace */
185
0x7ff, /* dst_mask */
186
true), /* pcrel_offset */
188
HOWTO (IMAGE_REL_MCORE_RVA, /* type */
190
2, /* size (0 = byte, 1 = short, 2 = long) */
192
false, /* pc_relative */
194
complain_overflow_signed, /* complain_on_overflow */
195
NULL, /* special_function */
196
"MCORE_RVA", /* name */
197
true, /* partial_inplace */
198
0xffffffff, /* src_mask */
199
0xffffffff, /* dst_mask */
200
true) /* pcrel_offset */
203
/* Extend the coff_link_hash_table structure with a few M*Core specific fields.
204
This allows us to store global data here without actually creating any
205
global variables, which is a no-no in the BFD world. */
206
typedef struct coff_mcore_link_hash_table
208
/* The original coff_link_hash_table structure. MUST be first field. */
209
struct coff_link_hash_table root;
211
bfd * bfd_of_toc_owner;
212
long int global_toc_size;
213
long int import_table_size;
214
long int first_thunk_address;
219
/* Get the MCore coff linker hash table from a link_info structure. */
220
#define coff_mcore_hash_table(info) \
221
((mcore_hash_table *) ((info)->hash))
224
/* Create an MCore coff linker hash table. */
226
static struct bfd_link_hash_table *
227
coff_mcore_link_hash_table_create (abfd)
230
mcore_hash_table * ret;
232
ret = (mcore_hash_table *) bfd_malloc ((bfd_size_type) sizeof (* ret));
233
if (ret == (mcore_hash_table *) NULL)
236
if (! _bfd_coff_link_hash_table_init
237
(& ret->root, abfd, _bfd_coff_link_hash_newfunc))
240
return (struct bfd_link_hash_table *) NULL;
243
ret->bfd_of_toc_owner = NULL;
244
ret->global_toc_size = 0;
245
ret->import_table_size = 0;
246
ret->first_thunk_address = 0;
249
return & ret->root.root;
253
/* Add an entry to the base file. */
256
mcore_emit_base_file_entry (info, output_bfd, input_section, reloc_offset)
257
struct bfd_link_info * info;
259
asection * input_section;
260
bfd_vma reloc_offset;
262
bfd_vma addr = reloc_offset
264
+ input_section->output_offset
265
+ input_section->output_section->vma;
267
if (coff_data (output_bfd)->pe)
268
addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
270
fwrite (&addr, 1, sizeof (addr), (FILE *) info->base_file);
273
static bfd_reloc_status_type
274
mcore_coff_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
275
output_bfd, error_message)
277
arelent * reloc_entry;
278
asymbol * symbol ATTRIBUTE_UNUSED;
279
PTR data ATTRIBUTE_UNUSED;
280
asection * input_section ATTRIBUTE_UNUSED;
281
bfd * output_bfd ATTRIBUTE_UNUSED;
282
char ** error_message ATTRIBUTE_UNUSED;
284
BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
286
_bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
287
bfd_archive_filename (abfd),
288
reloc_entry->howto->name,
289
reloc_entry->howto->type);
291
return bfd_reloc_notsupported;
294
/* A cheesy little macro to make the code a little more readable. */
295
#define HOW2MAP(bfd_rtype, mcore_rtype) \
296
case bfd_rtype: return & mcore_coff_howto_table [mcore_rtype]
298
static reloc_howto_type *
299
mcore_coff_reloc_type_lookup (abfd, code)
300
bfd * abfd ATTRIBUTE_UNUSED;
301
bfd_reloc_code_real_type code;
305
HOW2MAP (BFD_RELOC_32, IMAGE_REL_MCORE_ADDR32);
306
HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM8BY4, IMAGE_REL_MCORE_PCREL_IMM8BY4);
307
HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM11BY2, IMAGE_REL_MCORE_PCREL_IMM11BY2);
308
HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM4BY2, IMAGE_REL_MCORE_PCREL_IMM4BY2);
309
HOW2MAP (BFD_RELOC_32_PCREL, IMAGE_REL_MCORE_PCREL_32);
310
HOW2MAP (BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2);
311
HOW2MAP (BFD_RELOC_RVA, IMAGE_REL_MCORE_RVA);
320
#define RTYPE2HOWTO(cache_ptr, dst) \
321
(cache_ptr)->howto = mcore_coff_howto_table + (dst)->r_type;
323
static reloc_howto_type *
324
coff_mcore_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
325
bfd * abfd ATTRIBUTE_UNUSED;
327
struct internal_reloc * rel;
328
struct coff_link_hash_entry * h ATTRIBUTE_UNUSED;
329
struct internal_syment * sym;
332
reloc_howto_type * howto;
334
if (rel->r_type >= NUM_ELEM (mcore_coff_howto_table))
337
howto = mcore_coff_howto_table + rel->r_type;
339
if (rel->r_type == IMAGE_REL_MCORE_RVA)
340
* addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
342
else if (howto->pc_relative)
344
* addendp = sec->vma - 2; /* XXX guess - is this right ? */
346
/* If the symbol is defined, then the generic code is going to
347
add back the symbol value in order to cancel out an
348
adjustment it made to the addend. However, we set the addend
349
to 0 at the start of this function. We need to adjust here,
350
to avoid the adjustment the generic code will make. FIXME:
351
This is getting a bit hackish. */
352
if (sym != NULL && sym->n_scnum != 0)
353
* addendp -= sym->n_value;
361
/* Return true if this relocation should appear in the output .reloc section.
362
This function is referenced in pe_mkobject in peicode.h. */
365
in_reloc_p (abfd, howto)
366
bfd * abfd ATTRIBUTE_UNUSED;
367
reloc_howto_type * howto;
369
return ! howto->pc_relative && howto->type != IMAGE_REL_MCORE_RVA;
372
/* The reloc processing routine for the optimized COFF linker. */
374
coff_mcore_relocate_section (output_bfd, info, input_bfd, input_section,
375
contents, relocs, syms, sections)
377
struct bfd_link_info * info;
379
asection * input_section;
381
struct internal_reloc * relocs;
382
struct internal_syment * syms;
383
asection ** sections;
385
struct internal_reloc * rel;
386
struct internal_reloc * relend;
390
/* If we are performing a relocateable link, we don't need to do a
391
thing. The caller will take care of adjusting the reloc
392
addresses and symbol indices. */
393
if (info->relocateable)
396
/* Check if we have the same endianess */
397
if ( input_bfd->xvec->byteorder != output_bfd->xvec->byteorder
398
&& output_bfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
400
(*_bfd_error_handler)
401
(_("%s: compiled for a %s system and target is %s.\n"),
402
bfd_archive_filename (input_bfd),
403
bfd_big_endian (input_bfd) ? _("big endian") : _("little endian"),
404
bfd_big_endian (output_bfd) ? _("big endian") : _("little endian"));
406
bfd_set_error (bfd_error_wrong_format);
414
relend = rel + input_section->reloc_count;
416
for (; rel < relend; rel++)
419
struct internal_syment * sym;
422
bfd_reloc_status_type rstat;
424
unsigned short r_type = rel->r_type;
425
reloc_howto_type * howto = NULL;
426
struct coff_link_hash_entry * h;
427
const char * my_name;
429
symndx = rel->r_symndx;
430
loc = contents + rel->r_vaddr - input_section->vma;
439
h = obj_coff_sym_hashes (input_bfd)[symndx];
445
/* Get the howto and initialise the addend. */
446
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
459
asection * sec = sections[symndx];
462
+ sec->output_section->vma
463
+ sec->output_offset);
466
my_name = "*unknown*";
467
else if ( sym->_n._n_n._n_zeroes == 0
468
&& sym->_n._n_n._n_offset != 0)
469
my_name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
472
static char buf [SYMNMLEN + 1];
474
strncpy (buf, sym->_n._n_name, SYMNMLEN);
475
buf[SYMNMLEN] = '\0';
482
if ( h->root.type == bfd_link_hash_defined
483
|| h->root.type == bfd_link_hash_defweak)
485
asection * sec = h->root.u.def.section;
487
val = (h->root.u.def.value
488
+ sec->output_section->vma
489
+ sec->output_offset);
493
if (! ((*info->callbacks->undefined_symbol)
494
(info, h->root.root.string, input_bfd, input_section,
495
rel->r_vaddr - input_section->vma, true)))
499
my_name = h->root.root.string;
502
rstat = bfd_reloc_ok;
504
/* Each case must do its own relocation, setting rstat appropriately. */
508
_bfd_error_handler (_("%s: unsupported relocation type 0x%02x"),
509
bfd_archive_filename (input_bfd), r_type);
510
bfd_set_error (bfd_error_bad_value);
513
case IMAGE_REL_MCORE_ABSOLUTE:
515
_("Warning: unsupported reloc %s <file %s, section %s>\n"),
517
bfd_archive_filename (input_bfd),
518
input_section->name);
520
fprintf (stderr,"sym %ld (%s), r_vaddr %ld (%lx)\n",
521
rel->r_symndx, my_name, (long) rel->r_vaddr,
522
(unsigned long) rel->r_vaddr);
525
case IMAGE_REL_MCORE_PCREL_IMM8BY4:
526
case IMAGE_REL_MCORE_PCREL_IMM11BY2:
527
case IMAGE_REL_MCORE_PCREL_IMM4BY2:
528
case IMAGE_REL_MCORE_PCREL_32:
529
case IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2:
530
case IMAGE_REL_MCORE_ADDR32:
531
/* XXX fixme - shouldn't this be like the code for the RVA reloc ? */
532
rstat = _bfd_relocate_contents (howto, input_bfd, val, loc);
535
case IMAGE_REL_MCORE_RVA:
536
rstat = _bfd_final_link_relocate
538
input_section, contents, rel->r_vaddr - input_section->vma,
545
/* Emit a reloc if the backend thinks it needs it. */
546
if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
547
mcore_emit_base_file_entry (info, output_bfd, input_section, rel->r_vaddr);
558
case bfd_reloc_overflow:
559
if (! ((*info->callbacks->reloc_overflow)
560
(info, my_name, howto->name,
561
(bfd_vma) 0, input_bfd,
562
input_section, rel->r_vaddr - input_section->vma)))
570
/* Tailor coffcode.h -- macro heaven. */
572
/* We use the special COFF backend linker, with our own special touch. */
574
#define coff_bfd_reloc_type_lookup mcore_coff_reloc_type_lookup
575
#define coff_relocate_section coff_mcore_relocate_section
576
#define coff_rtype_to_howto coff_mcore_rtype_to_howto
578
#define SELECT_RELOC(internal, howto) {internal.r_type = howto->type;}
580
#define COFF_PAGE_SIZE 0x1000
582
#include "coffcode.h"
584
/* Forward declaration to initialise alterbative_target field. */
585
extern const bfd_target TARGET_LITTLE_SYM;
587
/* The transfer vectors that lead the outside world to all of the above. */
588
CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED,
589
(SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
590
0, & TARGET_LITTLE_SYM)
591
CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED,
592
(SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),