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