Add missing prototypes
[platform/upstream/binutils.git] / bfd / pe-mips.c
1 /* BFD back-end for MIPS PE COFF files.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001 Free Software Foundation, Inc.
4    Modified from coff-i386.c by DJ Delorie, dj@cygnus.com
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #define COFF_WITH_PE
23 #define COFF_LONG_SECTION_NAMES
24 #define PCRELOFFSET true
25
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "libbfd.h"
29
30 #include "coff/mipspe.h"
31
32 #include "coff/internal.h"
33
34 #include "coff/pe.h"
35
36 #include "libcoff.h"
37
38 static bfd_reloc_status_type coff_mips_reloc
39   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
40 static reloc_howto_type *coff_mips_rtype_to_howto
41   PARAMS ((bfd *, asection *, struct internal_reloc *,
42            struct coff_link_hash_entry *, struct internal_syment *,
43
44            bfd_vma *));
45 #if 0
46 static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
47                                               struct internal_reloc *));
48 static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
49                                                const struct internal_reloc *,
50                                                PTR));
51 static void mips_adjust_reloc_in PARAMS ((bfd *,
52                                           const struct internal_reloc *,
53                                           arelent *));
54 static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
55                                            struct internal_reloc *));
56 #endif
57
58 static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
59 static reloc_howto_type * coff_mips_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
60 static void mips_swap_reloc_in PARAMS ((bfd *, PTR, PTR));
61 static unsigned int mips_swap_reloc_out PARAMS ((bfd *, PTR, PTR));
62 static boolean coff_pe_mips_relocate_section
63   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
64            struct internal_reloc *, struct internal_syment *, asection **));
65
66 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
67 /* The page size is a guess based on ELF.  */
68
69 #define COFF_PAGE_SIZE 0x1000
70
71 /* For some reason when using mips COFF the value stored in the .text
72    section for a reference to a common symbol is the value itself plus
73    any desired offset.  Ian Taylor, Cygnus Support.  */
74
75 /* If we are producing relocateable output, we need to do some
76    adjustments to the object file that are not done by the
77    bfd_perform_relocation function.  This function is called by every
78    reloc type to make any required adjustments.  */
79
80 static bfd_reloc_status_type
81 coff_mips_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
82                  error_message)
83      bfd *abfd;
84      arelent *reloc_entry;
85      asymbol *symbol;
86      PTR data;
87      asection *input_section ATTRIBUTE_UNUSED;
88      bfd *output_bfd;
89      char **error_message ATTRIBUTE_UNUSED;
90 {
91   symvalue diff;
92
93   if (output_bfd == (bfd *) NULL)
94     return bfd_reloc_continue;
95
96   if (bfd_is_com_section (symbol->section))
97     {
98 #ifndef COFF_WITH_PE
99       /* We are relocating a common symbol.  The current value in the
100          object file is ORIG + OFFSET, where ORIG is the value of the
101          common symbol as seen by the object file when it was compiled
102          (this may be zero if the symbol was undefined) and OFFSET is
103          the offset into the common symbol (normally zero, but may be
104          non-zero when referring to a field in a common structure).
105          ORIG is the negative of reloc_entry->addend, which is set by
106          the CALC_ADDEND macro below.  We want to replace the value in
107          the object file with NEW + OFFSET, where NEW is the value of
108          the common symbol which we are going to put in the final
109          object file.  NEW is symbol->value.  */
110       diff = symbol->value + reloc_entry->addend;
111 #else
112       /* In PE mode, we do not offset the common symbol.  */
113       diff = reloc_entry->addend;
114 #endif
115     }
116   else
117     {
118       /* For some reason bfd_perform_relocation always effectively
119          ignores the addend for a COFF target when producing
120          relocateable output.  This seems to be always wrong for 386
121          COFF, so we handle the addend here instead.  */
122       diff = reloc_entry->addend;
123     }
124
125 #ifdef COFF_WITH_PE
126 #if 0
127   /* dj - handle it like any other reloc? */
128   /* FIXME: How should this case be handled?  */
129   if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0)
130     abort ();
131 #endif
132 #endif
133
134 #define DOIT(x) \
135   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask))
136
137     if (diff != 0)
138       {
139         reloc_howto_type *howto = reloc_entry->howto;
140         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
141
142         switch (howto->size)
143           {
144           case 0:
145             {
146               char x = bfd_get_8 (abfd, addr);
147               DOIT (x);
148               bfd_put_8 (abfd, x, addr);
149             }
150             break;
151
152           case 1:
153             {
154               short x = bfd_get_16 (abfd, addr);
155               DOIT (x);
156               bfd_put_16 (abfd, x, addr);
157             }
158             break;
159
160           case 2:
161             {
162               long x = bfd_get_32 (abfd, addr);
163               DOIT (x);
164               bfd_put_32 (abfd, x, addr);
165             }
166             break;
167
168           default:
169             abort ();
170           }
171       }
172
173   /* Now let bfd_perform_relocation finish everything up.  */
174   return bfd_reloc_continue;
175 }
176
177 #ifdef COFF_WITH_PE
178 /* Return true if this relocation should
179    appear in the output .reloc section.  */
180
181 static boolean
182 in_reloc_p (abfd, howto)
183      bfd * abfd ATTRIBUTE_UNUSED;
184      reloc_howto_type *howto;
185 {
186   return ! howto->pc_relative && howto->type != MIPS_R_RVA;
187 }
188 #endif
189
190 #ifndef PCRELOFFSET
191 #define PCRELOFFSET false
192 #endif
193
194 static reloc_howto_type howto_table[] =
195 {
196   /* Reloc type 0 is ignored.  The reloc reading code ensures that
197      this is a reference to the .abs section, which will cause
198      bfd_perform_relocation to do nothing.  */
199   HOWTO (MIPS_R_ABSOLUTE,       /* type */
200          0,                     /* rightshift */
201          0,                     /* size (0 = byte, 1 = short, 2 = long) */
202          8,                     /* bitsize */
203          false,                 /* pc_relative */
204          0,                     /* bitpos */
205          complain_overflow_dont, /* complain_on_overflow */
206          0,                     /* special_function */
207          "IGNORE",              /* name */
208          false,                 /* partial_inplace */
209          0,                     /* src_mask */
210          0,                     /* dst_mask */
211          false),                /* pcrel_offset */
212
213   /* A 16 bit reference to a symbol, normally from a data section.  */
214   HOWTO (MIPS_R_REFHALF,        /* type */
215          0,                     /* rightshift */
216          1,                     /* size (0 = byte, 1 = short, 2 = long) */
217          16,                    /* bitsize */
218          false,                 /* pc_relative */
219          0,                     /* bitpos */
220          complain_overflow_bitfield, /* complain_on_overflow */
221          coff_mips_reloc,       /* special_function */
222          "REFHALF",             /* name */
223          true,                  /* partial_inplace */
224          0xffff,                /* src_mask */
225          0xffff,                /* dst_mask */
226          false),                /* pcrel_offset */
227
228   /* A 32 bit reference to a symbol, normally from a data section.  */
229   HOWTO (MIPS_R_REFWORD,        /* type */
230          0,                     /* rightshift */
231          2,                     /* size (0 = byte, 1 = short, 2 = long) */
232          32,                    /* bitsize */
233          false,                 /* pc_relative */
234          0,                     /* bitpos */
235          complain_overflow_bitfield, /* complain_on_overflow */
236          coff_mips_reloc,       /* special_function */
237          "REFWORD",             /* name */
238          true,                  /* partial_inplace */
239          0xffffffff,            /* src_mask */
240          0xffffffff,            /* dst_mask */
241          false),                /* pcrel_offset */
242
243   /* A 26 bit absolute jump address.  */
244   HOWTO (MIPS_R_JMPADDR,        /* type */
245          2,                     /* rightshift */
246          2,                     /* size (0 = byte, 1 = short, 2 = long) */
247          26,                    /* bitsize */
248          false,                 /* pc_relative */
249          0,                     /* bitpos */
250          complain_overflow_dont, /* complain_on_overflow */
251                                 /* This needs complex overflow
252                                    detection, because the upper four
253                                    bits must match the PC.  */
254          coff_mips_reloc,       /* special_function */
255          "JMPADDR",             /* name */
256          true,                  /* partial_inplace */
257          0x3ffffff,             /* src_mask */
258          0x3ffffff,             /* dst_mask */
259          false),                /* pcrel_offset */
260
261   /* The high 16 bits of a symbol value.  Handled by the function
262      mips_refhi_reloc.  */
263   HOWTO (MIPS_R_REFHI,          /* type */
264          16,                    /* rightshift */
265          2,                     /* size (0 = byte, 1 = short, 2 = long) */
266          16,                    /* bitsize */
267          false,                 /* pc_relative */
268          0,                     /* bitpos */
269          complain_overflow_bitfield, /* complain_on_overflow */
270          coff_mips_reloc,       /* special_function */
271          "REFHI",               /* name */
272          true,                  /* partial_inplace */
273          0xffff,                /* src_mask */
274          0xffff,                /* dst_mask */
275          false),                /* pcrel_offset */
276
277   /* The low 16 bits of a symbol value.  */
278   HOWTO (MIPS_R_REFLO,          /* type */
279          0,                     /* rightshift */
280          2,                     /* size (0 = byte, 1 = short, 2 = long) */
281          16,                    /* bitsize */
282          false,                 /* pc_relative */
283          0,                     /* bitpos */
284          complain_overflow_dont, /* complain_on_overflow */
285          coff_mips_reloc,       /* special_function */
286          "REFLO",               /* name */
287          true,                  /* partial_inplace */
288          0xffff,                /* src_mask */
289          0xffff,                /* dst_mask */
290          false),                /* pcrel_offset */
291
292   /* A reference to an offset from the gp register.  Handled by the
293      function mips_gprel_reloc.  */
294   HOWTO (MIPS_R_GPREL,          /* type */
295          0,                     /* rightshift */
296          2,                     /* size (0 = byte, 1 = short, 2 = long) */
297          16,                    /* bitsize */
298          false,                 /* pc_relative */
299          0,                     /* bitpos */
300          complain_overflow_signed, /* complain_on_overflow */
301          coff_mips_reloc,       /* special_function */
302          "GPREL",               /* name */
303          true,                  /* partial_inplace */
304          0xffff,                /* src_mask */
305          0xffff,                /* dst_mask */
306          false),                /* pcrel_offset */
307
308   /* A reference to a literal using an offset from the gp register.
309      Handled by the function mips_gprel_reloc.  */
310   HOWTO (MIPS_R_LITERAL,        /* type */
311          0,                     /* rightshift */
312          2,                     /* size (0 = byte, 1 = short, 2 = long) */
313          16,                    /* bitsize */
314          false,                 /* pc_relative */
315          0,                     /* bitpos */
316          complain_overflow_signed, /* complain_on_overflow */
317          coff_mips_reloc,       /* special_function */
318          "LITERAL",             /* name */
319          true,                  /* partial_inplace */
320          0xffff,                /* src_mask */
321          0xffff,                /* dst_mask */
322          false),                /* pcrel_offset */
323
324   EMPTY_HOWTO (8),
325   EMPTY_HOWTO (9),
326   EMPTY_HOWTO (10),
327   EMPTY_HOWTO (11),
328   EMPTY_HOWTO (12),
329   EMPTY_HOWTO (13),
330   EMPTY_HOWTO (14),
331   EMPTY_HOWTO (15),
332   EMPTY_HOWTO (16),
333   EMPTY_HOWTO (17),
334   EMPTY_HOWTO (18),
335   EMPTY_HOWTO (19),
336   EMPTY_HOWTO (20),
337   EMPTY_HOWTO (21),
338   EMPTY_HOWTO (22),
339   EMPTY_HOWTO (23),
340   EMPTY_HOWTO (24),
341   EMPTY_HOWTO (25),
342   EMPTY_HOWTO (26),
343   EMPTY_HOWTO (27),
344   EMPTY_HOWTO (28),
345   EMPTY_HOWTO (29),
346   EMPTY_HOWTO (30),
347   EMPTY_HOWTO (31),
348   EMPTY_HOWTO (32),
349   EMPTY_HOWTO (33),
350   HOWTO (MIPS_R_RVA,            /* type */
351          0,                     /* rightshift */
352          2,                     /* size (0 = byte, 1 = short, 2 = long) */
353          32,                    /* bitsize */
354          false,                 /* pc_relative */
355          0,                     /* bitpos */
356          complain_overflow_bitfield, /* complain_on_overflow */
357          coff_mips_reloc,       /* special_function */
358          "rva32",               /* name */
359          true,                  /* partial_inplace */
360          0xffffffff,            /* src_mask */
361          0xffffffff,            /* dst_mask */
362          false),                /* pcrel_offset */
363   EMPTY_HOWTO (35),
364   EMPTY_HOWTO (36),
365   HOWTO (MIPS_R_PAIR,           /* type */
366          0,                     /* rightshift */
367          2,                     /* size (0 = byte, 1 = short, 2 = long) */
368          32,                    /* bitsize */
369          false,                 /* pc_relative */
370          0,                     /* bitpos */
371          complain_overflow_bitfield, /* complain_on_overflow */
372          coff_mips_reloc,       /* special_function */
373          "PAIR",                /* name */
374          true,                  /* partial_inplace */
375          0xffffffff,            /* src_mask */
376          0xffffffff,            /* dst_mask */
377          false),                /* pcrel_offset */
378 };
379
380 /* Turn a howto into a reloc  nunmber */
381
382 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
383 #define BADMAG(x) MIPSBADMAG(x)
384 #define MIPS 1                  /* Customize coffcode.h */
385
386 #define RTYPE2HOWTO(cache_ptr, dst) \
387             (cache_ptr)->howto = howto_table + (dst)->r_type;
388
389 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
390    the object file contains the value of the common symbol.  By the
391    time this is called, the linker may be using a different symbol
392    from a different object file with a different value.  Therefore, we
393    hack wildly to locate the original symbol from this file so that we
394    can make the correct adjustment.  This macro sets coffsym to the
395    symbol from the original file, and uses it to set the addend value
396    correctly.  If this is not a common symbol, the usual addend
397    calculation is done, except that an additional tweak is needed for
398    PC relative relocs.
399    FIXME: This macro refers to symbols and asect; these are from the
400    calling function, not the macro arguments.  */
401
402 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
403   {                                                             \
404     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
405     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
406       coffsym = (obj_symbols (abfd)                             \
407                  + (cache_ptr->sym_ptr_ptr - symbols));         \
408     else if (ptr)                                               \
409       coffsym = coff_symbol_from (abfd, ptr);                   \
410     if (coffsym != (coff_symbol_type *) NULL                    \
411         && coffsym->native->u.syment.n_scnum == 0)              \
412       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
413     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
414              && ptr->section != (asection *) NULL)              \
415       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
416     else                                                        \
417       cache_ptr->addend = 0;                                    \
418     if (ptr && howto_table[reloc.r_type].pc_relative)           \
419       cache_ptr->addend += asect->vma;                          \
420   }
421
422 /* Convert an rtype to howto for the COFF backend linker.  */
423
424 static reloc_howto_type *
425 coff_mips_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
426      bfd *abfd ATTRIBUTE_UNUSED;
427      asection *sec;
428      struct internal_reloc *rel;
429      struct coff_link_hash_entry *h;
430      struct internal_syment *sym;
431      bfd_vma *addendp;
432 {
433
434   reloc_howto_type *howto;
435
436   howto = howto_table + rel->r_type;
437
438 #ifdef COFF_WITH_PE
439   *addendp = 0;
440 #endif
441
442   if (howto->pc_relative)
443     *addendp += sec->vma;
444
445   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
446     {
447       /* This is a common symbol.  The section contents include the
448          size (sym->n_value) as an addend.  The relocate_section
449          function will be adding in the final value of the symbol.  We
450          need to subtract out the current size in order to get the
451          correct result.  */
452
453       BFD_ASSERT (h != NULL);
454
455 #ifndef COFF_WITH_PE
456       /* I think we *do* want to bypass this.  If we don't, I have
457          seen some data parameters get the wrong relocation address.
458          If I link two versions with and without this section bypassed
459          and then do a binary comparison, the addresses which are
460          different can be looked up in the map.  The case in which
461          this section has been bypassed has addresses which correspond
462          to values I can find in the map.  */
463       *addendp -= sym->n_value;
464 #endif
465     }
466
467 #ifndef COFF_WITH_PE
468   /* If the output symbol is common (in which case this must be a
469      relocateable link), we need to add in the final size of the
470      common symbol.  */
471   if (h != NULL && h->root.type == bfd_link_hash_common)
472     *addendp += h->root.u.c.size;
473 #endif
474
475 #ifdef COFF_WITH_PE
476   if (howto->pc_relative)
477     {
478       *addendp -= 4;
479
480       /* If the symbol is defined, then the generic code is going to
481          add back the symbol value in order to cancel out an
482          adjustment it made to the addend.  However, we set the addend
483          to 0 at the start of this function.  We need to adjust here,
484          to avoid the adjustment the generic code will make.  FIXME:
485          This is getting a bit hackish.  */
486       if (sym != NULL && sym->n_scnum != 0)
487         *addendp -= sym->n_value;
488     }
489
490   if (rel->r_type == MIPS_R_RVA)
491     {
492       *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
493     }
494 #endif
495
496   return howto;
497 }
498
499 #define coff_rtype_to_howto coff_mips_rtype_to_howto
500
501 #define coff_bfd_reloc_type_lookup coff_mips_reloc_type_lookup
502
503 /* Get the howto structure for a generic reloc type.  */
504
505 static reloc_howto_type *
506 coff_mips_reloc_type_lookup (abfd, code)
507      bfd *abfd ATTRIBUTE_UNUSED;
508      bfd_reloc_code_real_type code;
509 {
510   int mips_type;
511
512   switch (code)
513     {
514     case BFD_RELOC_16:
515       mips_type = MIPS_R_REFHALF;
516       break;
517     case BFD_RELOC_32:
518     case BFD_RELOC_CTOR:
519       mips_type = MIPS_R_REFWORD;
520       break;
521     case BFD_RELOC_MIPS_JMP:
522       mips_type = MIPS_R_JMPADDR;
523       break;
524     case BFD_RELOC_HI16_S:
525       mips_type = MIPS_R_REFHI;
526       break;
527     case BFD_RELOC_LO16:
528       mips_type = MIPS_R_REFLO;
529       break;
530     case BFD_RELOC_MIPS_GPREL:
531       mips_type = MIPS_R_GPREL;
532       break;
533     case BFD_RELOC_MIPS_LITERAL:
534       mips_type = MIPS_R_LITERAL;
535       break;
536 /* FIXME?
537     case BFD_RELOC_16_PCREL_S2:
538       mips_type = MIPS_R_PCREL16;
539       break;
540     case BFD_RELOC_PCREL_HI16_S:
541       mips_type = MIPS_R_RELHI;
542       break;
543     case BFD_RELOC_PCREL_LO16:
544       mips_type = MIPS_R_RELLO;
545       break;
546     case BFD_RELOC_GPREL32:
547       mips_type = MIPS_R_SWITCH;
548       break;
549 */
550     case BFD_RELOC_RVA:
551       mips_type = MIPS_R_RVA;
552       break;
553     default:
554       return (reloc_howto_type *) NULL;
555     }
556
557   return &howto_table[mips_type];
558 }
559
560 static void
561 mips_swap_reloc_in (abfd, src, dst)
562      bfd *abfd;
563      PTR src;
564      PTR dst;
565 {
566   static struct internal_reloc pair_prev;
567   RELOC *reloc_src = (RELOC *) src;
568   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
569
570   reloc_dst->r_vaddr = bfd_h_get_32(abfd, (bfd_byte *)reloc_src->r_vaddr);
571   reloc_dst->r_symndx =
572     bfd_h_get_signed_32(abfd, (bfd_byte *) reloc_src->r_symndx);
573   reloc_dst->r_type = bfd_h_get_16(abfd, (bfd_byte *) reloc_src->r_type);
574   reloc_dst->r_size = 0;
575   reloc_dst->r_extern = 0;
576   reloc_dst->r_offset = 0;
577
578   switch (reloc_dst->r_type)
579   {
580   case MIPS_R_REFHI:
581     pair_prev = *reloc_dst;
582     break;
583   case MIPS_R_PAIR:
584     reloc_dst->r_offset = reloc_dst->r_symndx;
585     if (reloc_dst->r_offset & 0x8000)
586       reloc_dst->r_offset -= 0x10000;
587     /*printf ("dj: pair offset is %08x\n", reloc_dst->r_offset);*/
588     reloc_dst->r_symndx = pair_prev.r_symndx;
589     break;
590   }
591 }
592
593 static unsigned int
594 mips_swap_reloc_out (abfd, src, dst)
595      bfd       *abfd;
596      PTR        src;
597      PTR        dst;
598 {
599   static int prev_offset = 1;
600   static bfd_vma prev_addr = 0;
601   struct internal_reloc *reloc_src = (struct internal_reloc *)src;
602   struct external_reloc *reloc_dst = (struct external_reloc *)dst;
603
604   switch (reloc_src->r_type)
605     {
606     case MIPS_R_REFHI:
607       prev_addr = reloc_src->r_vaddr;
608       prev_offset = reloc_src->r_offset;
609       break;
610     case MIPS_R_REFLO:
611       if (reloc_src->r_vaddr == prev_addr)
612         {
613           /* FIXME: only slightly hackish.  If we see a REFLO pointing to
614              the same address as a REFHI, we assume this is the matching
615              PAIR reloc and output it accordingly.  The symndx is really
616              the low 16 bits of the addend */
617           bfd_h_put_32 (abfd, reloc_src->r_vaddr,
618                         (bfd_byte *) reloc_dst->r_vaddr);
619           bfd_h_put_32 (abfd, reloc_src->r_symndx,
620                         (bfd_byte *) reloc_dst->r_symndx);
621
622           bfd_h_put_16(abfd, MIPS_R_PAIR, (bfd_byte *)
623                        reloc_dst->r_type);
624           return RELSZ;
625         }
626       break;
627     }
628
629   bfd_h_put_32(abfd, reloc_src->r_vaddr, (bfd_byte *) reloc_dst->r_vaddr);
630   bfd_h_put_32(abfd, reloc_src->r_symndx, (bfd_byte *) reloc_dst->r_symndx);
631
632   bfd_h_put_16(abfd, reloc_src->r_type, (bfd_byte *)
633                reloc_dst->r_type);
634   return RELSZ;
635 }
636
637 #define coff_swap_reloc_in mips_swap_reloc_in
638 #define coff_swap_reloc_out mips_swap_reloc_out
639 #define NO_COFF_RELOCS
640
641 static boolean
642 coff_pe_mips_relocate_section (output_bfd, info, input_bfd,
643                                input_section, contents, relocs, syms,
644                                sections)
645      bfd *output_bfd;
646      struct bfd_link_info *info;
647      bfd *input_bfd;
648      asection *input_section;
649      bfd_byte *contents;
650      struct internal_reloc *relocs;
651      struct internal_syment *syms;
652      asection **sections;
653 {
654   bfd_vma gp;
655   boolean gp_undefined;
656   size_t adjust;
657   struct internal_reloc *rel;
658   struct internal_reloc *rel_end;
659   unsigned int i;
660   boolean got_lo;
661
662   if (info->relocateable)
663   {
664     (*_bfd_error_handler) (_("\
665 %s: `ld -r' not supported with PE MIPS objects\n"),
666                           bfd_get_filename (input_bfd));
667     bfd_set_error (bfd_error_bad_value);
668     return false;
669   }
670
671   BFD_ASSERT (input_bfd->xvec->byteorder
672               == output_bfd->xvec->byteorder);
673
674 #if 0
675   printf ("dj: relocate %s(%s) %08x\n",
676          input_bfd->filename, input_section->name,
677          input_section->output_section->vma + input_section->output_offset);
678 #endif
679
680   gp = _bfd_get_gp_value (output_bfd);
681   if (gp == 0)
682     gp_undefined = true;
683   else
684     gp_undefined = false;
685
686   got_lo = false;
687
688   adjust = 0;
689
690   rel = relocs;
691   rel_end = rel + input_section->reloc_count;
692   for (i = 0; rel < rel_end; rel++, i++)
693     {
694       long symndx;
695       struct coff_link_hash_entry *h;
696       struct internal_syment *sym;
697       bfd_vma addend = 0;
698       bfd_vma val, tmp, targ, src, low;
699       reloc_howto_type *howto;
700       unsigned char *mem = contents + rel->r_vaddr;
701
702       symndx = rel->r_symndx;
703
704       if (symndx == -1)
705         {
706           h = NULL;
707           sym = NULL;
708         }
709       else
710         {
711           h = obj_coff_sym_hashes (input_bfd)[symndx];
712           sym = syms + symndx;
713         }
714
715       /* COFF treats common symbols in one of two ways.  Either the
716          size of the symbol is included in the section contents, or it
717          is not.  We assume that the size is not included, and force
718          the rtype_to_howto function to adjust the addend as needed.  */
719
720       if (sym != NULL && sym->n_scnum != 0)
721         addend = - sym->n_value;
722       else
723         addend = 0;
724
725       howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
726                                        sym, &addend);
727       if (howto == NULL)
728         return false;
729
730       /* If we are doing a relocateable link, then we can just ignore
731          a PC relative reloc that is pcrel_offset.  It will already
732          have the correct value.  If this is not a relocateable link,
733          then we should ignore the symbol value.  */
734       if (howto->pc_relative && howto->pcrel_offset)
735         {
736           if (info->relocateable)
737             continue;
738           if (sym != NULL && sym->n_scnum != 0)
739             addend += sym->n_value;
740         }
741
742       val = 0;
743
744       if (h == NULL)
745         {
746           asection *sec;
747
748           if (symndx == -1)
749             {
750               sec = bfd_abs_section_ptr;
751               val = 0;
752             }
753           else
754             {
755               sec = sections[symndx];
756               val = (sec->output_section->vma
757                      + sec->output_offset
758                      + sym->n_value);
759               if (! obj_pe (input_bfd))
760                 val -= sec->vma;
761             }
762         }
763       else
764         {
765           if (h->root.type == bfd_link_hash_defined
766               || h->root.type == bfd_link_hash_defweak)
767             {
768               asection *sec;
769
770               sec = h->root.u.def.section;
771               val = (h->root.u.def.value
772                      + sec->output_section->vma
773                      + sec->output_offset);
774               }
775
776           else if (! info->relocateable)
777             {
778               if (! ((*info->callbacks->undefined_symbol)
779                      (info, h->root.root.string, input_bfd, input_section,
780                       rel->r_vaddr - input_section->vma, true)))
781                 return false;
782             }
783         }
784
785       src = rel->r_vaddr + input_section->output_section->vma
786         + input_section->output_offset;
787 #if 0
788       printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n",
789              rel->r_type, howto_table[rel->r_type].name,
790              src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset,
791              h?h->root.root.string:"(none)");
792 #endif
793
794       /* OK, at this point the following variables are set up:
795            src = VMA of the memory we're fixing up
796            mem = pointer to memory we're fixing up
797            val = VMA of what we need to refer to
798       */
799
800 #define UI(x) (*_bfd_error_handler) (_("%s: unimplemented %s\n"), \
801                                     bfd_get_filename (input_bfd), x); \
802               bfd_set_error (bfd_error_bad_value);
803
804       switch (rel->r_type)
805         {
806         case MIPS_R_ABSOLUTE:
807           /* ignore these */
808           break;
809
810         case MIPS_R_REFHALF:
811           UI("refhalf");
812           break;
813
814         case MIPS_R_REFWORD:
815           tmp = bfd_get_32(input_bfd, mem);
816           /* printf ("refword: src=%08x targ=%08x+%08x\n", src, tmp, val); */
817           tmp += val;
818           bfd_put_32(input_bfd, tmp, mem);
819           break;
820
821         case MIPS_R_JMPADDR:
822           tmp = bfd_get_32(input_bfd, mem);
823           targ = val + (tmp&0x03ffffff)*4;
824           if ((src & 0xf0000000) != (targ & 0xf0000000))
825             {
826               (*_bfd_error_handler) (_("%s: jump too far away\n"),
827                                     bfd_get_filename (input_bfd));
828               bfd_set_error (bfd_error_bad_value);
829               return false;
830             }
831           tmp &= 0xfc000000;
832           tmp |= (targ/4) & 0x3ffffff;
833           bfd_put_32(input_bfd, tmp, mem);
834           break;
835
836         case MIPS_R_REFHI:
837           tmp = bfd_get_32(input_bfd, mem);
838           switch (rel[1].r_type)
839             {
840             case MIPS_R_PAIR:
841               /* MS PE object */
842               targ = val + rel[1].r_offset + ((tmp & 0xffff) << 16);
843               break;
844             case MIPS_R_REFLO:
845               /* GNU COFF object */
846               low = bfd_get_32(input_bfd, contents + rel[1].r_vaddr);
847               low &= 0xffff;
848               if (low & 0x8000)
849                 low -= 0x10000;
850               targ = val + low + ((tmp & 0xffff) << 16);
851               break;
852             default:
853               (*_bfd_error_handler) (_("%s: bad pair/reflo after refhi\n"),
854                                     bfd_get_filename (input_bfd));
855               bfd_set_error (bfd_error_bad_value);
856               return false;
857             }
858           tmp &= 0xffff0000;
859           tmp |= (targ >> 16) & 0xffff;
860           bfd_put_32(input_bfd, tmp, mem);
861           break;
862
863         case MIPS_R_REFLO:
864           tmp = bfd_get_32(input_bfd, mem);
865           targ = val + (tmp & 0xffff);
866           /* printf ("refword: src=%08x targ=%08x\n", src, targ); */
867           tmp &= 0xffff0000;
868           tmp |= targ & 0xffff;
869           bfd_put_32(input_bfd, tmp, mem);
870           break;
871
872         case MIPS_R_GPREL:
873         case MIPS_R_LITERAL:
874           UI("gprel");
875           break;
876
877         case MIPS_R_SECTION:
878           UI("section");
879           break;
880
881         case MIPS_R_SECREL:
882           UI("secrel");
883           break;
884
885         case MIPS_R_SECRELLO:
886           UI("secrello");
887           break;
888
889         case MIPS_R_SECRELHI:
890           UI("secrelhi");
891           break;
892
893         case MIPS_R_RVA:
894           tmp = bfd_get_32 (input_bfd, mem);
895           /* printf ("rva: src=%08x targ=%08x+%08x\n", src, tmp, val); */
896           tmp += val
897             - pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
898           bfd_put_32 (input_bfd, tmp, mem);
899           break;
900
901         case MIPS_R_PAIR:
902           /* ignore these */
903           break;
904         }
905     }
906
907   return true;
908 }
909
910 #define coff_relocate_section coff_pe_mips_relocate_section
911
912 #ifdef TARGET_UNDERSCORE
913
914 /* If mips gcc uses underscores for symbol names, then it does not use
915    a leading dot for local labels, so if TARGET_UNDERSCORE is defined
916    we treat all symbols starting with L as local.  */
917
918 static boolean coff_mips_is_local_label_name PARAMS ((bfd *, const char *));
919
920 static boolean
921 coff_mips_is_local_label_name (abfd, name)
922      bfd *abfd;
923      const char *name;
924 {
925   if (name[0] == 'L')
926     return true;
927
928   return _bfd_coff_is_local_label_name (abfd, name);
929 }
930
931 #define coff_bfd_is_local_label_name coff_mips_is_local_label_name
932
933 #endif /* TARGET_UNDERSCORE */
934
935 #define COFF_NO_HACK_SCNHDR_SIZE
936
937 #include "coffcode.h"
938
939 const bfd_target
940 #ifdef TARGET_SYM
941   TARGET_SYM =
942 #else
943   mipslpe_vec =
944 #endif
945 {
946 #ifdef TARGET_NAME
947   TARGET_NAME,
948 #else
949   "pe-mips",                    /* name */
950 #endif
951   bfd_target_coff_flavour,
952   BFD_ENDIAN_LITTLE,            /* data byte order is little */
953   BFD_ENDIAN_LITTLE,            /* header byte order is little */
954
955   (HAS_RELOC | EXEC_P |         /* object flags */
956    HAS_LINENO | HAS_DEBUG |
957    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
958
959 #ifndef COFF_WITH_PE
960   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
961    | SEC_CODE | SEC_DATA),
962 #else
963   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
964    | SEC_CODE | SEC_DATA
965    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
966 #endif
967
968 #ifdef TARGET_UNDERSCORE
969   TARGET_UNDERSCORE,            /* leading underscore */
970 #else
971   0,                            /* leading underscore */
972 #endif
973   '/',                          /* ar_pad_char */
974   15,                           /* ar_max_namelen */
975
976   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
977      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
978      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
979   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
980      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
981      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
982
983 /* Note that we allow an object file to be treated as a core file as well.  */
984     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
985        bfd_generic_archive_p, coff_object_p},
986     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
987        bfd_false},
988     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
989        _bfd_write_archive_contents, bfd_false},
990
991      BFD_JUMP_TABLE_GENERIC (coff),
992      BFD_JUMP_TABLE_COPY (coff),
993      BFD_JUMP_TABLE_CORE (_bfd_nocore),
994      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
995      BFD_JUMP_TABLE_SYMBOLS (coff),
996      BFD_JUMP_TABLE_RELOCS (coff),
997      BFD_JUMP_TABLE_WRITE (coff),
998      BFD_JUMP_TABLE_LINK (coff),
999      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1000
1001   NULL,
1002
1003   COFF_SWAP_TABLE
1004 };