xref: /freebsd-11-stable/contrib/binutils/bfd/pe-mips.c (revision ce8fb931782e66cb56f7bfb4cff1ac032fc57076)
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 
48 static bfd_reloc_status_type
coff_mips_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)49 coff_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 
139 static bfd_boolean
in_reloc_p(bfd * abfd ATTRIBUTE_UNUSED,reloc_howto_type * howto)140 in_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 
150 static 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 
382 static reloc_howto_type *
coff_mips_rtype_to_howto(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,struct internal_reloc * rel,struct coff_link_hash_entry * h,struct internal_syment * sym,bfd_vma * addendp)383 coff_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 
460 static reloc_howto_type *
coff_mips_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)461 coff_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 
500 static reloc_howto_type *
coff_mips_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)501 coff_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 
516 static void
mips_swap_reloc_in(bfd * abfd,void * src,void * dst)517 mips_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 
544 static unsigned int
mips_swap_reloc_out(bfd * abfd,void * src,void * dst)545 mips_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 
584 static bfd_boolean
coff_pe_mips_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,struct internal_reloc * relocs,struct internal_syment * syms,asection ** sections)585 coff_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 
838 static bfd_boolean
coff_mips_is_local_label_name(bfd * abfd,const char * name)839 coff_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 
855 const 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