bfd/
[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, 2004 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       (_("%B: `ld -r' not supported with PE MIPS objects\n"), input_bfd);
637     bfd_set_error (bfd_error_bad_value);
638     return FALSE;
639   }
640
641   BFD_ASSERT (input_bfd->xvec->byteorder
642               == output_bfd->xvec->byteorder);
643
644 #if 0
645   printf ("dj: relocate %s(%s) %08x\n",
646          input_bfd->filename, input_section->name,
647          input_section->output_section->vma + input_section->output_offset);
648 #endif
649
650   gp = _bfd_get_gp_value (output_bfd);
651   if (gp == 0)
652     gp_undefined = TRUE;
653   else
654     gp_undefined = FALSE;
655
656   got_lo = FALSE;
657
658   adjust = 0;
659
660   rel = relocs;
661   rel_end = rel + input_section->reloc_count;
662   for (i = 0; rel < rel_end; rel++, i++)
663     {
664       long symndx;
665       struct coff_link_hash_entry *h;
666       struct internal_syment *sym;
667       bfd_vma addend = 0;
668       bfd_vma val, tmp, targ, src, low;
669       reloc_howto_type *howto;
670       unsigned char *mem = contents + rel->r_vaddr;
671
672       symndx = rel->r_symndx;
673
674       if (symndx == -1)
675         {
676           h = NULL;
677           sym = NULL;
678         }
679       else
680         {
681           h = obj_coff_sym_hashes (input_bfd)[symndx];
682           sym = syms + symndx;
683         }
684
685       /* COFF treats common symbols in one of two ways.  Either the
686          size of the symbol is included in the section contents, or it
687          is not.  We assume that the size is not included, and force
688          the rtype_to_howto function to adjust the addend as needed.  */
689
690       if (sym != NULL && sym->n_scnum != 0)
691         addend = - sym->n_value;
692       else
693         addend = 0;
694
695       howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
696                                        sym, &addend);
697       if (howto == NULL)
698         return FALSE;
699
700       /* If we are doing a relocatable link, then we can just ignore
701          a PC relative reloc that is pcrel_offset.  It will already
702          have the correct value.  If this is not a relocatable link,
703          then we should ignore the symbol value.  */
704       if (howto->pc_relative && howto->pcrel_offset)
705         {
706           if (info->relocatable)
707             continue;
708           if (sym != NULL && sym->n_scnum != 0)
709             addend += sym->n_value;
710         }
711
712       val = 0;
713
714       if (h == NULL)
715         {
716           asection *sec;
717
718           if (symndx == -1)
719             {
720               sec = bfd_abs_section_ptr;
721               val = 0;
722             }
723           else
724             {
725               sec = sections[symndx];
726               val = (sec->output_section->vma
727                      + sec->output_offset
728                      + sym->n_value);
729               if (! obj_pe (input_bfd))
730                 val -= sec->vma;
731             }
732         }
733       else
734         {
735           if (h->root.type == bfd_link_hash_defined
736               || h->root.type == bfd_link_hash_defweak)
737             {
738               asection *sec;
739
740               sec = h->root.u.def.section;
741               val = (h->root.u.def.value
742                      + sec->output_section->vma
743                      + sec->output_offset);
744               }
745
746           else if (! info->relocatable)
747             {
748               if (! ((*info->callbacks->undefined_symbol)
749                      (info, h->root.root.string, input_bfd, input_section,
750                       rel->r_vaddr - input_section->vma, TRUE)))
751                 return FALSE;
752             }
753         }
754
755       src = rel->r_vaddr + input_section->output_section->vma
756         + input_section->output_offset;
757 #if 0
758       printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n",
759              rel->r_type, howto_table[rel->r_type].name,
760              src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset,
761              h?h->root.root.string:"(none)");
762 #endif
763
764       /* OK, at this point the following variables are set up:
765            src = VMA of the memory we're fixing up
766            mem = pointer to memory we're fixing up
767            val = VMA of what we need to refer to
768       */
769
770 #define UI(x) (*_bfd_error_handler) (_("%B: unimplemented %s\n"), \
771                                      input_bfd, x); \
772               bfd_set_error (bfd_error_bad_value);
773
774       switch (rel->r_type)
775         {
776         case MIPS_R_ABSOLUTE:
777           /* ignore these */
778           break;
779
780         case MIPS_R_REFHALF:
781           UI("refhalf");
782           break;
783
784         case MIPS_R_REFWORD:
785           tmp = bfd_get_32(input_bfd, mem);
786           /* printf ("refword: src=%08x targ=%08x+%08x\n", src, tmp, val); */
787           tmp += val;
788           bfd_put_32(input_bfd, tmp, mem);
789           break;
790
791         case MIPS_R_JMPADDR:
792           tmp = bfd_get_32(input_bfd, mem);
793           targ = val + (tmp&0x03ffffff)*4;
794           if ((src & 0xf0000000) != (targ & 0xf0000000))
795             {
796               (*_bfd_error_handler) (_("%B: jump too far away\n"), input_bfd);
797               bfd_set_error (bfd_error_bad_value);
798               return FALSE;
799             }
800           tmp &= 0xfc000000;
801           tmp |= (targ/4) & 0x3ffffff;
802           bfd_put_32(input_bfd, tmp, mem);
803           break;
804
805         case MIPS_R_REFHI:
806           tmp = bfd_get_32(input_bfd, mem);
807           switch (rel[1].r_type)
808             {
809             case MIPS_R_PAIR:
810               /* MS PE object */
811               targ = val + rel[1].r_offset + ((tmp & 0xffff) << 16);
812               break;
813             case MIPS_R_REFLO:
814               /* GNU COFF object */
815               low = bfd_get_32(input_bfd, contents + rel[1].r_vaddr);
816               low &= 0xffff;
817               if (low & 0x8000)
818                 low -= 0x10000;
819               targ = val + low + ((tmp & 0xffff) << 16);
820               break;
821             default:
822               (*_bfd_error_handler) (_("%B: bad pair/reflo after refhi\n"),
823                                      input_bfd);
824               bfd_set_error (bfd_error_bad_value);
825               return FALSE;
826             }
827           tmp &= 0xffff0000;
828           tmp |= (targ >> 16) & 0xffff;
829           bfd_put_32(input_bfd, tmp, mem);
830           break;
831
832         case MIPS_R_REFLO:
833           tmp = bfd_get_32(input_bfd, mem);
834           targ = val + (tmp & 0xffff);
835           /* printf ("refword: src=%08x targ=%08x\n", src, targ); */
836           tmp &= 0xffff0000;
837           tmp |= targ & 0xffff;
838           bfd_put_32(input_bfd, tmp, mem);
839           break;
840
841         case MIPS_R_GPREL:
842         case MIPS_R_LITERAL:
843           UI("gprel");
844           break;
845
846         case MIPS_R_SECTION:
847           UI("section");
848           break;
849
850         case MIPS_R_SECREL:
851           UI("secrel");
852           break;
853
854         case MIPS_R_SECRELLO:
855           UI("secrello");
856           break;
857
858         case MIPS_R_SECRELHI:
859           UI("secrelhi");
860           break;
861
862         case MIPS_R_RVA:
863           tmp = bfd_get_32 (input_bfd, mem);
864           /* printf ("rva: src=%08x targ=%08x+%08x\n", src, tmp, val); */
865           tmp += val
866             - pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
867           bfd_put_32 (input_bfd, tmp, mem);
868           break;
869
870         case MIPS_R_PAIR:
871           /* ignore these */
872           break;
873         }
874     }
875
876   return TRUE;
877 }
878
879 #define coff_relocate_section coff_pe_mips_relocate_section
880
881 #ifdef TARGET_UNDERSCORE
882
883 /* If mips gcc uses underscores for symbol names, then it does not use
884    a leading dot for local labels, so if TARGET_UNDERSCORE is defined
885    we treat all symbols starting with L as local.  */
886
887 static bfd_boolean coff_mips_is_local_label_name
888    PARAMS ((bfd *, const char *));
889
890 static bfd_boolean
891 coff_mips_is_local_label_name (abfd, name)
892      bfd *abfd;
893      const char *name;
894 {
895   if (name[0] == 'L')
896     return TRUE;
897
898   return _bfd_coff_is_local_label_name (abfd, name);
899 }
900
901 #define coff_bfd_is_local_label_name coff_mips_is_local_label_name
902
903 #endif /* TARGET_UNDERSCORE */
904
905 #define COFF_NO_HACK_SCNHDR_SIZE
906
907 #include "coffcode.h"
908
909 const bfd_target
910 #ifdef TARGET_SYM
911   TARGET_SYM =
912 #else
913   mipslpe_vec =
914 #endif
915 {
916 #ifdef TARGET_NAME
917   TARGET_NAME,
918 #else
919   "pe-mips",                    /* name */
920 #endif
921   bfd_target_coff_flavour,
922   BFD_ENDIAN_LITTLE,            /* data byte order is little */
923   BFD_ENDIAN_LITTLE,            /* header byte order is little */
924
925   (HAS_RELOC | EXEC_P |         /* object flags */
926    HAS_LINENO | HAS_DEBUG |
927    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
928
929 #ifndef COFF_WITH_PE
930   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
931    | SEC_CODE | SEC_DATA),
932 #else
933   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
934    | SEC_CODE | SEC_DATA
935    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
936 #endif
937
938 #ifdef TARGET_UNDERSCORE
939   TARGET_UNDERSCORE,            /* leading underscore */
940 #else
941   0,                            /* leading underscore */
942 #endif
943   '/',                          /* ar_pad_char */
944   15,                           /* ar_max_namelen */
945
946   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
947      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
948      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
949   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
950      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
951      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
952
953 /* Note that we allow an object file to be treated as a core file as well.  */
954     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
955        bfd_generic_archive_p, coff_object_p},
956     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
957        bfd_false},
958     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
959        _bfd_write_archive_contents, bfd_false},
960
961      BFD_JUMP_TABLE_GENERIC (coff),
962      BFD_JUMP_TABLE_COPY (coff),
963      BFD_JUMP_TABLE_CORE (_bfd_nocore),
964      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
965      BFD_JUMP_TABLE_SYMBOLS (coff),
966      BFD_JUMP_TABLE_RELOCS (coff),
967      BFD_JUMP_TABLE_WRITE (coff),
968      BFD_JUMP_TABLE_LINK (coff),
969      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
970
971   NULL,
972
973   COFF_SWAP_TABLE
974 };