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