Initial import from FreeBSD RELENG_4:
[dragonfly.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 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
44            bfd_vma *));
45 #if 0
46 static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
47                                               struct internal_reloc *));
48 static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
49                                                const struct internal_reloc *,
50                                                PTR));
51 static void mips_adjust_reloc_in PARAMS ((bfd *,
52                                           const struct internal_reloc *,
53                                           arelent *));
54 static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
55                                            struct internal_reloc *));
56 #endif
57
58 static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
59 static reloc_howto_type * coff_mips_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
60 static void mips_swap_reloc_in PARAMS ((bfd *, PTR, PTR));
61 static unsigned int mips_swap_reloc_out PARAMS ((bfd *, PTR, PTR));
62 static boolean coff_pe_mips_relocate_section
63   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
64            struct internal_reloc *, struct internal_syment *, asection **));
65
66 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
67 /* The page size is a guess based on ELF.  */
68
69 #define COFF_PAGE_SIZE 0x1000
70
71 /* For some reason when using mips COFF the value stored in the .text
72    section for a reference to a common symbol is the value itself plus
73    any desired offset.  Ian Taylor, Cygnus Support.  */
74
75 /* If we are producing relocateable output, we need to do some
76    adjustments to the object file that are not done by the
77    bfd_perform_relocation function.  This function is called by every
78    reloc type to make any required adjustments.  */
79
80 static bfd_reloc_status_type
81 coff_mips_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
82                  error_message)
83      bfd *abfd;
84      arelent *reloc_entry;
85      asymbol *symbol;
86      PTR data;
87      asection *input_section ATTRIBUTE_UNUSED;
88      bfd *output_bfd;
89      char **error_message ATTRIBUTE_UNUSED;
90 {
91   symvalue diff;
92
93   if (output_bfd == (bfd *) NULL)
94     return bfd_reloc_continue;
95
96   if (bfd_is_com_section (symbol->section))
97     {
98 #ifndef COFF_WITH_PE
99       /* We are relocating a common symbol.  The current value in the
100          object file is ORIG + OFFSET, where ORIG is the value of the
101          common symbol as seen by the object file when it was compiled
102          (this may be zero if the symbol was undefined) and OFFSET is
103          the offset into the common symbol (normally zero, but may be
104          non-zero when referring to a field in a common structure).
105          ORIG is the negative of reloc_entry->addend, which is set by
106          the CALC_ADDEND macro below.  We want to replace the value in
107          the object file with NEW + OFFSET, where NEW is the value of
108          the common symbol which we are going to put in the final
109          object file.  NEW is symbol->value.  */
110       diff = symbol->value + reloc_entry->addend;
111 #else
112       /* In PE mode, we do not offset the common symbol.  */
113       diff = reloc_entry->addend;
114 #endif
115     }
116   else
117     {
118       /* For some reason bfd_perform_relocation always effectively
119          ignores the addend for a COFF target when producing
120          relocateable output.  This seems to be always wrong for 386
121          COFF, so we handle the addend here instead.  */
122       diff = reloc_entry->addend;
123     }
124
125 #ifdef COFF_WITH_PE
126 #if 0
127   /* dj - handle it like any other reloc? */
128   /* FIXME: How should this case be handled?  */
129   if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0)
130     abort ();
131 #endif
132 #endif
133
134 #define DOIT(x) \
135   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask))
136
137     if (diff != 0)
138       {
139         reloc_howto_type *howto = reloc_entry->howto;
140         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
141
142         switch (howto->size)
143           {
144           case 0:
145             {
146               char x = bfd_get_8 (abfd, addr);
147               DOIT (x);
148               bfd_put_8 (abfd, x, addr);
149             }
150             break;
151
152           case 1:
153             {
154               short x = bfd_get_16 (abfd, addr);
155               DOIT (x);
156               bfd_put_16 (abfd, (bfd_vma) x, addr);
157             }
158             break;
159
160           case 2:
161             {
162               long x = bfd_get_32 (abfd, addr);
163               DOIT (x);
164               bfd_put_32 (abfd, (bfd_vma) x, addr);
165             }
166             break;
167
168           default:
169             abort ();
170           }
171       }
172
173   /* Now let bfd_perform_relocation finish everything up.  */
174   return bfd_reloc_continue;
175 }
176
177 #ifdef COFF_WITH_PE
178 /* Return true if this relocation should
179    appear in the output .reloc section.  */
180
181 static boolean
182 in_reloc_p (abfd, howto)
183      bfd * abfd ATTRIBUTE_UNUSED;
184      reloc_howto_type *howto;
185 {
186   return ! howto->pc_relative && howto->type != MIPS_R_RVA;
187 }
188 #endif
189
190 #ifndef PCRELOFFSET
191 #define PCRELOFFSET false
192 #endif
193
194 static reloc_howto_type howto_table[] =
195 {
196   /* Reloc type 0 is ignored.  The reloc reading code ensures that
197      this is a reference to the .abs section, which will cause
198      bfd_perform_relocation to do nothing.  */
199   HOWTO (MIPS_R_ABSOLUTE,       /* type */
200          0,                     /* rightshift */
201          0,                     /* size (0 = byte, 1 = short, 2 = long) */
202          8,                     /* bitsize */
203          false,                 /* pc_relative */
204          0,                     /* bitpos */
205          complain_overflow_dont, /* complain_on_overflow */
206          0,                     /* special_function */
207          "IGNORE",              /* name */
208          false,                 /* partial_inplace */
209          0,                     /* src_mask */
210          0,                     /* dst_mask */
211          false),                /* pcrel_offset */
212
213   /* A 16 bit reference to a symbol, normally from a data section.  */
214   HOWTO (MIPS_R_REFHALF,        /* type */
215          0,                     /* rightshift */
216          1,                     /* size (0 = byte, 1 = short, 2 = long) */
217          16,                    /* bitsize */
218          false,                 /* pc_relative */
219          0,                     /* bitpos */
220          complain_overflow_bitfield, /* complain_on_overflow */
221          coff_mips_reloc,       /* special_function */
222          "REFHALF",             /* name */
223          true,                  /* partial_inplace */
224          0xffff,                /* src_mask */
225          0xffff,                /* dst_mask */
226          false),                /* pcrel_offset */
227
228   /* A 32 bit reference to a symbol, normally from a data section.  */
229   HOWTO (MIPS_R_REFWORD,        /* type */
230          0,                     /* rightshift */
231          2,                     /* size (0 = byte, 1 = short, 2 = long) */
232          32,                    /* bitsize */
233          false,                 /* pc_relative */
234          0,                     /* bitpos */
235          complain_overflow_bitfield, /* complain_on_overflow */
236          coff_mips_reloc,       /* special_function */
237          "REFWORD",             /* name */
238          true,                  /* partial_inplace */
239          0xffffffff,            /* src_mask */
240          0xffffffff,            /* dst_mask */
241          false),                /* pcrel_offset */
242
243   /* A 26 bit absolute jump address.  */
244   HOWTO (MIPS_R_JMPADDR,        /* type */
245          2,                     /* rightshift */
246          2,                     /* size (0 = byte, 1 = short, 2 = long) */
247          26,                    /* bitsize */
248          false,                 /* pc_relative */
249          0,                     /* bitpos */
250          complain_overflow_dont, /* complain_on_overflow */
251                                 /* This needs complex overflow
252                                    detection, because the upper four
253                                    bits must match the PC.  */
254          coff_mips_reloc,       /* special_function */
255          "JMPADDR",             /* name */
256          true,                  /* partial_inplace */
257          0x3ffffff,             /* src_mask */
258          0x3ffffff,             /* dst_mask */
259          false),                /* pcrel_offset */
260
261   /* The high 16 bits of a symbol value.  Handled by the function
262      mips_refhi_reloc.  */
263   HOWTO (MIPS_R_REFHI,          /* type */
264          16,                    /* rightshift */
265          2,                     /* size (0 = byte, 1 = short, 2 = long) */
266          16,                    /* bitsize */
267          false,                 /* pc_relative */
268          0,                     /* bitpos */
269          complain_overflow_bitfield, /* complain_on_overflow */
270          coff_mips_reloc,       /* special_function */
271          "REFHI",               /* name */
272          true,                  /* partial_inplace */
273          0xffff,                /* src_mask */
274          0xffff,                /* dst_mask */
275          false),                /* pcrel_offset */
276
277   /* The low 16 bits of a symbol value.  */
278   HOWTO (MIPS_R_REFLO,          /* type */
279          0,                     /* rightshift */
280          2,                     /* size (0 = byte, 1 = short, 2 = long) */
281          16,                    /* bitsize */
282          false,                 /* pc_relative */
283          0,                     /* bitpos */
284          complain_overflow_dont, /* complain_on_overflow */
285          coff_mips_reloc,       /* special_function */
286          "REFLO",               /* name */
287          true,                  /* partial_inplace */
288          0xffff,                /* src_mask */
289          0xffff,                /* dst_mask */
290          false),                /* pcrel_offset */
291
292   /* A reference to an offset from the gp register.  Handled by the
293      function mips_gprel_reloc.  */
294   HOWTO (MIPS_R_GPREL,          /* type */
295          0,                     /* rightshift */
296          2,                     /* size (0 = byte, 1 = short, 2 = long) */
297          16,                    /* bitsize */
298          false,                 /* pc_relative */
299          0,                     /* bitpos */
300          complain_overflow_signed, /* complain_on_overflow */
301          coff_mips_reloc,       /* special_function */
302          "GPREL",               /* name */
303          true,                  /* partial_inplace */
304          0xffff,                /* src_mask */
305          0xffff,                /* dst_mask */
306          false),                /* pcrel_offset */
307
308   /* A reference to a literal using an offset from the gp register.
309      Handled by the function mips_gprel_reloc.  */
310   HOWTO (MIPS_R_LITERAL,        /* type */
311          0,                     /* rightshift */
312          2,                     /* size (0 = byte, 1 = short, 2 = long) */
313          16,                    /* bitsize */
314          false,                 /* pc_relative */
315          0,                     /* bitpos */
316          complain_overflow_signed, /* complain_on_overflow */
317          coff_mips_reloc,       /* special_function */
318          "LITERAL",             /* name */
319          true,                  /* partial_inplace */
320          0xffff,                /* src_mask */
321          0xffff,                /* dst_mask */
322          false),                /* pcrel_offset */
323
324   EMPTY_HOWTO (8),
325   EMPTY_HOWTO (9),
326   EMPTY_HOWTO (10),
327   EMPTY_HOWTO (11),
328   EMPTY_HOWTO (12),
329   EMPTY_HOWTO (13),
330   EMPTY_HOWTO (14),
331   EMPTY_HOWTO (15),
332   EMPTY_HOWTO (16),
333   EMPTY_HOWTO (17),
334   EMPTY_HOWTO (18),
335   EMPTY_HOWTO (19),
336   EMPTY_HOWTO (20),
337   EMPTY_HOWTO (21),
338   EMPTY_HOWTO (22),
339   EMPTY_HOWTO (23),
340   EMPTY_HOWTO (24),
341   EMPTY_HOWTO (25),
342   EMPTY_HOWTO (26),
343   EMPTY_HOWTO (27),
344   EMPTY_HOWTO (28),
345   EMPTY_HOWTO (29),
346   EMPTY_HOWTO (30),
347   EMPTY_HOWTO (31),
348   EMPTY_HOWTO (32),
349   EMPTY_HOWTO (33),
350   HOWTO (MIPS_R_RVA,            /* type */
351          0,                     /* rightshift */
352          2,                     /* size (0 = byte, 1 = short, 2 = long) */
353          32,                    /* bitsize */
354          false,                 /* pc_relative */
355          0,                     /* bitpos */
356          complain_overflow_bitfield, /* complain_on_overflow */
357          coff_mips_reloc,       /* special_function */
358          "rva32",               /* name */
359          true,                  /* partial_inplace */
360          0xffffffff,            /* src_mask */
361          0xffffffff,            /* dst_mask */
362          false),                /* pcrel_offset */
363   EMPTY_HOWTO (35),
364   EMPTY_HOWTO (36),
365   HOWTO (MIPS_R_PAIR,           /* type */
366          0,                     /* rightshift */
367          2,                     /* size (0 = byte, 1 = short, 2 = long) */
368          32,                    /* bitsize */
369          false,                 /* pc_relative */
370          0,                     /* bitpos */
371          complain_overflow_bitfield, /* complain_on_overflow */
372          coff_mips_reloc,       /* special_function */
373          "PAIR",                /* name */
374          true,                  /* partial_inplace */
375          0xffffffff,            /* src_mask */
376          0xffffffff,            /* dst_mask */
377          false),                /* pcrel_offset */
378 };
379
380 /* Turn a howto into a reloc  nunmber */
381
382 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
383 #define BADMAG(x) MIPSBADMAG(x)
384 #define MIPS 1                  /* Customize coffcode.h */
385
386 #define RTYPE2HOWTO(cache_ptr, dst) \
387             (cache_ptr)->howto = howto_table + (dst)->r_type;
388
389 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
390    the object file contains the value of the common symbol.  By the
391    time this is called, the linker may be using a different symbol
392    from a different object file with a different value.  Therefore, we
393    hack wildly to locate the original symbol from this file so that we
394    can make the correct adjustment.  This macro sets coffsym to the
395    symbol from the original file, and uses it to set the addend value
396    correctly.  If this is not a common symbol, the usual addend
397    calculation is done, except that an additional tweak is needed for
398    PC relative relocs.
399    FIXME: This macro refers to symbols and asect; these are from the
400    calling function, not the macro arguments.  */
401
402 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
403   {                                                             \
404     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
405     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
406       coffsym = (obj_symbols (abfd)                             \
407                  + (cache_ptr->sym_ptr_ptr - symbols));         \
408     else if (ptr)                                               \
409       coffsym = coff_symbol_from (abfd, ptr);                   \
410     if (coffsym != (coff_symbol_type *) NULL                    \
411         && coffsym->native->u.syment.n_scnum == 0)              \
412       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
413     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
414              && ptr->section != (asection *) NULL)              \
415       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
416     else                                                        \
417       cache_ptr->addend = 0;                                    \
418     if (ptr && howto_table[reloc.r_type].pc_relative)           \
419       cache_ptr->addend += asect->vma;                          \
420   }
421
422 /* Convert an rtype to howto for the COFF backend linker.  */
423
424 static reloc_howto_type *
425 coff_mips_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
426      bfd *abfd ATTRIBUTE_UNUSED;
427      asection *sec;
428      struct internal_reloc *rel;
429      struct coff_link_hash_entry *h;
430      struct internal_syment *sym;
431      bfd_vma *addendp;
432 {
433
434   reloc_howto_type *howto;
435
436   howto = howto_table + rel->r_type;
437
438 #ifdef COFF_WITH_PE
439   *addendp = 0;
440 #endif
441
442   if (howto->pc_relative)
443     *addendp += sec->vma;
444
445   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
446     {
447       /* This is a common symbol.  The section contents include the
448          size (sym->n_value) as an addend.  The relocate_section
449          function will be adding in the final value of the symbol.  We
450          need to subtract out the current size in order to get the
451          correct result.  */
452
453       BFD_ASSERT (h != NULL);
454
455 #ifndef COFF_WITH_PE
456       /* I think we *do* want to bypass this.  If we don't, I have
457          seen some data parameters get the wrong relocation address.
458          If I link two versions with and without this section bypassed
459          and then do a binary comparison, the addresses which are
460          different can be looked up in the map.  The case in which
461          this section has been bypassed has addresses which correspond
462          to values I can find in the map.  */
463       *addendp -= sym->n_value;
464 #endif
465     }
466
467 #ifndef COFF_WITH_PE
468   /* If the output symbol is common (in which case this must be a
469      relocateable link), we need to add in the final size of the
470      common symbol.  */
471   if (h != NULL && h->root.type == bfd_link_hash_common)
472     *addendp += h->root.u.c.size;
473 #endif
474
475 #ifdef COFF_WITH_PE
476   if (howto->pc_relative)
477     {
478       *addendp -= 4;
479
480       /* If the symbol is defined, then the generic code is going to
481          add back the symbol value in order to cancel out an
482          adjustment it made to the addend.  However, we set the addend
483          to 0 at the start of this function.  We need to adjust here,
484          to avoid the adjustment the generic code will make.  FIXME:
485          This is getting a bit hackish.  */
486       if (sym != NULL && sym->n_scnum != 0)
487         *addendp -= sym->n_value;
488     }
489
490   if (rel->r_type == MIPS_R_RVA)
491     {
492       *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
493     }
494 #endif
495
496   return howto;
497 }
498
499 #define coff_rtype_to_howto coff_mips_rtype_to_howto
500
501 #define coff_bfd_reloc_type_lookup coff_mips_reloc_type_lookup
502
503 /* Get the howto structure for a generic reloc type.  */
504
505 static reloc_howto_type *
506 coff_mips_reloc_type_lookup (abfd, code)
507      bfd *abfd ATTRIBUTE_UNUSED;
508      bfd_reloc_code_real_type code;
509 {
510   int mips_type;
511
512   switch (code)
513     {
514     case BFD_RELOC_16:
515       mips_type = MIPS_R_REFHALF;
516       break;
517     case BFD_RELOC_32:
518     case BFD_RELOC_CTOR:
519       mips_type = MIPS_R_REFWORD;
520       break;
521     case BFD_RELOC_MIPS_JMP:
522       mips_type = MIPS_R_JMPADDR;
523       break;
524     case BFD_RELOC_HI16_S:
525       mips_type = MIPS_R_REFHI;
526       break;
527     case BFD_RELOC_LO16:
528       mips_type = MIPS_R_REFLO;
529       break;
530     case BFD_RELOC_GPREL16:
531       mips_type = MIPS_R_GPREL;
532       break;
533     case BFD_RELOC_MIPS_LITERAL:
534       mips_type = MIPS_R_LITERAL;
535       break;
536 /* FIXME?
537     case BFD_RELOC_16_PCREL_S2:
538       mips_type = MIPS_R_PCREL16;
539       break;
540     case BFD_RELOC_PCREL_HI16_S:
541       mips_type = MIPS_R_RELHI;
542       break;
543     case BFD_RELOC_PCREL_LO16:
544       mips_type = MIPS_R_RELLO;
545       break;
546     case BFD_RELOC_GPREL32:
547       mips_type = MIPS_R_SWITCH;
548       break;
549 */
550     case BFD_RELOC_RVA:
551       mips_type = MIPS_R_RVA;
552       break;
553     default:
554       return (reloc_howto_type *) NULL;
555     }
556
557   return &howto_table[mips_type];
558 }
559
560 static void
561 mips_swap_reloc_in (abfd, src, dst)
562      bfd *abfd;
563      PTR src;
564      PTR dst;
565 {
566   static struct internal_reloc pair_prev;
567   RELOC *reloc_src = (RELOC *) src;
568   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
569
570   reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr);
571   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
572   reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type);
573   reloc_dst->r_size = 0;
574   reloc_dst->r_extern = 0;
575   reloc_dst->r_offset = 0;
576
577   switch (reloc_dst->r_type)
578   {
579   case MIPS_R_REFHI:
580     pair_prev = *reloc_dst;
581     break;
582   case MIPS_R_PAIR:
583     reloc_dst->r_offset = reloc_dst->r_symndx;
584     if (reloc_dst->r_offset & 0x8000)
585       reloc_dst->r_offset -= 0x10000;
586     /*printf ("dj: pair offset is %08x\n", reloc_dst->r_offset);*/
587     reloc_dst->r_symndx = pair_prev.r_symndx;
588     break;
589   }
590 }
591
592 static unsigned int
593 mips_swap_reloc_out (abfd, src, dst)
594      bfd       *abfd;
595      PTR        src;
596      PTR        dst;
597 {
598   static int prev_offset = 1;
599   static bfd_vma prev_addr = 0;
600   struct internal_reloc *reloc_src = (struct internal_reloc *)src;
601   struct external_reloc *reloc_dst = (struct external_reloc *)dst;
602
603   switch (reloc_src->r_type)
604     {
605     case MIPS_R_REFHI:
606       prev_addr = reloc_src->r_vaddr;
607       prev_offset = reloc_src->r_offset;
608       break;
609     case MIPS_R_REFLO:
610       if (reloc_src->r_vaddr == prev_addr)
611         {
612           /* FIXME: only slightly hackish.  If we see a REFLO pointing to
613              the same address as a REFHI, we assume this is the matching
614              PAIR reloc and output it accordingly.  The symndx is really
615              the low 16 bits of the addend */
616           H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
617           H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
618           H_PUT_16 (abfd, MIPS_R_PAIR, reloc_dst->r_type);
619           return RELSZ;
620         }
621       break;
622     }
623
624   H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
625   H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
626
627   H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
628   return RELSZ;
629 }
630
631 #define coff_swap_reloc_in mips_swap_reloc_in
632 #define coff_swap_reloc_out mips_swap_reloc_out
633 #define NO_COFF_RELOCS
634
635 static boolean
636 coff_pe_mips_relocate_section (output_bfd, info, input_bfd,
637                                input_section, contents, relocs, syms,
638                                sections)
639      bfd *output_bfd;
640      struct bfd_link_info *info;
641      bfd *input_bfd;
642      asection *input_section;
643      bfd_byte *contents;
644      struct internal_reloc *relocs;
645      struct internal_syment *syms;
646      asection **sections;
647 {
648   bfd_vma gp;
649   boolean gp_undefined;
650   size_t adjust;
651   struct internal_reloc *rel;
652   struct internal_reloc *rel_end;
653   unsigned int i;
654   boolean got_lo;
655
656   if (info->relocateable)
657   {
658     (*_bfd_error_handler) (_("\
659 %s: `ld -r' not supported with PE MIPS objects\n"),
660                            bfd_archive_filename (input_bfd));
661     bfd_set_error (bfd_error_bad_value);
662     return false;
663   }
664
665   BFD_ASSERT (input_bfd->xvec->byteorder
666               == output_bfd->xvec->byteorder);
667
668 #if 0
669   printf ("dj: relocate %s(%s) %08x\n",
670          input_bfd->filename, input_section->name,
671          input_section->output_section->vma + input_section->output_offset);
672 #endif
673
674   gp = _bfd_get_gp_value (output_bfd);
675   if (gp == 0)
676     gp_undefined = true;
677   else
678     gp_undefined = false;
679
680   got_lo = false;
681
682   adjust = 0;
683
684   rel = relocs;
685   rel_end = rel + input_section->reloc_count;
686   for (i = 0; rel < rel_end; rel++, i++)
687     {
688       long symndx;
689       struct coff_link_hash_entry *h;
690       struct internal_syment *sym;
691       bfd_vma addend = 0;
692       bfd_vma val, tmp, targ, src, low;
693       reloc_howto_type *howto;
694       unsigned char *mem = contents + rel->r_vaddr;
695
696       symndx = rel->r_symndx;
697
698       if (symndx == -1)
699         {
700           h = NULL;
701           sym = NULL;
702         }
703       else
704         {
705           h = obj_coff_sym_hashes (input_bfd)[symndx];
706           sym = syms + symndx;
707         }
708
709       /* COFF treats common symbols in one of two ways.  Either the
710          size of the symbol is included in the section contents, or it
711          is not.  We assume that the size is not included, and force
712          the rtype_to_howto function to adjust the addend as needed.  */
713
714       if (sym != NULL && sym->n_scnum != 0)
715         addend = - sym->n_value;
716       else
717         addend = 0;
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_archive_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_archive_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_archive_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 };