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