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