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