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