xref: /openbsd-src/gnu/usr.bin/binutils/bfd/pe-mips.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
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 };
999