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