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