xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/coff-mips.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* BFD back-end for MIPS Extended-Coff files.
2*3d8817e4Smiod    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3*3d8817e4Smiod    2000, 2001, 2002, 2003, 2004
4*3d8817e4Smiod    Free Software Foundation, Inc.
5*3d8817e4Smiod    Original version by Per Bothner.
6*3d8817e4Smiod    Full support added by Ian Lance Taylor, ian@cygnus.com.
7*3d8817e4Smiod 
8*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
9*3d8817e4Smiod 
10*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
11*3d8817e4Smiod it under the terms of the GNU General Public License as published by
12*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
13*3d8817e4Smiod (at your option) any later version.
14*3d8817e4Smiod 
15*3d8817e4Smiod This program is distributed in the hope that it will be useful,
16*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
17*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*3d8817e4Smiod GNU General Public License for more details.
19*3d8817e4Smiod 
20*3d8817e4Smiod You should have received a copy of the GNU General Public License
21*3d8817e4Smiod along with this program; if not, write to the Free Software
22*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
23*3d8817e4Smiod 
24*3d8817e4Smiod #include "bfd.h"
25*3d8817e4Smiod #include "sysdep.h"
26*3d8817e4Smiod #include "bfdlink.h"
27*3d8817e4Smiod #include "libbfd.h"
28*3d8817e4Smiod #include "coff/internal.h"
29*3d8817e4Smiod #include "coff/sym.h"
30*3d8817e4Smiod #include "coff/symconst.h"
31*3d8817e4Smiod #include "coff/ecoff.h"
32*3d8817e4Smiod #include "coff/mips.h"
33*3d8817e4Smiod #include "libcoff.h"
34*3d8817e4Smiod #include "libecoff.h"
35*3d8817e4Smiod 
36*3d8817e4Smiod /* Prototypes for static functions.  */
37*3d8817e4Smiod 
38*3d8817e4Smiod static bfd_boolean mips_ecoff_bad_format_hook
39*3d8817e4Smiod   PARAMS ((bfd *abfd, PTR filehdr));
40*3d8817e4Smiod static void mips_ecoff_swap_reloc_in
41*3d8817e4Smiod   PARAMS ((bfd *, PTR, struct internal_reloc *));
42*3d8817e4Smiod static void mips_ecoff_swap_reloc_out
43*3d8817e4Smiod   PARAMS ((bfd *, const struct internal_reloc *, PTR));
44*3d8817e4Smiod static void mips_adjust_reloc_in
45*3d8817e4Smiod   PARAMS ((bfd *, const struct internal_reloc *, arelent *));
46*3d8817e4Smiod static void mips_adjust_reloc_out
47*3d8817e4Smiod   PARAMS ((bfd *, const arelent *, struct internal_reloc *));
48*3d8817e4Smiod static bfd_reloc_status_type mips_generic_reloc
49*3d8817e4Smiod   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
50*3d8817e4Smiod 	   asection *section, bfd *output_bfd, char **error));
51*3d8817e4Smiod static bfd_reloc_status_type mips_refhi_reloc
52*3d8817e4Smiod   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
53*3d8817e4Smiod 	   asection *section, bfd *output_bfd, char **error));
54*3d8817e4Smiod static bfd_reloc_status_type mips_reflo_reloc
55*3d8817e4Smiod   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
56*3d8817e4Smiod 	   asection *section, bfd *output_bfd, char **error));
57*3d8817e4Smiod static bfd_reloc_status_type mips_gprel_reloc
58*3d8817e4Smiod   PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
59*3d8817e4Smiod 	   asection *section, bfd *output_bfd, char **error));
60*3d8817e4Smiod static void mips_relocate_hi
61*3d8817e4Smiod   PARAMS ((struct internal_reloc *refhi, struct internal_reloc *reflo,
62*3d8817e4Smiod 	   bfd *input_bfd, asection *input_section, bfd_byte *contents,
63*3d8817e4Smiod 	   bfd_vma relocation));
64*3d8817e4Smiod static bfd_boolean mips_relocate_section
65*3d8817e4Smiod   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));
66*3d8817e4Smiod static reloc_howto_type *mips_bfd_reloc_type_lookup
67*3d8817e4Smiod   PARAMS ((bfd *, bfd_reloc_code_real_type));
68*3d8817e4Smiod 
69*3d8817e4Smiod /* ECOFF has COFF sections, but the debugging information is stored in
70*3d8817e4Smiod    a completely different format.  ECOFF targets use some of the
71*3d8817e4Smiod    swapping routines from coffswap.h, and some of the generic COFF
72*3d8817e4Smiod    routines in coffgen.c, but, unlike the real COFF targets, do not
73*3d8817e4Smiod    use coffcode.h itself.
74*3d8817e4Smiod 
75*3d8817e4Smiod    Get the generic COFF swapping routines, except for the reloc,
76*3d8817e4Smiod    symbol, and lineno ones.  Give them ECOFF names.  */
77*3d8817e4Smiod #define MIPSECOFF
78*3d8817e4Smiod #define NO_COFF_RELOCS
79*3d8817e4Smiod #define NO_COFF_SYMBOLS
80*3d8817e4Smiod #define NO_COFF_LINENOS
81*3d8817e4Smiod #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
82*3d8817e4Smiod #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
83*3d8817e4Smiod #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
84*3d8817e4Smiod #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
85*3d8817e4Smiod #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
86*3d8817e4Smiod #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
87*3d8817e4Smiod #include "coffswap.h"
88*3d8817e4Smiod 
89*3d8817e4Smiod /* Get the ECOFF swapping routines.  */
90*3d8817e4Smiod #define ECOFF_32
91*3d8817e4Smiod #include "ecoffswap.h"
92*3d8817e4Smiod 
93*3d8817e4Smiod /* How to process the various relocs types.  */
94*3d8817e4Smiod 
95*3d8817e4Smiod static reloc_howto_type mips_howto_table[] =
96*3d8817e4Smiod {
97*3d8817e4Smiod   /* Reloc type 0 is ignored.  The reloc reading code ensures that
98*3d8817e4Smiod      this is a reference to the .abs section, which will cause
99*3d8817e4Smiod      bfd_perform_relocation to do nothing.  */
100*3d8817e4Smiod   HOWTO (MIPS_R_IGNORE,	/* type */
101*3d8817e4Smiod 	 0,			/* rightshift */
102*3d8817e4Smiod 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
103*3d8817e4Smiod 	 8,			/* bitsize */
104*3d8817e4Smiod 	 FALSE,			/* pc_relative */
105*3d8817e4Smiod 	 0,			/* bitpos */
106*3d8817e4Smiod 	 complain_overflow_dont, /* complain_on_overflow */
107*3d8817e4Smiod 	 0,			/* special_function */
108*3d8817e4Smiod 	 "IGNORE",		/* name */
109*3d8817e4Smiod 	 FALSE,			/* partial_inplace */
110*3d8817e4Smiod 	 0,			/* src_mask */
111*3d8817e4Smiod 	 0,			/* dst_mask */
112*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
113*3d8817e4Smiod 
114*3d8817e4Smiod   /* A 16 bit reference to a symbol, normally from a data section.  */
115*3d8817e4Smiod   HOWTO (MIPS_R_REFHALF,	/* type */
116*3d8817e4Smiod 	 0,			/* rightshift */
117*3d8817e4Smiod 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
118*3d8817e4Smiod 	 16,			/* bitsize */
119*3d8817e4Smiod 	 FALSE,			/* pc_relative */
120*3d8817e4Smiod 	 0,			/* bitpos */
121*3d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
122*3d8817e4Smiod 	 mips_generic_reloc,	/* special_function */
123*3d8817e4Smiod 	 "REFHALF",		/* name */
124*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
125*3d8817e4Smiod 	 0xffff,		/* src_mask */
126*3d8817e4Smiod 	 0xffff,		/* dst_mask */
127*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
128*3d8817e4Smiod 
129*3d8817e4Smiod   /* A 32 bit reference to a symbol, normally from a data section.  */
130*3d8817e4Smiod   HOWTO (MIPS_R_REFWORD,	/* type */
131*3d8817e4Smiod 	 0,			/* rightshift */
132*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
133*3d8817e4Smiod 	 32,			/* bitsize */
134*3d8817e4Smiod 	 FALSE,			/* pc_relative */
135*3d8817e4Smiod 	 0,			/* bitpos */
136*3d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
137*3d8817e4Smiod 	 mips_generic_reloc,	/* special_function */
138*3d8817e4Smiod 	 "REFWORD",		/* name */
139*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
140*3d8817e4Smiod 	 0xffffffff,		/* src_mask */
141*3d8817e4Smiod 	 0xffffffff,		/* dst_mask */
142*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
143*3d8817e4Smiod 
144*3d8817e4Smiod   /* A 26 bit absolute jump address.  */
145*3d8817e4Smiod   HOWTO (MIPS_R_JMPADDR,	/* type */
146*3d8817e4Smiod 	 2,			/* rightshift */
147*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
148*3d8817e4Smiod 	 26,			/* bitsize */
149*3d8817e4Smiod 	 FALSE,			/* pc_relative */
150*3d8817e4Smiod 	 0,			/* bitpos */
151*3d8817e4Smiod 	 complain_overflow_dont, /* complain_on_overflow */
152*3d8817e4Smiod 	 			/* This needs complex overflow
153*3d8817e4Smiod 				   detection, because the upper four
154*3d8817e4Smiod 				   bits must match the PC.  */
155*3d8817e4Smiod 	 mips_generic_reloc,	/* special_function */
156*3d8817e4Smiod 	 "JMPADDR",		/* name */
157*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
158*3d8817e4Smiod 	 0x3ffffff,		/* src_mask */
159*3d8817e4Smiod 	 0x3ffffff,		/* dst_mask */
160*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
161*3d8817e4Smiod 
162*3d8817e4Smiod   /* The high 16 bits of a symbol value.  Handled by the function
163*3d8817e4Smiod      mips_refhi_reloc.  */
164*3d8817e4Smiod   HOWTO (MIPS_R_REFHI,		/* type */
165*3d8817e4Smiod 	 16,			/* rightshift */
166*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
167*3d8817e4Smiod 	 16,			/* bitsize */
168*3d8817e4Smiod 	 FALSE,			/* pc_relative */
169*3d8817e4Smiod 	 0,			/* bitpos */
170*3d8817e4Smiod 	 complain_overflow_bitfield, /* complain_on_overflow */
171*3d8817e4Smiod 	 mips_refhi_reloc,	/* special_function */
172*3d8817e4Smiod 	 "REFHI",		/* name */
173*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
174*3d8817e4Smiod 	 0xffff,		/* src_mask */
175*3d8817e4Smiod 	 0xffff,		/* dst_mask */
176*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
177*3d8817e4Smiod 
178*3d8817e4Smiod   /* The low 16 bits of a symbol value.  */
179*3d8817e4Smiod   HOWTO (MIPS_R_REFLO,		/* type */
180*3d8817e4Smiod 	 0,			/* rightshift */
181*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
182*3d8817e4Smiod 	 16,			/* bitsize */
183*3d8817e4Smiod 	 FALSE,			/* pc_relative */
184*3d8817e4Smiod 	 0,			/* bitpos */
185*3d8817e4Smiod 	 complain_overflow_dont, /* complain_on_overflow */
186*3d8817e4Smiod 	 mips_reflo_reloc,	/* special_function */
187*3d8817e4Smiod 	 "REFLO",		/* name */
188*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
189*3d8817e4Smiod 	 0xffff,		/* src_mask */
190*3d8817e4Smiod 	 0xffff,		/* dst_mask */
191*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
192*3d8817e4Smiod 
193*3d8817e4Smiod   /* A reference to an offset from the gp register.  Handled by the
194*3d8817e4Smiod      function mips_gprel_reloc.  */
195*3d8817e4Smiod   HOWTO (MIPS_R_GPREL,		/* type */
196*3d8817e4Smiod 	 0,			/* rightshift */
197*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
198*3d8817e4Smiod 	 16,			/* bitsize */
199*3d8817e4Smiod 	 FALSE,			/* pc_relative */
200*3d8817e4Smiod 	 0,			/* bitpos */
201*3d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
202*3d8817e4Smiod 	 mips_gprel_reloc,	/* special_function */
203*3d8817e4Smiod 	 "GPREL",		/* name */
204*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
205*3d8817e4Smiod 	 0xffff,		/* src_mask */
206*3d8817e4Smiod 	 0xffff,		/* dst_mask */
207*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
208*3d8817e4Smiod 
209*3d8817e4Smiod   /* A reference to a literal using an offset from the gp register.
210*3d8817e4Smiod      Handled by the function mips_gprel_reloc.  */
211*3d8817e4Smiod   HOWTO (MIPS_R_LITERAL,	/* type */
212*3d8817e4Smiod 	 0,			/* rightshift */
213*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
214*3d8817e4Smiod 	 16,			/* bitsize */
215*3d8817e4Smiod 	 FALSE,			/* pc_relative */
216*3d8817e4Smiod 	 0,			/* bitpos */
217*3d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
218*3d8817e4Smiod 	 mips_gprel_reloc,	/* special_function */
219*3d8817e4Smiod 	 "LITERAL",		/* name */
220*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
221*3d8817e4Smiod 	 0xffff,		/* src_mask */
222*3d8817e4Smiod 	 0xffff,		/* dst_mask */
223*3d8817e4Smiod 	 FALSE),		/* pcrel_offset */
224*3d8817e4Smiod 
225*3d8817e4Smiod   EMPTY_HOWTO (8),
226*3d8817e4Smiod   EMPTY_HOWTO (9),
227*3d8817e4Smiod   EMPTY_HOWTO (10),
228*3d8817e4Smiod   EMPTY_HOWTO (11),
229*3d8817e4Smiod 
230*3d8817e4Smiod   /* FIXME: This relocation is used (internally only) to represent branches
231*3d8817e4Smiod      when assembling.  It should never appear in output files, and
232*3d8817e4Smiod      be removed.  (It used to be used for embedded-PIC support.)  */
233*3d8817e4Smiod   HOWTO (MIPS_R_PCREL16,	/* type */
234*3d8817e4Smiod 	 2,			/* rightshift */
235*3d8817e4Smiod 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
236*3d8817e4Smiod 	 16,			/* bitsize */
237*3d8817e4Smiod 	 TRUE,			/* pc_relative */
238*3d8817e4Smiod 	 0,			/* bitpos */
239*3d8817e4Smiod 	 complain_overflow_signed, /* complain_on_overflow */
240*3d8817e4Smiod 	 mips_generic_reloc,	/* special_function */
241*3d8817e4Smiod 	 "PCREL16",		/* name */
242*3d8817e4Smiod 	 TRUE,			/* partial_inplace */
243*3d8817e4Smiod 	 0xffff,		/* src_mask */
244*3d8817e4Smiod 	 0xffff,		/* dst_mask */
245*3d8817e4Smiod 	 TRUE),			/* pcrel_offset */
246*3d8817e4Smiod };
247*3d8817e4Smiod 
248*3d8817e4Smiod #define MIPS_HOWTO_COUNT \
249*3d8817e4Smiod   (sizeof mips_howto_table / sizeof mips_howto_table[0])
250*3d8817e4Smiod 
251*3d8817e4Smiod /* See whether the magic number matches.  */
252*3d8817e4Smiod 
253*3d8817e4Smiod static bfd_boolean
mips_ecoff_bad_format_hook(abfd,filehdr)254*3d8817e4Smiod mips_ecoff_bad_format_hook (abfd, filehdr)
255*3d8817e4Smiod      bfd *abfd;
256*3d8817e4Smiod      PTR filehdr;
257*3d8817e4Smiod {
258*3d8817e4Smiod   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
259*3d8817e4Smiod 
260*3d8817e4Smiod   switch (internal_f->f_magic)
261*3d8817e4Smiod     {
262*3d8817e4Smiod     case MIPS_MAGIC_1:
263*3d8817e4Smiod       /* I don't know what endianness this implies.  */
264*3d8817e4Smiod       return TRUE;
265*3d8817e4Smiod 
266*3d8817e4Smiod     case MIPS_MAGIC_BIG:
267*3d8817e4Smiod     case MIPS_MAGIC_BIG2:
268*3d8817e4Smiod     case MIPS_MAGIC_BIG3:
269*3d8817e4Smiod       return bfd_big_endian (abfd);
270*3d8817e4Smiod 
271*3d8817e4Smiod     case MIPS_MAGIC_LITTLE:
272*3d8817e4Smiod     case MIPS_MAGIC_LITTLE2:
273*3d8817e4Smiod     case MIPS_MAGIC_LITTLE3:
274*3d8817e4Smiod       return bfd_little_endian (abfd);
275*3d8817e4Smiod 
276*3d8817e4Smiod     default:
277*3d8817e4Smiod       return FALSE;
278*3d8817e4Smiod     }
279*3d8817e4Smiod }
280*3d8817e4Smiod 
281*3d8817e4Smiod /* Reloc handling.  MIPS ECOFF relocs are packed into 8 bytes in
282*3d8817e4Smiod    external form.  They use a bit which indicates whether the symbol
283*3d8817e4Smiod    is external.  */
284*3d8817e4Smiod 
285*3d8817e4Smiod /* Swap a reloc in.  */
286*3d8817e4Smiod 
287*3d8817e4Smiod static void
mips_ecoff_swap_reloc_in(abfd,ext_ptr,intern)288*3d8817e4Smiod mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
289*3d8817e4Smiod      bfd *abfd;
290*3d8817e4Smiod      PTR ext_ptr;
291*3d8817e4Smiod      struct internal_reloc *intern;
292*3d8817e4Smiod {
293*3d8817e4Smiod   const RELOC *ext = (RELOC *) ext_ptr;
294*3d8817e4Smiod 
295*3d8817e4Smiod   intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
296*3d8817e4Smiod   if (bfd_header_big_endian (abfd))
297*3d8817e4Smiod     {
298*3d8817e4Smiod       intern->r_symndx = (((int) ext->r_bits[0]
299*3d8817e4Smiod 			   << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
300*3d8817e4Smiod 			  | ((int) ext->r_bits[1]
301*3d8817e4Smiod 			     << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
302*3d8817e4Smiod 			  | ((int) ext->r_bits[2]
303*3d8817e4Smiod 			     << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
304*3d8817e4Smiod       intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
305*3d8817e4Smiod 			>> RELOC_BITS3_TYPE_SH_BIG);
306*3d8817e4Smiod       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
307*3d8817e4Smiod     }
308*3d8817e4Smiod   else
309*3d8817e4Smiod     {
310*3d8817e4Smiod       intern->r_symndx = (((int) ext->r_bits[0]
311*3d8817e4Smiod 			   << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
312*3d8817e4Smiod 			  | ((int) ext->r_bits[1]
313*3d8817e4Smiod 			     << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
314*3d8817e4Smiod 			  | ((int) ext->r_bits[2]
315*3d8817e4Smiod 			     << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
316*3d8817e4Smiod       intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
317*3d8817e4Smiod 			 >> RELOC_BITS3_TYPE_SH_LITTLE)
318*3d8817e4Smiod 			| ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
319*3d8817e4Smiod 			   << RELOC_BITS3_TYPEHI_SH_LITTLE));
320*3d8817e4Smiod       intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
321*3d8817e4Smiod     }
322*3d8817e4Smiod }
323*3d8817e4Smiod 
324*3d8817e4Smiod /* Swap a reloc out.  */
325*3d8817e4Smiod 
326*3d8817e4Smiod static void
mips_ecoff_swap_reloc_out(abfd,intern,dst)327*3d8817e4Smiod mips_ecoff_swap_reloc_out (abfd, intern, dst)
328*3d8817e4Smiod      bfd *abfd;
329*3d8817e4Smiod      const struct internal_reloc *intern;
330*3d8817e4Smiod      PTR dst;
331*3d8817e4Smiod {
332*3d8817e4Smiod   RELOC *ext = (RELOC *) dst;
333*3d8817e4Smiod   long r_symndx;
334*3d8817e4Smiod 
335*3d8817e4Smiod   BFD_ASSERT (intern->r_extern
336*3d8817e4Smiod 	      || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
337*3d8817e4Smiod 
338*3d8817e4Smiod   r_symndx = intern->r_symndx;
339*3d8817e4Smiod 
340*3d8817e4Smiod   H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
341*3d8817e4Smiod   if (bfd_header_big_endian (abfd))
342*3d8817e4Smiod     {
343*3d8817e4Smiod       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
344*3d8817e4Smiod       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
345*3d8817e4Smiod       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
346*3d8817e4Smiod       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
347*3d8817e4Smiod 			 & RELOC_BITS3_TYPE_BIG)
348*3d8817e4Smiod 			| (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
349*3d8817e4Smiod     }
350*3d8817e4Smiod   else
351*3d8817e4Smiod     {
352*3d8817e4Smiod       ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
353*3d8817e4Smiod       ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
354*3d8817e4Smiod       ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
355*3d8817e4Smiod       ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
356*3d8817e4Smiod 			 & RELOC_BITS3_TYPE_LITTLE)
357*3d8817e4Smiod 			| ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
358*3d8817e4Smiod 			    & RELOC_BITS3_TYPEHI_LITTLE))
359*3d8817e4Smiod 			| (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
360*3d8817e4Smiod     }
361*3d8817e4Smiod }
362*3d8817e4Smiod 
363*3d8817e4Smiod /* Finish canonicalizing a reloc.  Part of this is generic to all
364*3d8817e4Smiod    ECOFF targets, and that part is in ecoff.c.  The rest is done in
365*3d8817e4Smiod    this backend routine.  It must fill in the howto field.  */
366*3d8817e4Smiod 
367*3d8817e4Smiod static void
mips_adjust_reloc_in(abfd,intern,rptr)368*3d8817e4Smiod mips_adjust_reloc_in (abfd, intern, rptr)
369*3d8817e4Smiod      bfd *abfd;
370*3d8817e4Smiod      const struct internal_reloc *intern;
371*3d8817e4Smiod      arelent *rptr;
372*3d8817e4Smiod {
373*3d8817e4Smiod   if (intern->r_type > MIPS_R_PCREL16)
374*3d8817e4Smiod     abort ();
375*3d8817e4Smiod 
376*3d8817e4Smiod   if (! intern->r_extern
377*3d8817e4Smiod       && (intern->r_type == MIPS_R_GPREL
378*3d8817e4Smiod 	  || intern->r_type == MIPS_R_LITERAL))
379*3d8817e4Smiod     rptr->addend += ecoff_data (abfd)->gp;
380*3d8817e4Smiod 
381*3d8817e4Smiod   /* If the type is MIPS_R_IGNORE, make sure this is a reference to
382*3d8817e4Smiod      the absolute section so that the reloc is ignored.  */
383*3d8817e4Smiod   if (intern->r_type == MIPS_R_IGNORE)
384*3d8817e4Smiod     rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
385*3d8817e4Smiod 
386*3d8817e4Smiod   rptr->howto = &mips_howto_table[intern->r_type];
387*3d8817e4Smiod }
388*3d8817e4Smiod 
389*3d8817e4Smiod /* Make any adjustments needed to a reloc before writing it out.  None
390*3d8817e4Smiod    are needed for MIPS.  */
391*3d8817e4Smiod 
392*3d8817e4Smiod static void
mips_adjust_reloc_out(abfd,rel,intern)393*3d8817e4Smiod mips_adjust_reloc_out (abfd, rel, intern)
394*3d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
395*3d8817e4Smiod      const arelent *rel ATTRIBUTE_UNUSED;
396*3d8817e4Smiod      struct internal_reloc *intern ATTRIBUTE_UNUSED;
397*3d8817e4Smiod {
398*3d8817e4Smiod }
399*3d8817e4Smiod 
400*3d8817e4Smiod /* ECOFF relocs are either against external symbols, or against
401*3d8817e4Smiod    sections.  If we are producing relocatable output, and the reloc
402*3d8817e4Smiod    is against an external symbol, and nothing has given us any
403*3d8817e4Smiod    additional addend, the resulting reloc will also be against the
404*3d8817e4Smiod    same symbol.  In such a case, we don't want to change anything
405*3d8817e4Smiod    about the way the reloc is handled, since it will all be done at
406*3d8817e4Smiod    final link time.  Rather than put special case code into
407*3d8817e4Smiod    bfd_perform_relocation, all the reloc types use this howto
408*3d8817e4Smiod    function.  It just short circuits the reloc if producing
409*3d8817e4Smiod    relocatable output against an external symbol.  */
410*3d8817e4Smiod 
411*3d8817e4Smiod static bfd_reloc_status_type
mips_generic_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)412*3d8817e4Smiod mips_generic_reloc (abfd,
413*3d8817e4Smiod 		    reloc_entry,
414*3d8817e4Smiod 		    symbol,
415*3d8817e4Smiod 		    data,
416*3d8817e4Smiod 		    input_section,
417*3d8817e4Smiod 		    output_bfd,
418*3d8817e4Smiod 		    error_message)
419*3d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
420*3d8817e4Smiod      arelent *reloc_entry;
421*3d8817e4Smiod      asymbol *symbol;
422*3d8817e4Smiod      PTR data ATTRIBUTE_UNUSED;
423*3d8817e4Smiod      asection *input_section;
424*3d8817e4Smiod      bfd *output_bfd;
425*3d8817e4Smiod      char **error_message ATTRIBUTE_UNUSED;
426*3d8817e4Smiod {
427*3d8817e4Smiod   if (output_bfd != (bfd *) NULL
428*3d8817e4Smiod       && (symbol->flags & BSF_SECTION_SYM) == 0
429*3d8817e4Smiod       && reloc_entry->addend == 0)
430*3d8817e4Smiod     {
431*3d8817e4Smiod       reloc_entry->address += input_section->output_offset;
432*3d8817e4Smiod       return bfd_reloc_ok;
433*3d8817e4Smiod     }
434*3d8817e4Smiod 
435*3d8817e4Smiod   return bfd_reloc_continue;
436*3d8817e4Smiod }
437*3d8817e4Smiod 
438*3d8817e4Smiod /* Do a REFHI relocation.  This has to be done in combination with a
439*3d8817e4Smiod    REFLO reloc, because there is a carry from the REFLO to the REFHI.
440*3d8817e4Smiod    Here we just save the information we need; we do the actual
441*3d8817e4Smiod    relocation when we see the REFLO.  MIPS ECOFF requires that the
442*3d8817e4Smiod    REFLO immediately follow the REFHI.  As a GNU extension, we permit
443*3d8817e4Smiod    an arbitrary number of HI relocs to be associated with a single LO
444*3d8817e4Smiod    reloc.  This extension permits gcc to output the HI and LO relocs
445*3d8817e4Smiod    itself.  */
446*3d8817e4Smiod 
447*3d8817e4Smiod struct mips_hi
448*3d8817e4Smiod {
449*3d8817e4Smiod   struct mips_hi *next;
450*3d8817e4Smiod   bfd_byte *addr;
451*3d8817e4Smiod   bfd_vma addend;
452*3d8817e4Smiod };
453*3d8817e4Smiod 
454*3d8817e4Smiod /* FIXME: This should not be a static variable.  */
455*3d8817e4Smiod 
456*3d8817e4Smiod static struct mips_hi *mips_refhi_list;
457*3d8817e4Smiod 
458*3d8817e4Smiod static bfd_reloc_status_type
mips_refhi_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)459*3d8817e4Smiod mips_refhi_reloc (abfd,
460*3d8817e4Smiod 		  reloc_entry,
461*3d8817e4Smiod 		  symbol,
462*3d8817e4Smiod 		  data,
463*3d8817e4Smiod 		  input_section,
464*3d8817e4Smiod 		  output_bfd,
465*3d8817e4Smiod 		  error_message)
466*3d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
467*3d8817e4Smiod      arelent *reloc_entry;
468*3d8817e4Smiod      asymbol *symbol;
469*3d8817e4Smiod      PTR data;
470*3d8817e4Smiod      asection *input_section;
471*3d8817e4Smiod      bfd *output_bfd;
472*3d8817e4Smiod      char **error_message ATTRIBUTE_UNUSED;
473*3d8817e4Smiod {
474*3d8817e4Smiod   bfd_reloc_status_type ret;
475*3d8817e4Smiod   bfd_vma relocation;
476*3d8817e4Smiod   struct mips_hi *n;
477*3d8817e4Smiod 
478*3d8817e4Smiod   /* If we're relocating, and this an external symbol, we don't want
479*3d8817e4Smiod      to change anything.  */
480*3d8817e4Smiod   if (output_bfd != (bfd *) NULL
481*3d8817e4Smiod       && (symbol->flags & BSF_SECTION_SYM) == 0
482*3d8817e4Smiod       && reloc_entry->addend == 0)
483*3d8817e4Smiod     {
484*3d8817e4Smiod       reloc_entry->address += input_section->output_offset;
485*3d8817e4Smiod       return bfd_reloc_ok;
486*3d8817e4Smiod     }
487*3d8817e4Smiod 
488*3d8817e4Smiod   ret = bfd_reloc_ok;
489*3d8817e4Smiod   if (bfd_is_und_section (symbol->section)
490*3d8817e4Smiod       && output_bfd == (bfd *) NULL)
491*3d8817e4Smiod     ret = bfd_reloc_undefined;
492*3d8817e4Smiod 
493*3d8817e4Smiod   if (bfd_is_com_section (symbol->section))
494*3d8817e4Smiod     relocation = 0;
495*3d8817e4Smiod   else
496*3d8817e4Smiod     relocation = symbol->value;
497*3d8817e4Smiod 
498*3d8817e4Smiod   relocation += symbol->section->output_section->vma;
499*3d8817e4Smiod   relocation += symbol->section->output_offset;
500*3d8817e4Smiod   relocation += reloc_entry->addend;
501*3d8817e4Smiod 
502*3d8817e4Smiod   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
503*3d8817e4Smiod     return bfd_reloc_outofrange;
504*3d8817e4Smiod 
505*3d8817e4Smiod   /* Save the information, and let REFLO do the actual relocation.  */
506*3d8817e4Smiod   n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
507*3d8817e4Smiod   if (n == NULL)
508*3d8817e4Smiod     return bfd_reloc_outofrange;
509*3d8817e4Smiod   n->addr = (bfd_byte *) data + reloc_entry->address;
510*3d8817e4Smiod   n->addend = relocation;
511*3d8817e4Smiod   n->next = mips_refhi_list;
512*3d8817e4Smiod   mips_refhi_list = n;
513*3d8817e4Smiod 
514*3d8817e4Smiod   if (output_bfd != (bfd *) NULL)
515*3d8817e4Smiod     reloc_entry->address += input_section->output_offset;
516*3d8817e4Smiod 
517*3d8817e4Smiod   return ret;
518*3d8817e4Smiod }
519*3d8817e4Smiod 
520*3d8817e4Smiod /* Do a REFLO relocation.  This is a straightforward 16 bit inplace
521*3d8817e4Smiod    relocation; this function exists in order to do the REFHI
522*3d8817e4Smiod    relocation described above.  */
523*3d8817e4Smiod 
524*3d8817e4Smiod static bfd_reloc_status_type
mips_reflo_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)525*3d8817e4Smiod mips_reflo_reloc (abfd,
526*3d8817e4Smiod 		  reloc_entry,
527*3d8817e4Smiod 		  symbol,
528*3d8817e4Smiod 		  data,
529*3d8817e4Smiod 		  input_section,
530*3d8817e4Smiod 		  output_bfd,
531*3d8817e4Smiod 		  error_message)
532*3d8817e4Smiod      bfd *abfd;
533*3d8817e4Smiod      arelent *reloc_entry;
534*3d8817e4Smiod      asymbol *symbol;
535*3d8817e4Smiod      PTR data;
536*3d8817e4Smiod      asection *input_section;
537*3d8817e4Smiod      bfd *output_bfd;
538*3d8817e4Smiod      char **error_message;
539*3d8817e4Smiod {
540*3d8817e4Smiod   if (mips_refhi_list != NULL)
541*3d8817e4Smiod     {
542*3d8817e4Smiod       struct mips_hi *l;
543*3d8817e4Smiod 
544*3d8817e4Smiod       l = mips_refhi_list;
545*3d8817e4Smiod       while (l != NULL)
546*3d8817e4Smiod 	{
547*3d8817e4Smiod 	  unsigned long insn;
548*3d8817e4Smiod 	  unsigned long val;
549*3d8817e4Smiod 	  unsigned long vallo;
550*3d8817e4Smiod 	  struct mips_hi *next;
551*3d8817e4Smiod 
552*3d8817e4Smiod 	  /* Do the REFHI relocation.  Note that we actually don't
553*3d8817e4Smiod 	     need to know anything about the REFLO itself, except
554*3d8817e4Smiod 	     where to find the low 16 bits of the addend needed by the
555*3d8817e4Smiod 	     REFHI.  */
556*3d8817e4Smiod 	  insn = bfd_get_32 (abfd, l->addr);
557*3d8817e4Smiod 	  vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
558*3d8817e4Smiod 		   & 0xffff);
559*3d8817e4Smiod 	  val = ((insn & 0xffff) << 16) + vallo;
560*3d8817e4Smiod 	  val += l->addend;
561*3d8817e4Smiod 
562*3d8817e4Smiod 	  /* The low order 16 bits are always treated as a signed
563*3d8817e4Smiod 	     value.  Therefore, a negative value in the low order bits
564*3d8817e4Smiod 	     requires an adjustment in the high order bits.  We need
565*3d8817e4Smiod 	     to make this adjustment in two ways: once for the bits we
566*3d8817e4Smiod 	     took from the data, and once for the bits we are putting
567*3d8817e4Smiod 	     back in to the data.  */
568*3d8817e4Smiod 	  if ((vallo & 0x8000) != 0)
569*3d8817e4Smiod 	    val -= 0x10000;
570*3d8817e4Smiod 	  if ((val & 0x8000) != 0)
571*3d8817e4Smiod 	    val += 0x10000;
572*3d8817e4Smiod 
573*3d8817e4Smiod 	  insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
574*3d8817e4Smiod 	  bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
575*3d8817e4Smiod 
576*3d8817e4Smiod 	  next = l->next;
577*3d8817e4Smiod 	  free (l);
578*3d8817e4Smiod 	  l = next;
579*3d8817e4Smiod 	}
580*3d8817e4Smiod 
581*3d8817e4Smiod       mips_refhi_list = NULL;
582*3d8817e4Smiod     }
583*3d8817e4Smiod 
584*3d8817e4Smiod   /* Now do the REFLO reloc in the usual way.  */
585*3d8817e4Smiod   return mips_generic_reloc (abfd, reloc_entry, symbol, data,
586*3d8817e4Smiod 			      input_section, output_bfd, error_message);
587*3d8817e4Smiod }
588*3d8817e4Smiod 
589*3d8817e4Smiod /* Do a GPREL relocation.  This is a 16 bit value which must become
590*3d8817e4Smiod    the offset from the gp register.  */
591*3d8817e4Smiod 
592*3d8817e4Smiod static bfd_reloc_status_type
mips_gprel_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)593*3d8817e4Smiod mips_gprel_reloc (abfd,
594*3d8817e4Smiod 		  reloc_entry,
595*3d8817e4Smiod 		  symbol,
596*3d8817e4Smiod 		  data,
597*3d8817e4Smiod 		  input_section,
598*3d8817e4Smiod 		  output_bfd,
599*3d8817e4Smiod 		  error_message)
600*3d8817e4Smiod      bfd *abfd;
601*3d8817e4Smiod      arelent *reloc_entry;
602*3d8817e4Smiod      asymbol *symbol;
603*3d8817e4Smiod      PTR data;
604*3d8817e4Smiod      asection *input_section;
605*3d8817e4Smiod      bfd *output_bfd;
606*3d8817e4Smiod      char **error_message;
607*3d8817e4Smiod {
608*3d8817e4Smiod   bfd_boolean relocatable;
609*3d8817e4Smiod   bfd_vma gp;
610*3d8817e4Smiod   bfd_vma relocation;
611*3d8817e4Smiod   unsigned long val;
612*3d8817e4Smiod   unsigned long insn;
613*3d8817e4Smiod 
614*3d8817e4Smiod   /* If we're relocating, and this is an external symbol with no
615*3d8817e4Smiod      addend, we don't want to change anything.  We will only have an
616*3d8817e4Smiod      addend if this is a newly created reloc, not read from an ECOFF
617*3d8817e4Smiod      file.  */
618*3d8817e4Smiod   if (output_bfd != (bfd *) NULL
619*3d8817e4Smiod       && (symbol->flags & BSF_SECTION_SYM) == 0
620*3d8817e4Smiod       && reloc_entry->addend == 0)
621*3d8817e4Smiod     {
622*3d8817e4Smiod       reloc_entry->address += input_section->output_offset;
623*3d8817e4Smiod       return bfd_reloc_ok;
624*3d8817e4Smiod     }
625*3d8817e4Smiod 
626*3d8817e4Smiod   if (output_bfd != (bfd *) NULL)
627*3d8817e4Smiod     relocatable = TRUE;
628*3d8817e4Smiod   else
629*3d8817e4Smiod     {
630*3d8817e4Smiod       relocatable = FALSE;
631*3d8817e4Smiod       output_bfd = symbol->section->output_section->owner;
632*3d8817e4Smiod     }
633*3d8817e4Smiod 
634*3d8817e4Smiod   if (bfd_is_und_section (symbol->section) && ! relocatable)
635*3d8817e4Smiod     return bfd_reloc_undefined;
636*3d8817e4Smiod 
637*3d8817e4Smiod   /* We have to figure out the gp value, so that we can adjust the
638*3d8817e4Smiod      symbol value correctly.  We look up the symbol _gp in the output
639*3d8817e4Smiod      BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
640*3d8817e4Smiod      target data.  We don't need to adjust the symbol value for an
641*3d8817e4Smiod      external symbol if we are producing relocatable output.  */
642*3d8817e4Smiod   gp = _bfd_get_gp_value (output_bfd);
643*3d8817e4Smiod   if (gp == 0
644*3d8817e4Smiod       && (! relocatable
645*3d8817e4Smiod 	  || (symbol->flags & BSF_SECTION_SYM) != 0))
646*3d8817e4Smiod     {
647*3d8817e4Smiod       if (relocatable)
648*3d8817e4Smiod 	{
649*3d8817e4Smiod 	  /* Make up a value.  */
650*3d8817e4Smiod 	  gp = symbol->section->output_section->vma + 0x4000;
651*3d8817e4Smiod 	  _bfd_set_gp_value (output_bfd, gp);
652*3d8817e4Smiod 	}
653*3d8817e4Smiod       else
654*3d8817e4Smiod 	{
655*3d8817e4Smiod 	  unsigned int count;
656*3d8817e4Smiod 	  asymbol **sym;
657*3d8817e4Smiod 	  unsigned int i;
658*3d8817e4Smiod 
659*3d8817e4Smiod 	  count = bfd_get_symcount (output_bfd);
660*3d8817e4Smiod 	  sym = bfd_get_outsymbols (output_bfd);
661*3d8817e4Smiod 
662*3d8817e4Smiod 	  if (sym == (asymbol **) NULL)
663*3d8817e4Smiod 	    i = count;
664*3d8817e4Smiod 	  else
665*3d8817e4Smiod 	    {
666*3d8817e4Smiod 	      for (i = 0; i < count; i++, sym++)
667*3d8817e4Smiod 		{
668*3d8817e4Smiod 		  register const char *name;
669*3d8817e4Smiod 
670*3d8817e4Smiod 		  name = bfd_asymbol_name (*sym);
671*3d8817e4Smiod 		  if (*name == '_' && strcmp (name, "_gp") == 0)
672*3d8817e4Smiod 		    {
673*3d8817e4Smiod 		      gp = bfd_asymbol_value (*sym);
674*3d8817e4Smiod 		      _bfd_set_gp_value (output_bfd, gp);
675*3d8817e4Smiod 		      break;
676*3d8817e4Smiod 		    }
677*3d8817e4Smiod 		}
678*3d8817e4Smiod 	    }
679*3d8817e4Smiod 
680*3d8817e4Smiod 	  if (i >= count)
681*3d8817e4Smiod 	    {
682*3d8817e4Smiod 	      /* Only get the error once.  */
683*3d8817e4Smiod 	      gp = 4;
684*3d8817e4Smiod 	      _bfd_set_gp_value (output_bfd, gp);
685*3d8817e4Smiod 	      *error_message =
686*3d8817e4Smiod 		(char *) _("GP relative relocation when _gp not defined");
687*3d8817e4Smiod 	      return bfd_reloc_dangerous;
688*3d8817e4Smiod 	    }
689*3d8817e4Smiod 	}
690*3d8817e4Smiod     }
691*3d8817e4Smiod 
692*3d8817e4Smiod   if (bfd_is_com_section (symbol->section))
693*3d8817e4Smiod     relocation = 0;
694*3d8817e4Smiod   else
695*3d8817e4Smiod     relocation = symbol->value;
696*3d8817e4Smiod 
697*3d8817e4Smiod   relocation += symbol->section->output_section->vma;
698*3d8817e4Smiod   relocation += symbol->section->output_offset;
699*3d8817e4Smiod 
700*3d8817e4Smiod   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
701*3d8817e4Smiod     return bfd_reloc_outofrange;
702*3d8817e4Smiod 
703*3d8817e4Smiod   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
704*3d8817e4Smiod 
705*3d8817e4Smiod   /* Set val to the offset into the section or symbol.  */
706*3d8817e4Smiod   val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
707*3d8817e4Smiod   if (val & 0x8000)
708*3d8817e4Smiod     val -= 0x10000;
709*3d8817e4Smiod 
710*3d8817e4Smiod   /* Adjust val for the final section location and GP value.  If we
711*3d8817e4Smiod      are producing relocatable output, we don't want to do this for
712*3d8817e4Smiod      an external symbol.  */
713*3d8817e4Smiod   if (! relocatable
714*3d8817e4Smiod       || (symbol->flags & BSF_SECTION_SYM) != 0)
715*3d8817e4Smiod     val += relocation - gp;
716*3d8817e4Smiod 
717*3d8817e4Smiod   insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
718*3d8817e4Smiod   bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
719*3d8817e4Smiod 
720*3d8817e4Smiod   if (relocatable)
721*3d8817e4Smiod     reloc_entry->address += input_section->output_offset;
722*3d8817e4Smiod 
723*3d8817e4Smiod   /* Make sure it fit in 16 bits.  */
724*3d8817e4Smiod   if ((long) val >= 0x8000 || (long) val < -0x8000)
725*3d8817e4Smiod     return bfd_reloc_overflow;
726*3d8817e4Smiod 
727*3d8817e4Smiod   return bfd_reloc_ok;
728*3d8817e4Smiod }
729*3d8817e4Smiod 
730*3d8817e4Smiod /* Get the howto structure for a generic reloc type.  */
731*3d8817e4Smiod 
732*3d8817e4Smiod static reloc_howto_type *
mips_bfd_reloc_type_lookup(abfd,code)733*3d8817e4Smiod mips_bfd_reloc_type_lookup (abfd, code)
734*3d8817e4Smiod      bfd *abfd ATTRIBUTE_UNUSED;
735*3d8817e4Smiod      bfd_reloc_code_real_type code;
736*3d8817e4Smiod {
737*3d8817e4Smiod   int mips_type;
738*3d8817e4Smiod 
739*3d8817e4Smiod   switch (code)
740*3d8817e4Smiod     {
741*3d8817e4Smiod     case BFD_RELOC_16:
742*3d8817e4Smiod       mips_type = MIPS_R_REFHALF;
743*3d8817e4Smiod       break;
744*3d8817e4Smiod     case BFD_RELOC_32:
745*3d8817e4Smiod     case BFD_RELOC_CTOR:
746*3d8817e4Smiod       mips_type = MIPS_R_REFWORD;
747*3d8817e4Smiod       break;
748*3d8817e4Smiod     case BFD_RELOC_MIPS_JMP:
749*3d8817e4Smiod       mips_type = MIPS_R_JMPADDR;
750*3d8817e4Smiod       break;
751*3d8817e4Smiod     case BFD_RELOC_HI16_S:
752*3d8817e4Smiod       mips_type = MIPS_R_REFHI;
753*3d8817e4Smiod       break;
754*3d8817e4Smiod     case BFD_RELOC_LO16:
755*3d8817e4Smiod       mips_type = MIPS_R_REFLO;
756*3d8817e4Smiod       break;
757*3d8817e4Smiod     case BFD_RELOC_GPREL16:
758*3d8817e4Smiod       mips_type = MIPS_R_GPREL;
759*3d8817e4Smiod       break;
760*3d8817e4Smiod     case BFD_RELOC_MIPS_LITERAL:
761*3d8817e4Smiod       mips_type = MIPS_R_LITERAL;
762*3d8817e4Smiod       break;
763*3d8817e4Smiod     case BFD_RELOC_16_PCREL_S2:
764*3d8817e4Smiod       mips_type = MIPS_R_PCREL16;
765*3d8817e4Smiod       break;
766*3d8817e4Smiod     default:
767*3d8817e4Smiod       return (reloc_howto_type *) NULL;
768*3d8817e4Smiod     }
769*3d8817e4Smiod 
770*3d8817e4Smiod   return &mips_howto_table[mips_type];
771*3d8817e4Smiod }
772*3d8817e4Smiod 
773*3d8817e4Smiod /* A helper routine for mips_relocate_section which handles the REFHI
774*3d8817e4Smiod    relocations.  The REFHI relocation must be followed by a REFLO
775*3d8817e4Smiod    relocation, and the addend used is formed from the addends of both
776*3d8817e4Smiod    instructions.  */
777*3d8817e4Smiod 
778*3d8817e4Smiod static void
mips_relocate_hi(refhi,reflo,input_bfd,input_section,contents,relocation)779*3d8817e4Smiod mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents,
780*3d8817e4Smiod 		  relocation)
781*3d8817e4Smiod      struct internal_reloc *refhi;
782*3d8817e4Smiod      struct internal_reloc *reflo;
783*3d8817e4Smiod      bfd *input_bfd;
784*3d8817e4Smiod      asection *input_section;
785*3d8817e4Smiod      bfd_byte *contents;
786*3d8817e4Smiod      bfd_vma relocation;
787*3d8817e4Smiod {
788*3d8817e4Smiod   unsigned long insn;
789*3d8817e4Smiod   unsigned long val;
790*3d8817e4Smiod   unsigned long vallo;
791*3d8817e4Smiod 
792*3d8817e4Smiod   if (refhi == NULL)
793*3d8817e4Smiod     return;
794*3d8817e4Smiod 
795*3d8817e4Smiod   insn = bfd_get_32 (input_bfd,
796*3d8817e4Smiod 		     contents + refhi->r_vaddr - input_section->vma);
797*3d8817e4Smiod   if (reflo == NULL)
798*3d8817e4Smiod     vallo = 0;
799*3d8817e4Smiod   else
800*3d8817e4Smiod     vallo = (bfd_get_32 (input_bfd,
801*3d8817e4Smiod 			 contents + reflo->r_vaddr - input_section->vma)
802*3d8817e4Smiod 	     & 0xffff);
803*3d8817e4Smiod 
804*3d8817e4Smiod   val = ((insn & 0xffff) << 16) + vallo;
805*3d8817e4Smiod   val += relocation;
806*3d8817e4Smiod 
807*3d8817e4Smiod   /* The low order 16 bits are always treated as a signed value.
808*3d8817e4Smiod      Therefore, a negative value in the low order bits requires an
809*3d8817e4Smiod      adjustment in the high order bits.  We need to make this
810*3d8817e4Smiod      adjustment in two ways: once for the bits we took from the data,
811*3d8817e4Smiod      and once for the bits we are putting back in to the data.  */
812*3d8817e4Smiod   if ((vallo & 0x8000) != 0)
813*3d8817e4Smiod     val -= 0x10000;
814*3d8817e4Smiod 
815*3d8817e4Smiod   if ((val & 0x8000) != 0)
816*3d8817e4Smiod     val += 0x10000;
817*3d8817e4Smiod 
818*3d8817e4Smiod   insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
819*3d8817e4Smiod   bfd_put_32 (input_bfd, (bfd_vma) insn,
820*3d8817e4Smiod 	      contents + refhi->r_vaddr - input_section->vma);
821*3d8817e4Smiod }
822*3d8817e4Smiod 
823*3d8817e4Smiod /* Relocate a section while linking a MIPS ECOFF file.  */
824*3d8817e4Smiod 
825*3d8817e4Smiod static bfd_boolean
mips_relocate_section(output_bfd,info,input_bfd,input_section,contents,external_relocs)826*3d8817e4Smiod mips_relocate_section (output_bfd, info, input_bfd, input_section,
827*3d8817e4Smiod 		       contents, external_relocs)
828*3d8817e4Smiod      bfd *output_bfd;
829*3d8817e4Smiod      struct bfd_link_info *info;
830*3d8817e4Smiod      bfd *input_bfd;
831*3d8817e4Smiod      asection *input_section;
832*3d8817e4Smiod      bfd_byte *contents;
833*3d8817e4Smiod      PTR external_relocs;
834*3d8817e4Smiod {
835*3d8817e4Smiod   asection **symndx_to_section;
836*3d8817e4Smiod   struct ecoff_link_hash_entry **sym_hashes;
837*3d8817e4Smiod   bfd_vma gp;
838*3d8817e4Smiod   bfd_boolean gp_undefined;
839*3d8817e4Smiod   struct external_reloc *ext_rel;
840*3d8817e4Smiod   struct external_reloc *ext_rel_end;
841*3d8817e4Smiod   unsigned int i;
842*3d8817e4Smiod   bfd_boolean got_lo;
843*3d8817e4Smiod   struct internal_reloc lo_int_rel;
844*3d8817e4Smiod   bfd_size_type amt;
845*3d8817e4Smiod 
846*3d8817e4Smiod   BFD_ASSERT (input_bfd->xvec->byteorder
847*3d8817e4Smiod 	      == output_bfd->xvec->byteorder);
848*3d8817e4Smiod 
849*3d8817e4Smiod   /* We keep a table mapping the symndx found in an internal reloc to
850*3d8817e4Smiod      the appropriate section.  This is faster than looking up the
851*3d8817e4Smiod      section by name each time.  */
852*3d8817e4Smiod   symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
853*3d8817e4Smiod   if (symndx_to_section == (asection **) NULL)
854*3d8817e4Smiod     {
855*3d8817e4Smiod       amt = NUM_RELOC_SECTIONS * sizeof (asection *);
856*3d8817e4Smiod       symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
857*3d8817e4Smiod       if (!symndx_to_section)
858*3d8817e4Smiod 	return FALSE;
859*3d8817e4Smiod 
860*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_NONE] = NULL;
861*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_TEXT] =
862*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".text");
863*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_RDATA] =
864*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".rdata");
865*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_DATA] =
866*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".data");
867*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_SDATA] =
868*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".sdata");
869*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_SBSS] =
870*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".sbss");
871*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_BSS] =
872*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".bss");
873*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_INIT] =
874*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".init");
875*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_LIT8] =
876*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".lit8");
877*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_LIT4] =
878*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".lit4");
879*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_XDATA] = NULL;
880*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_PDATA] = NULL;
881*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_FINI] =
882*3d8817e4Smiod 	bfd_get_section_by_name (input_bfd, ".fini");
883*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_LITA] = NULL;
884*3d8817e4Smiod       symndx_to_section[RELOC_SECTION_ABS] = NULL;
885*3d8817e4Smiod 
886*3d8817e4Smiod       ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
887*3d8817e4Smiod     }
888*3d8817e4Smiod 
889*3d8817e4Smiod   sym_hashes = ecoff_data (input_bfd)->sym_hashes;
890*3d8817e4Smiod 
891*3d8817e4Smiod   gp = _bfd_get_gp_value (output_bfd);
892*3d8817e4Smiod   if (gp == 0)
893*3d8817e4Smiod     gp_undefined = TRUE;
894*3d8817e4Smiod   else
895*3d8817e4Smiod     gp_undefined = FALSE;
896*3d8817e4Smiod 
897*3d8817e4Smiod   got_lo = FALSE;
898*3d8817e4Smiod 
899*3d8817e4Smiod   ext_rel = (struct external_reloc *) external_relocs;
900*3d8817e4Smiod   ext_rel_end = ext_rel + input_section->reloc_count;
901*3d8817e4Smiod   for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
902*3d8817e4Smiod     {
903*3d8817e4Smiod       struct internal_reloc int_rel;
904*3d8817e4Smiod       bfd_boolean use_lo = FALSE;
905*3d8817e4Smiod       bfd_vma addend;
906*3d8817e4Smiod       reloc_howto_type *howto;
907*3d8817e4Smiod       struct ecoff_link_hash_entry *h = NULL;
908*3d8817e4Smiod       asection *s = NULL;
909*3d8817e4Smiod       bfd_vma relocation;
910*3d8817e4Smiod       bfd_reloc_status_type r;
911*3d8817e4Smiod 
912*3d8817e4Smiod       if (! got_lo)
913*3d8817e4Smiod 	mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
914*3d8817e4Smiod       else
915*3d8817e4Smiod 	{
916*3d8817e4Smiod 	  int_rel = lo_int_rel;
917*3d8817e4Smiod 	  got_lo = FALSE;
918*3d8817e4Smiod 	}
919*3d8817e4Smiod 
920*3d8817e4Smiod       BFD_ASSERT (int_rel.r_type
921*3d8817e4Smiod 		  < sizeof mips_howto_table / sizeof mips_howto_table[0]);
922*3d8817e4Smiod 
923*3d8817e4Smiod       /* The REFHI reloc requires special handling.  It must be followed
924*3d8817e4Smiod 	 by a REFLO reloc, and the addend is formed from both relocs.  */
925*3d8817e4Smiod       if (int_rel.r_type == MIPS_R_REFHI)
926*3d8817e4Smiod 	{
927*3d8817e4Smiod 	  struct external_reloc *lo_ext_rel;
928*3d8817e4Smiod 
929*3d8817e4Smiod 	  /* As a GNU extension, permit an arbitrary number of REFHI
930*3d8817e4Smiod              relocs before the REFLO reloc.  This permits gcc to emit
931*3d8817e4Smiod 	     the HI and LO relocs itself.  */
932*3d8817e4Smiod 	  for (lo_ext_rel = ext_rel + 1;
933*3d8817e4Smiod 	       lo_ext_rel < ext_rel_end;
934*3d8817e4Smiod 	       lo_ext_rel++)
935*3d8817e4Smiod 	    {
936*3d8817e4Smiod 	      mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,
937*3d8817e4Smiod 					&lo_int_rel);
938*3d8817e4Smiod 	      if (lo_int_rel.r_type != int_rel.r_type)
939*3d8817e4Smiod 		break;
940*3d8817e4Smiod 	    }
941*3d8817e4Smiod 
942*3d8817e4Smiod 	  if (lo_ext_rel < ext_rel_end
943*3d8817e4Smiod 	      && lo_int_rel.r_type == MIPS_R_REFLO
944*3d8817e4Smiod 	      && int_rel.r_extern == lo_int_rel.r_extern
945*3d8817e4Smiod 	      && int_rel.r_symndx == lo_int_rel.r_symndx)
946*3d8817e4Smiod 	    {
947*3d8817e4Smiod 	      use_lo = TRUE;
948*3d8817e4Smiod 	      if (lo_ext_rel == ext_rel + 1)
949*3d8817e4Smiod 		got_lo = TRUE;
950*3d8817e4Smiod 	    }
951*3d8817e4Smiod 	}
952*3d8817e4Smiod 
953*3d8817e4Smiod       howto = &mips_howto_table[int_rel.r_type];
954*3d8817e4Smiod 
955*3d8817e4Smiod       if (int_rel.r_extern)
956*3d8817e4Smiod 	{
957*3d8817e4Smiod 	  h = sym_hashes[int_rel.r_symndx];
958*3d8817e4Smiod 	  /* If h is NULL, that means that there is a reloc against an
959*3d8817e4Smiod 	     external symbol which we thought was just a debugging
960*3d8817e4Smiod 	     symbol.  This should not happen.  */
961*3d8817e4Smiod 	  if (h == (struct ecoff_link_hash_entry *) NULL)
962*3d8817e4Smiod 	    abort ();
963*3d8817e4Smiod 	}
964*3d8817e4Smiod       else
965*3d8817e4Smiod 	{
966*3d8817e4Smiod 	  if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
967*3d8817e4Smiod 	    s = NULL;
968*3d8817e4Smiod 	  else
969*3d8817e4Smiod 	    s = symndx_to_section[int_rel.r_symndx];
970*3d8817e4Smiod 
971*3d8817e4Smiod 	  if (s == (asection *) NULL)
972*3d8817e4Smiod 	    abort ();
973*3d8817e4Smiod 	}
974*3d8817e4Smiod 
975*3d8817e4Smiod       /* The GPREL reloc uses an addend: the difference in the GP
976*3d8817e4Smiod 	 values.  */
977*3d8817e4Smiod       if (int_rel.r_type != MIPS_R_GPREL
978*3d8817e4Smiod 	  && int_rel.r_type != MIPS_R_LITERAL)
979*3d8817e4Smiod 	addend = 0;
980*3d8817e4Smiod       else
981*3d8817e4Smiod 	{
982*3d8817e4Smiod 	  if (gp_undefined)
983*3d8817e4Smiod 	    {
984*3d8817e4Smiod 	      if (! ((*info->callbacks->reloc_dangerous)
985*3d8817e4Smiod 		     (info, _("GP relative relocation used when GP not defined"),
986*3d8817e4Smiod 		      input_bfd, input_section,
987*3d8817e4Smiod 		      int_rel.r_vaddr - input_section->vma)))
988*3d8817e4Smiod 		return FALSE;
989*3d8817e4Smiod 	      /* Only give the error once per link.  */
990*3d8817e4Smiod 	      gp = 4;
991*3d8817e4Smiod 	      _bfd_set_gp_value (output_bfd, gp);
992*3d8817e4Smiod 	      gp_undefined = FALSE;
993*3d8817e4Smiod 	    }
994*3d8817e4Smiod 	  if (! int_rel.r_extern)
995*3d8817e4Smiod 	    {
996*3d8817e4Smiod 	      /* This is a relocation against a section.  The current
997*3d8817e4Smiod 		 addend in the instruction is the difference between
998*3d8817e4Smiod 		 INPUT_SECTION->vma and the GP value of INPUT_BFD.  We
999*3d8817e4Smiod 		 must change this to be the difference between the
1000*3d8817e4Smiod 		 final definition (which will end up in RELOCATION)
1001*3d8817e4Smiod 		 and the GP value of OUTPUT_BFD (which is in GP).  */
1002*3d8817e4Smiod 	      addend = ecoff_data (input_bfd)->gp - gp;
1003*3d8817e4Smiod 	    }
1004*3d8817e4Smiod 	  else if (! info->relocatable
1005*3d8817e4Smiod 		   || h->root.type == bfd_link_hash_defined
1006*3d8817e4Smiod 		   || h->root.type == bfd_link_hash_defweak)
1007*3d8817e4Smiod 	    {
1008*3d8817e4Smiod 	      /* This is a relocation against a defined symbol.  The
1009*3d8817e4Smiod 		 current addend in the instruction is simply the
1010*3d8817e4Smiod 		 desired offset into the symbol (normally zero).  We
1011*3d8817e4Smiod 		 are going to change this into a relocation against a
1012*3d8817e4Smiod 		 defined symbol, so we want the instruction to hold
1013*3d8817e4Smiod 		 the difference between the final definition of the
1014*3d8817e4Smiod 		 symbol (which will end up in RELOCATION) and the GP
1015*3d8817e4Smiod 		 value of OUTPUT_BFD (which is in GP).  */
1016*3d8817e4Smiod 	      addend = - gp;
1017*3d8817e4Smiod 	    }
1018*3d8817e4Smiod 	  else
1019*3d8817e4Smiod 	    {
1020*3d8817e4Smiod 	      /* This is a relocation against an undefined or common
1021*3d8817e4Smiod 		 symbol.  The current addend in the instruction is
1022*3d8817e4Smiod 		 simply the desired offset into the symbol (normally
1023*3d8817e4Smiod 		 zero).  We are generating relocatable output, and we
1024*3d8817e4Smiod 		 aren't going to define this symbol, so we just leave
1025*3d8817e4Smiod 		 the instruction alone.  */
1026*3d8817e4Smiod 	      addend = 0;
1027*3d8817e4Smiod 	    }
1028*3d8817e4Smiod 	}
1029*3d8817e4Smiod 
1030*3d8817e4Smiod       if (info->relocatable)
1031*3d8817e4Smiod 	{
1032*3d8817e4Smiod 	  /* We are generating relocatable output, and must convert
1033*3d8817e4Smiod 	     the existing reloc.  */
1034*3d8817e4Smiod 	  if (int_rel.r_extern)
1035*3d8817e4Smiod 	    {
1036*3d8817e4Smiod 	      if ((h->root.type == bfd_link_hash_defined
1037*3d8817e4Smiod 		   || h->root.type == bfd_link_hash_defweak)
1038*3d8817e4Smiod 		  && ! bfd_is_abs_section (h->root.u.def.section))
1039*3d8817e4Smiod 		{
1040*3d8817e4Smiod 		  const char *name;
1041*3d8817e4Smiod 
1042*3d8817e4Smiod 		  /* This symbol is defined in the output.  Convert
1043*3d8817e4Smiod 		     the reloc from being against the symbol to being
1044*3d8817e4Smiod 		     against the section.  */
1045*3d8817e4Smiod 
1046*3d8817e4Smiod 		  /* Clear the r_extern bit.  */
1047*3d8817e4Smiod 		  int_rel.r_extern = 0;
1048*3d8817e4Smiod 
1049*3d8817e4Smiod 		  /* Compute a new r_symndx value.  */
1050*3d8817e4Smiod 		  s = h->root.u.def.section;
1051*3d8817e4Smiod 		  name = bfd_get_section_name (output_bfd,
1052*3d8817e4Smiod 					       s->output_section);
1053*3d8817e4Smiod 
1054*3d8817e4Smiod 		  int_rel.r_symndx = -1;
1055*3d8817e4Smiod 		  switch (name[1])
1056*3d8817e4Smiod 		    {
1057*3d8817e4Smiod 		    case 'b':
1058*3d8817e4Smiod 		      if (strcmp (name, ".bss") == 0)
1059*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_BSS;
1060*3d8817e4Smiod 		      break;
1061*3d8817e4Smiod 		    case 'd':
1062*3d8817e4Smiod 		      if (strcmp (name, ".data") == 0)
1063*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_DATA;
1064*3d8817e4Smiod 		      break;
1065*3d8817e4Smiod 		    case 'f':
1066*3d8817e4Smiod 		      if (strcmp (name, ".fini") == 0)
1067*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_FINI;
1068*3d8817e4Smiod 		      break;
1069*3d8817e4Smiod 		    case 'i':
1070*3d8817e4Smiod 		      if (strcmp (name, ".init") == 0)
1071*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_INIT;
1072*3d8817e4Smiod 		      break;
1073*3d8817e4Smiod 		    case 'l':
1074*3d8817e4Smiod 		      if (strcmp (name, ".lit8") == 0)
1075*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_LIT8;
1076*3d8817e4Smiod 		      else if (strcmp (name, ".lit4") == 0)
1077*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_LIT4;
1078*3d8817e4Smiod 		      break;
1079*3d8817e4Smiod 		    case 'r':
1080*3d8817e4Smiod 		      if (strcmp (name, ".rdata") == 0)
1081*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_RDATA;
1082*3d8817e4Smiod 		      break;
1083*3d8817e4Smiod 		    case 's':
1084*3d8817e4Smiod 		      if (strcmp (name, ".sdata") == 0)
1085*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_SDATA;
1086*3d8817e4Smiod 		      else if (strcmp (name, ".sbss") == 0)
1087*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_SBSS;
1088*3d8817e4Smiod 		      break;
1089*3d8817e4Smiod 		    case 't':
1090*3d8817e4Smiod 		      if (strcmp (name, ".text") == 0)
1091*3d8817e4Smiod 			int_rel.r_symndx = RELOC_SECTION_TEXT;
1092*3d8817e4Smiod 		      break;
1093*3d8817e4Smiod 		    }
1094*3d8817e4Smiod 
1095*3d8817e4Smiod 		  if (int_rel.r_symndx == -1)
1096*3d8817e4Smiod 		    abort ();
1097*3d8817e4Smiod 
1098*3d8817e4Smiod 		  /* Add the section VMA and the symbol value.  */
1099*3d8817e4Smiod 		  relocation = (h->root.u.def.value
1100*3d8817e4Smiod 				+ s->output_section->vma
1101*3d8817e4Smiod 				+ s->output_offset);
1102*3d8817e4Smiod 
1103*3d8817e4Smiod 		  /* For a PC relative relocation, the object file
1104*3d8817e4Smiod 		     currently holds just the addend.  We must adjust
1105*3d8817e4Smiod 		     by the address to get the right value.  */
1106*3d8817e4Smiod 		  if (howto->pc_relative)
1107*3d8817e4Smiod 		    relocation -= int_rel.r_vaddr - input_section->vma;
1108*3d8817e4Smiod 
1109*3d8817e4Smiod 		  h = NULL;
1110*3d8817e4Smiod 		}
1111*3d8817e4Smiod 	      else
1112*3d8817e4Smiod 		{
1113*3d8817e4Smiod 		  /* Change the symndx value to the right one for the
1114*3d8817e4Smiod 		     output BFD.  */
1115*3d8817e4Smiod 		  int_rel.r_symndx = h->indx;
1116*3d8817e4Smiod 		  if (int_rel.r_symndx == -1)
1117*3d8817e4Smiod 		    {
1118*3d8817e4Smiod 		      /* This symbol is not being written out.  */
1119*3d8817e4Smiod 		      if (! ((*info->callbacks->unattached_reloc)
1120*3d8817e4Smiod 			     (info, h->root.root.string, input_bfd,
1121*3d8817e4Smiod 			      input_section,
1122*3d8817e4Smiod 			      int_rel.r_vaddr - input_section->vma)))
1123*3d8817e4Smiod 			return FALSE;
1124*3d8817e4Smiod 		      int_rel.r_symndx = 0;
1125*3d8817e4Smiod 		    }
1126*3d8817e4Smiod 		  relocation = 0;
1127*3d8817e4Smiod 		}
1128*3d8817e4Smiod 	    }
1129*3d8817e4Smiod 	  else
1130*3d8817e4Smiod 	    {
1131*3d8817e4Smiod 	      /* This is a relocation against a section.  Adjust the
1132*3d8817e4Smiod 		 value by the amount the section moved.  */
1133*3d8817e4Smiod 	      relocation = (s->output_section->vma
1134*3d8817e4Smiod 			    + s->output_offset
1135*3d8817e4Smiod 			    - s->vma);
1136*3d8817e4Smiod 	    }
1137*3d8817e4Smiod 
1138*3d8817e4Smiod 	  relocation += addend;
1139*3d8817e4Smiod 	  addend = 0;
1140*3d8817e4Smiod 
1141*3d8817e4Smiod 	  /* Adjust a PC relative relocation by removing the reference
1142*3d8817e4Smiod 	     to the original address in the section and including the
1143*3d8817e4Smiod 	     reference to the new address.  */
1144*3d8817e4Smiod 	  if (howto->pc_relative)
1145*3d8817e4Smiod 	    relocation -= (input_section->output_section->vma
1146*3d8817e4Smiod 			   + input_section->output_offset
1147*3d8817e4Smiod 			   - input_section->vma);
1148*3d8817e4Smiod 
1149*3d8817e4Smiod 	  /* Adjust the contents.  */
1150*3d8817e4Smiod 	  if (relocation == 0)
1151*3d8817e4Smiod 	    r = bfd_reloc_ok;
1152*3d8817e4Smiod 	  else
1153*3d8817e4Smiod 	    {
1154*3d8817e4Smiod 	      if (int_rel.r_type != MIPS_R_REFHI)
1155*3d8817e4Smiod 		r = _bfd_relocate_contents (howto, input_bfd, relocation,
1156*3d8817e4Smiod 					    (contents
1157*3d8817e4Smiod 					     + int_rel.r_vaddr
1158*3d8817e4Smiod 					     - input_section->vma));
1159*3d8817e4Smiod 	      else
1160*3d8817e4Smiod 		{
1161*3d8817e4Smiod 		  mips_relocate_hi (&int_rel,
1162*3d8817e4Smiod 				    use_lo ? &lo_int_rel : NULL,
1163*3d8817e4Smiod 				    input_bfd, input_section, contents,
1164*3d8817e4Smiod 				    relocation);
1165*3d8817e4Smiod 		  r = bfd_reloc_ok;
1166*3d8817e4Smiod 		}
1167*3d8817e4Smiod 	    }
1168*3d8817e4Smiod 
1169*3d8817e4Smiod 	  /* Adjust the reloc address.  */
1170*3d8817e4Smiod 	  int_rel.r_vaddr += (input_section->output_section->vma
1171*3d8817e4Smiod 			      + input_section->output_offset
1172*3d8817e4Smiod 			      - input_section->vma);
1173*3d8817e4Smiod 
1174*3d8817e4Smiod 	  /* Save the changed reloc information.  */
1175*3d8817e4Smiod 	  mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
1176*3d8817e4Smiod 	}
1177*3d8817e4Smiod       else
1178*3d8817e4Smiod 	{
1179*3d8817e4Smiod 	  /* We are producing a final executable.  */
1180*3d8817e4Smiod 	  if (int_rel.r_extern)
1181*3d8817e4Smiod 	    {
1182*3d8817e4Smiod 	      /* This is a reloc against a symbol.  */
1183*3d8817e4Smiod 	      if (h->root.type == bfd_link_hash_defined
1184*3d8817e4Smiod 		  || h->root.type == bfd_link_hash_defweak)
1185*3d8817e4Smiod 		{
1186*3d8817e4Smiod 		  asection *hsec;
1187*3d8817e4Smiod 
1188*3d8817e4Smiod 		  hsec = h->root.u.def.section;
1189*3d8817e4Smiod 		  relocation = (h->root.u.def.value
1190*3d8817e4Smiod 				+ hsec->output_section->vma
1191*3d8817e4Smiod 				+ hsec->output_offset);
1192*3d8817e4Smiod 		}
1193*3d8817e4Smiod 	      else
1194*3d8817e4Smiod 		{
1195*3d8817e4Smiod 		  if (! ((*info->callbacks->undefined_symbol)
1196*3d8817e4Smiod 			 (info, h->root.root.string, input_bfd,
1197*3d8817e4Smiod 			  input_section,
1198*3d8817e4Smiod 			  int_rel.r_vaddr - input_section->vma, TRUE)))
1199*3d8817e4Smiod 		    return FALSE;
1200*3d8817e4Smiod 		  relocation = 0;
1201*3d8817e4Smiod 		}
1202*3d8817e4Smiod 	    }
1203*3d8817e4Smiod 	  else
1204*3d8817e4Smiod 	    {
1205*3d8817e4Smiod 	      /* This is a reloc against a section.  */
1206*3d8817e4Smiod 	      relocation = (s->output_section->vma
1207*3d8817e4Smiod 			    + s->output_offset
1208*3d8817e4Smiod 			    - s->vma);
1209*3d8817e4Smiod 
1210*3d8817e4Smiod 	      /* A PC relative reloc is already correct in the object
1211*3d8817e4Smiod 		 file.  Make it look like a pcrel_offset relocation by
1212*3d8817e4Smiod 		 adding in the start address.  */
1213*3d8817e4Smiod 	      if (howto->pc_relative)
1214*3d8817e4Smiod 		relocation += int_rel.r_vaddr;
1215*3d8817e4Smiod 	    }
1216*3d8817e4Smiod 
1217*3d8817e4Smiod 	  if (int_rel.r_type != MIPS_R_REFHI)
1218*3d8817e4Smiod 	    r = _bfd_final_link_relocate (howto,
1219*3d8817e4Smiod 					  input_bfd,
1220*3d8817e4Smiod 					  input_section,
1221*3d8817e4Smiod 					  contents,
1222*3d8817e4Smiod 					  (int_rel.r_vaddr
1223*3d8817e4Smiod 					   - input_section->vma),
1224*3d8817e4Smiod 					  relocation,
1225*3d8817e4Smiod 					  addend);
1226*3d8817e4Smiod 	  else
1227*3d8817e4Smiod 	    {
1228*3d8817e4Smiod 	      mips_relocate_hi (&int_rel,
1229*3d8817e4Smiod 				use_lo ? &lo_int_rel : NULL,
1230*3d8817e4Smiod 				input_bfd, input_section, contents,
1231*3d8817e4Smiod 				relocation);
1232*3d8817e4Smiod 	      r = bfd_reloc_ok;
1233*3d8817e4Smiod 	    }
1234*3d8817e4Smiod 	}
1235*3d8817e4Smiod 
1236*3d8817e4Smiod       /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
1237*3d8817e4Smiod 	 instruction provides a 28 bit address (the two lower bits are
1238*3d8817e4Smiod 	 implicit zeroes) which is combined with the upper four bits
1239*3d8817e4Smiod 	 of the instruction address.  */
1240*3d8817e4Smiod       if (r == bfd_reloc_ok
1241*3d8817e4Smiod 	  && int_rel.r_type == MIPS_R_JMPADDR
1242*3d8817e4Smiod 	  && (((relocation
1243*3d8817e4Smiod 		+ addend
1244*3d8817e4Smiod 		+ (int_rel.r_extern ? 0 : s->vma))
1245*3d8817e4Smiod 	       & 0xf0000000)
1246*3d8817e4Smiod 	      != ((input_section->output_section->vma
1247*3d8817e4Smiod 		   + input_section->output_offset
1248*3d8817e4Smiod 		   + (int_rel.r_vaddr - input_section->vma))
1249*3d8817e4Smiod 		  & 0xf0000000)))
1250*3d8817e4Smiod 	r = bfd_reloc_overflow;
1251*3d8817e4Smiod 
1252*3d8817e4Smiod       if (r != bfd_reloc_ok)
1253*3d8817e4Smiod 	{
1254*3d8817e4Smiod 	  switch (r)
1255*3d8817e4Smiod 	    {
1256*3d8817e4Smiod 	    default:
1257*3d8817e4Smiod 	    case bfd_reloc_outofrange:
1258*3d8817e4Smiod 	      abort ();
1259*3d8817e4Smiod 	    case bfd_reloc_overflow:
1260*3d8817e4Smiod 	      {
1261*3d8817e4Smiod 		const char *name;
1262*3d8817e4Smiod 
1263*3d8817e4Smiod 		if (int_rel.r_extern)
1264*3d8817e4Smiod 		  name = NULL;
1265*3d8817e4Smiod 		else
1266*3d8817e4Smiod 		  name = bfd_section_name (input_bfd, s);
1267*3d8817e4Smiod 		if (! ((*info->callbacks->reloc_overflow)
1268*3d8817e4Smiod 		       (info, (h ? &h->root : NULL), name, howto->name,
1269*3d8817e4Smiod 			(bfd_vma) 0, input_bfd, input_section,
1270*3d8817e4Smiod 			int_rel.r_vaddr - input_section->vma)))
1271*3d8817e4Smiod 		  return FALSE;
1272*3d8817e4Smiod 	      }
1273*3d8817e4Smiod 	      break;
1274*3d8817e4Smiod 	    }
1275*3d8817e4Smiod 	}
1276*3d8817e4Smiod     }
1277*3d8817e4Smiod 
1278*3d8817e4Smiod   return TRUE;
1279*3d8817e4Smiod }
1280*3d8817e4Smiod 
1281*3d8817e4Smiod /* This is the ECOFF backend structure.  The backend field of the
1282*3d8817e4Smiod    target vector points to this.  */
1283*3d8817e4Smiod 
1284*3d8817e4Smiod static const struct ecoff_backend_data mips_ecoff_backend_data =
1285*3d8817e4Smiod {
1286*3d8817e4Smiod   /* COFF backend structure.  */
1287*3d8817e4Smiod   {
1288*3d8817e4Smiod     (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
1289*3d8817e4Smiod     (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
1290*3d8817e4Smiod     (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
1291*3d8817e4Smiod     (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
1292*3d8817e4Smiod     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
1293*3d8817e4Smiod     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
1294*3d8817e4Smiod     (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
1295*3d8817e4Smiod     mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
1296*3d8817e4Smiod     mips_ecoff_swap_scnhdr_out,
1297*3d8817e4Smiod     FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2,
1298*3d8817e4Smiod     mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
1299*3d8817e4Smiod     mips_ecoff_swap_scnhdr_in, NULL,
1300*3d8817e4Smiod     mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
1301*3d8817e4Smiod     _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
1302*3d8817e4Smiod     _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
1303*3d8817e4Smiod     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1304*3d8817e4Smiod     NULL, NULL
1305*3d8817e4Smiod   },
1306*3d8817e4Smiod   /* Supported architecture.  */
1307*3d8817e4Smiod   bfd_arch_mips,
1308*3d8817e4Smiod   /* Initial portion of armap string.  */
1309*3d8817e4Smiod   "__________",
1310*3d8817e4Smiod   /* The page boundary used to align sections in a demand-paged
1311*3d8817e4Smiod      executable file.  E.g., 0x1000.  */
1312*3d8817e4Smiod   0x1000,
1313*3d8817e4Smiod   /* TRUE if the .rdata section is part of the text segment, as on the
1314*3d8817e4Smiod      Alpha.  FALSE if .rdata is part of the data segment, as on the
1315*3d8817e4Smiod      MIPS.  */
1316*3d8817e4Smiod   FALSE,
1317*3d8817e4Smiod   /* Bitsize of constructor entries.  */
1318*3d8817e4Smiod   32,
1319*3d8817e4Smiod   /* Reloc to use for constructor entries.  */
1320*3d8817e4Smiod   &mips_howto_table[MIPS_R_REFWORD],
1321*3d8817e4Smiod   {
1322*3d8817e4Smiod     /* Symbol table magic number.  */
1323*3d8817e4Smiod     magicSym,
1324*3d8817e4Smiod     /* Alignment of debugging information.  E.g., 4.  */
1325*3d8817e4Smiod     4,
1326*3d8817e4Smiod     /* Sizes of external symbolic information.  */
1327*3d8817e4Smiod     sizeof (struct hdr_ext),
1328*3d8817e4Smiod     sizeof (struct dnr_ext),
1329*3d8817e4Smiod     sizeof (struct pdr_ext),
1330*3d8817e4Smiod     sizeof (struct sym_ext),
1331*3d8817e4Smiod     sizeof (struct opt_ext),
1332*3d8817e4Smiod     sizeof (struct fdr_ext),
1333*3d8817e4Smiod     sizeof (struct rfd_ext),
1334*3d8817e4Smiod     sizeof (struct ext_ext),
1335*3d8817e4Smiod     /* Functions to swap in external symbolic data.  */
1336*3d8817e4Smiod     ecoff_swap_hdr_in,
1337*3d8817e4Smiod     ecoff_swap_dnr_in,
1338*3d8817e4Smiod     ecoff_swap_pdr_in,
1339*3d8817e4Smiod     ecoff_swap_sym_in,
1340*3d8817e4Smiod     ecoff_swap_opt_in,
1341*3d8817e4Smiod     ecoff_swap_fdr_in,
1342*3d8817e4Smiod     ecoff_swap_rfd_in,
1343*3d8817e4Smiod     ecoff_swap_ext_in,
1344*3d8817e4Smiod     _bfd_ecoff_swap_tir_in,
1345*3d8817e4Smiod     _bfd_ecoff_swap_rndx_in,
1346*3d8817e4Smiod     /* Functions to swap out external symbolic data.  */
1347*3d8817e4Smiod     ecoff_swap_hdr_out,
1348*3d8817e4Smiod     ecoff_swap_dnr_out,
1349*3d8817e4Smiod     ecoff_swap_pdr_out,
1350*3d8817e4Smiod     ecoff_swap_sym_out,
1351*3d8817e4Smiod     ecoff_swap_opt_out,
1352*3d8817e4Smiod     ecoff_swap_fdr_out,
1353*3d8817e4Smiod     ecoff_swap_rfd_out,
1354*3d8817e4Smiod     ecoff_swap_ext_out,
1355*3d8817e4Smiod     _bfd_ecoff_swap_tir_out,
1356*3d8817e4Smiod     _bfd_ecoff_swap_rndx_out,
1357*3d8817e4Smiod     /* Function to read in symbolic data.  */
1358*3d8817e4Smiod     _bfd_ecoff_slurp_symbolic_info
1359*3d8817e4Smiod   },
1360*3d8817e4Smiod   /* External reloc size.  */
1361*3d8817e4Smiod   RELSZ,
1362*3d8817e4Smiod   /* Reloc swapping functions.  */
1363*3d8817e4Smiod   mips_ecoff_swap_reloc_in,
1364*3d8817e4Smiod   mips_ecoff_swap_reloc_out,
1365*3d8817e4Smiod   /* Backend reloc tweaking.  */
1366*3d8817e4Smiod   mips_adjust_reloc_in,
1367*3d8817e4Smiod   mips_adjust_reloc_out,
1368*3d8817e4Smiod   /* Relocate section contents while linking.  */
1369*3d8817e4Smiod   mips_relocate_section,
1370*3d8817e4Smiod   /* Do final adjustments to filehdr and aouthdr.  */
1371*3d8817e4Smiod   NULL,
1372*3d8817e4Smiod   /* Read an element from an archive at a given file position.  */
1373*3d8817e4Smiod   _bfd_get_elt_at_filepos
1374*3d8817e4Smiod };
1375*3d8817e4Smiod 
1376*3d8817e4Smiod /* Looking up a reloc type is MIPS specific.  */
1377*3d8817e4Smiod #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
1378*3d8817e4Smiod 
1379*3d8817e4Smiod /* Getting relocated section contents is generic.  */
1380*3d8817e4Smiod #define _bfd_ecoff_bfd_get_relocated_section_contents \
1381*3d8817e4Smiod   bfd_generic_get_relocated_section_contents
1382*3d8817e4Smiod 
1383*3d8817e4Smiod /* Handling file windows is generic.  */
1384*3d8817e4Smiod #define _bfd_ecoff_get_section_contents_in_window \
1385*3d8817e4Smiod   _bfd_generic_get_section_contents_in_window
1386*3d8817e4Smiod 
1387*3d8817e4Smiod /* Relaxing sections is MIPS specific.  */
1388*3d8817e4Smiod #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
1389*3d8817e4Smiod 
1390*3d8817e4Smiod /* GC of sections is not done.  */
1391*3d8817e4Smiod #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
1392*3d8817e4Smiod 
1393*3d8817e4Smiod /* Merging of sections is not done.  */
1394*3d8817e4Smiod #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
1395*3d8817e4Smiod 
1396*3d8817e4Smiod #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
1397*3d8817e4Smiod #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
1398*3d8817e4Smiod #define _bfd_ecoff_section_already_linked \
1399*3d8817e4Smiod   _bfd_generic_section_already_linked
1400*3d8817e4Smiod 
1401*3d8817e4Smiod extern const bfd_target ecoff_big_vec;
1402*3d8817e4Smiod 
1403*3d8817e4Smiod const bfd_target ecoff_little_vec =
1404*3d8817e4Smiod {
1405*3d8817e4Smiod   "ecoff-littlemips",		/* name */
1406*3d8817e4Smiod   bfd_target_ecoff_flavour,
1407*3d8817e4Smiod   BFD_ENDIAN_LITTLE,		/* data byte order is little */
1408*3d8817e4Smiod   BFD_ENDIAN_LITTLE,		/* header byte order is little */
1409*3d8817e4Smiod 
1410*3d8817e4Smiod   (HAS_RELOC | EXEC_P |		/* object flags */
1411*3d8817e4Smiod    HAS_LINENO | HAS_DEBUG |
1412*3d8817e4Smiod    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1413*3d8817e4Smiod 
1414*3d8817e4Smiod   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1415*3d8817e4Smiod   0,				/* leading underscore */
1416*3d8817e4Smiod   ' ',				/* ar_pad_char */
1417*3d8817e4Smiod   15,				/* ar_max_namelen */
1418*3d8817e4Smiod   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1419*3d8817e4Smiod      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1420*3d8817e4Smiod      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1421*3d8817e4Smiod   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1422*3d8817e4Smiod      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1423*3d8817e4Smiod      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
1424*3d8817e4Smiod 
1425*3d8817e4Smiod   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1426*3d8817e4Smiod      _bfd_ecoff_archive_p, _bfd_dummy_target},
1427*3d8817e4Smiod   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
1428*3d8817e4Smiod      _bfd_generic_mkarchive, bfd_false},
1429*3d8817e4Smiod   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1430*3d8817e4Smiod      _bfd_write_archive_contents, bfd_false},
1431*3d8817e4Smiod 
1432*3d8817e4Smiod      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1433*3d8817e4Smiod      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1434*3d8817e4Smiod      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1435*3d8817e4Smiod      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1436*3d8817e4Smiod      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1437*3d8817e4Smiod      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1438*3d8817e4Smiod      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1439*3d8817e4Smiod      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1440*3d8817e4Smiod      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1441*3d8817e4Smiod 
1442*3d8817e4Smiod   & ecoff_big_vec,
1443*3d8817e4Smiod 
1444*3d8817e4Smiod   (PTR) &mips_ecoff_backend_data
1445*3d8817e4Smiod };
1446*3d8817e4Smiod 
1447*3d8817e4Smiod const bfd_target ecoff_big_vec =
1448*3d8817e4Smiod {
1449*3d8817e4Smiod   "ecoff-bigmips",		/* name */
1450*3d8817e4Smiod   bfd_target_ecoff_flavour,
1451*3d8817e4Smiod   BFD_ENDIAN_BIG,		/* data byte order is big */
1452*3d8817e4Smiod   BFD_ENDIAN_BIG,		/* header byte order is big */
1453*3d8817e4Smiod 
1454*3d8817e4Smiod   (HAS_RELOC | EXEC_P |		/* object flags */
1455*3d8817e4Smiod    HAS_LINENO | HAS_DEBUG |
1456*3d8817e4Smiod    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1457*3d8817e4Smiod 
1458*3d8817e4Smiod   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1459*3d8817e4Smiod   0,				/* leading underscore */
1460*3d8817e4Smiod   ' ',				/* ar_pad_char */
1461*3d8817e4Smiod   15,				/* ar_max_namelen */
1462*3d8817e4Smiod   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1463*3d8817e4Smiod      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1464*3d8817e4Smiod      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1465*3d8817e4Smiod   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1466*3d8817e4Smiod      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1467*3d8817e4Smiod      bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1468*3d8817e4Smiod  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1469*3d8817e4Smiod     _bfd_ecoff_archive_p, _bfd_dummy_target},
1470*3d8817e4Smiod  {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
1471*3d8817e4Smiod     _bfd_generic_mkarchive, bfd_false},
1472*3d8817e4Smiod  {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1473*3d8817e4Smiod     _bfd_write_archive_contents, bfd_false},
1474*3d8817e4Smiod 
1475*3d8817e4Smiod      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1476*3d8817e4Smiod      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1477*3d8817e4Smiod      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1478*3d8817e4Smiod      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1479*3d8817e4Smiod      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1480*3d8817e4Smiod      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1481*3d8817e4Smiod      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1482*3d8817e4Smiod      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1483*3d8817e4Smiod      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1484*3d8817e4Smiod 
1485*3d8817e4Smiod   & ecoff_little_vec,
1486*3d8817e4Smiod 
1487*3d8817e4Smiod   (PTR) &mips_ecoff_backend_data
1488*3d8817e4Smiod };
1489*3d8817e4Smiod 
1490*3d8817e4Smiod const bfd_target ecoff_biglittle_vec =
1491*3d8817e4Smiod {
1492*3d8817e4Smiod   "ecoff-biglittlemips",		/* name */
1493*3d8817e4Smiod   bfd_target_ecoff_flavour,
1494*3d8817e4Smiod   BFD_ENDIAN_LITTLE,		/* data byte order is little */
1495*3d8817e4Smiod   BFD_ENDIAN_BIG,		/* header byte order is big */
1496*3d8817e4Smiod 
1497*3d8817e4Smiod   (HAS_RELOC | EXEC_P |		/* object flags */
1498*3d8817e4Smiod    HAS_LINENO | HAS_DEBUG |
1499*3d8817e4Smiod    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1500*3d8817e4Smiod 
1501*3d8817e4Smiod   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1502*3d8817e4Smiod   0,				/* leading underscore */
1503*3d8817e4Smiod   ' ',				/* ar_pad_char */
1504*3d8817e4Smiod   15,				/* ar_max_namelen */
1505*3d8817e4Smiod   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1506*3d8817e4Smiod      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1507*3d8817e4Smiod      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1508*3d8817e4Smiod   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1509*3d8817e4Smiod      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1510*3d8817e4Smiod      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1511*3d8817e4Smiod 
1512*3d8817e4Smiod   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1513*3d8817e4Smiod      _bfd_ecoff_archive_p, _bfd_dummy_target},
1514*3d8817e4Smiod   {bfd_false, _bfd_ecoff_mkobject,  /* bfd_set_format */
1515*3d8817e4Smiod      _bfd_generic_mkarchive, bfd_false},
1516*3d8817e4Smiod   {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1517*3d8817e4Smiod      _bfd_write_archive_contents, bfd_false},
1518*3d8817e4Smiod 
1519*3d8817e4Smiod      BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1520*3d8817e4Smiod      BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1521*3d8817e4Smiod      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1522*3d8817e4Smiod      BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1523*3d8817e4Smiod      BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1524*3d8817e4Smiod      BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1525*3d8817e4Smiod      BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1526*3d8817e4Smiod      BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1527*3d8817e4Smiod      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1528*3d8817e4Smiod 
1529*3d8817e4Smiod   NULL,
1530*3d8817e4Smiod 
1531*3d8817e4Smiod   (PTR) &mips_ecoff_backend_data
1532*3d8817e4Smiod };
1533