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