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