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