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