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