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