1 |
/* BFD back-end for MIPS PE COFF files. |
/* BFD back-end for MIPS PE COFF files. |
2 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
3 |
2000, 2001 Free Software Foundation, Inc. |
2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
4 |
Modified from coff-i386.c by DJ Delorie, dj@cygnus.com |
Modified from coff-i386.c by DJ Delorie, dj@cygnus.com |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
21 |
|
|
22 |
#define COFF_WITH_PE |
#define COFF_WITH_PE |
23 |
#define COFF_LONG_SECTION_NAMES |
#define COFF_LONG_SECTION_NAMES |
24 |
#define PCRELOFFSET true |
#define PCRELOFFSET TRUE |
25 |
|
|
26 |
#include "bfd.h" |
#include "bfd.h" |
27 |
#include "sysdep.h" |
#include "sysdep.h" |
40 |
static reloc_howto_type *coff_mips_rtype_to_howto |
static reloc_howto_type *coff_mips_rtype_to_howto |
41 |
PARAMS ((bfd *, asection *, struct internal_reloc *, |
PARAMS ((bfd *, asection *, struct internal_reloc *, |
42 |
struct coff_link_hash_entry *, struct internal_syment *, |
struct coff_link_hash_entry *, struct internal_syment *, |
|
|
|
43 |
bfd_vma *)); |
bfd_vma *)); |
|
#if 0 |
|
|
static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR, |
|
|
struct internal_reloc *)); |
|
|
static void mips_ecoff_swap_reloc_out PARAMS ((bfd *, |
|
|
const struct internal_reloc *, |
|
|
PTR)); |
|
|
static void mips_adjust_reloc_in PARAMS ((bfd *, |
|
|
const struct internal_reloc *, |
|
|
arelent *)); |
|
|
static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *, |
|
|
struct internal_reloc *)); |
|
|
#endif |
|
44 |
|
|
45 |
static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *)); |
static bfd_boolean in_reloc_p |
46 |
static reloc_howto_type * coff_mips_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); |
PARAMS ((bfd *, reloc_howto_type *)); |
47 |
static void mips_swap_reloc_in PARAMS ((bfd *, PTR, PTR)); |
static reloc_howto_type * coff_mips_reloc_type_lookup |
48 |
static unsigned int mips_swap_reloc_out PARAMS ((bfd *, PTR, PTR)); |
PARAMS ((bfd *, bfd_reloc_code_real_type)); |
49 |
static boolean coff_pe_mips_relocate_section |
static void mips_swap_reloc_in |
50 |
|
PARAMS ((bfd *, PTR, PTR)); |
51 |
|
static unsigned int mips_swap_reloc_out |
52 |
|
PARAMS ((bfd *, PTR, PTR)); |
53 |
|
static bfd_boolean coff_pe_mips_relocate_section |
54 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
55 |
struct internal_reloc *, struct internal_syment *, asection **)); |
struct internal_reloc *, struct internal_syment *, asection **)); |
56 |
|
|
63 |
section for a reference to a common symbol is the value itself plus |
section for a reference to a common symbol is the value itself plus |
64 |
any desired offset. Ian Taylor, Cygnus Support. */ |
any desired offset. Ian Taylor, Cygnus Support. */ |
65 |
|
|
66 |
/* If we are producing relocateable output, we need to do some |
/* If we are producing relocatable output, we need to do some |
67 |
adjustments to the object file that are not done by the |
adjustments to the object file that are not done by the |
68 |
bfd_perform_relocation function. This function is called by every |
bfd_perform_relocation function. This function is called by every |
69 |
reloc type to make any required adjustments. */ |
reloc type to make any required adjustments. */ |
108 |
{ |
{ |
109 |
/* For some reason bfd_perform_relocation always effectively |
/* For some reason bfd_perform_relocation always effectively |
110 |
ignores the addend for a COFF target when producing |
ignores the addend for a COFF target when producing |
111 |
relocateable output. This seems to be always wrong for 386 |
relocatable output. This seems to be always wrong for 386 |
112 |
COFF, so we handle the addend here instead. */ |
COFF, so we handle the addend here instead. */ |
113 |
diff = reloc_entry->addend; |
diff = reloc_entry->addend; |
114 |
} |
} |
115 |
|
|
|
#ifdef COFF_WITH_PE |
|
|
#if 0 |
|
|
/* dj - handle it like any other reloc? */ |
|
|
/* FIXME: How should this case be handled? */ |
|
|
if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0) |
|
|
abort (); |
|
|
#endif |
|
|
#endif |
|
|
|
|
116 |
#define DOIT(x) \ |
#define DOIT(x) \ |
117 |
x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask)) |
x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask)) |
118 |
|
|
157 |
} |
} |
158 |
|
|
159 |
#ifdef COFF_WITH_PE |
#ifdef COFF_WITH_PE |
160 |
/* Return true if this relocation should |
/* Return TRUE if this relocation should |
161 |
appear in the output .reloc section. */ |
appear in the output .reloc section. */ |
162 |
|
|
163 |
static boolean |
static bfd_boolean |
164 |
in_reloc_p (abfd, howto) |
in_reloc_p (abfd, howto) |
165 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd * abfd ATTRIBUTE_UNUSED; |
166 |
reloc_howto_type *howto; |
reloc_howto_type *howto; |
170 |
#endif |
#endif |
171 |
|
|
172 |
#ifndef PCRELOFFSET |
#ifndef PCRELOFFSET |
173 |
#define PCRELOFFSET false |
#define PCRELOFFSET FALSE |
174 |
#endif |
#endif |
175 |
|
|
176 |
static reloc_howto_type howto_table[] = |
static reloc_howto_type howto_table[] = |
182 |
0, /* rightshift */ |
0, /* rightshift */ |
183 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
184 |
8, /* bitsize */ |
8, /* bitsize */ |
185 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
186 |
0, /* bitpos */ |
0, /* bitpos */ |
187 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
188 |
0, /* special_function */ |
0, /* special_function */ |
189 |
"IGNORE", /* name */ |
"IGNORE", /* name */ |
190 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
191 |
0, /* src_mask */ |
0, /* src_mask */ |
192 |
0, /* dst_mask */ |
0, /* dst_mask */ |
193 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
194 |
|
|
195 |
/* A 16 bit reference to a symbol, normally from a data section. */ |
/* A 16 bit reference to a symbol, normally from a data section. */ |
196 |
HOWTO (MIPS_R_REFHALF, /* type */ |
HOWTO (MIPS_R_REFHALF, /* type */ |
197 |
0, /* rightshift */ |
0, /* rightshift */ |
198 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
199 |
16, /* bitsize */ |
16, /* bitsize */ |
200 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
201 |
0, /* bitpos */ |
0, /* bitpos */ |
202 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
203 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
204 |
"REFHALF", /* name */ |
"REFHALF", /* name */ |
205 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
206 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
207 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
208 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
209 |
|
|
210 |
/* A 32 bit reference to a symbol, normally from a data section. */ |
/* A 32 bit reference to a symbol, normally from a data section. */ |
211 |
HOWTO (MIPS_R_REFWORD, /* type */ |
HOWTO (MIPS_R_REFWORD, /* type */ |
212 |
0, /* rightshift */ |
0, /* rightshift */ |
213 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
214 |
32, /* bitsize */ |
32, /* bitsize */ |
215 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
216 |
0, /* bitpos */ |
0, /* bitpos */ |
217 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
218 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
219 |
"REFWORD", /* name */ |
"REFWORD", /* name */ |
220 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
221 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
222 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
223 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
224 |
|
|
225 |
/* A 26 bit absolute jump address. */ |
/* A 26 bit absolute jump address. */ |
226 |
HOWTO (MIPS_R_JMPADDR, /* type */ |
HOWTO (MIPS_R_JMPADDR, /* type */ |
227 |
2, /* rightshift */ |
2, /* rightshift */ |
228 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
229 |
26, /* bitsize */ |
26, /* bitsize */ |
230 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
231 |
0, /* bitpos */ |
0, /* bitpos */ |
232 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
233 |
/* This needs complex overflow |
/* This needs complex overflow |
235 |
bits must match the PC. */ |
bits must match the PC. */ |
236 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
237 |
"JMPADDR", /* name */ |
"JMPADDR", /* name */ |
238 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
239 |
0x3ffffff, /* src_mask */ |
0x3ffffff, /* src_mask */ |
240 |
0x3ffffff, /* dst_mask */ |
0x3ffffff, /* dst_mask */ |
241 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
242 |
|
|
243 |
/* The high 16 bits of a symbol value. Handled by the function |
/* The high 16 bits of a symbol value. Handled by the function |
244 |
mips_refhi_reloc. */ |
mips_refhi_reloc. */ |
246 |
16, /* rightshift */ |
16, /* rightshift */ |
247 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
248 |
16, /* bitsize */ |
16, /* bitsize */ |
249 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
250 |
0, /* bitpos */ |
0, /* bitpos */ |
251 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
252 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
253 |
"REFHI", /* name */ |
"REFHI", /* name */ |
254 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
255 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
256 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
257 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
258 |
|
|
259 |
/* The low 16 bits of a symbol value. */ |
/* The low 16 bits of a symbol value. */ |
260 |
HOWTO (MIPS_R_REFLO, /* type */ |
HOWTO (MIPS_R_REFLO, /* type */ |
261 |
0, /* rightshift */ |
0, /* rightshift */ |
262 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
263 |
16, /* bitsize */ |
16, /* bitsize */ |
264 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
265 |
0, /* bitpos */ |
0, /* bitpos */ |
266 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
267 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
268 |
"REFLO", /* name */ |
"REFLO", /* name */ |
269 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
270 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
271 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
272 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
273 |
|
|
274 |
/* A reference to an offset from the gp register. Handled by the |
/* A reference to an offset from the gp register. Handled by the |
275 |
function mips_gprel_reloc. */ |
function mips_gprel_reloc. */ |
277 |
0, /* rightshift */ |
0, /* rightshift */ |
278 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
279 |
16, /* bitsize */ |
16, /* bitsize */ |
280 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
281 |
0, /* bitpos */ |
0, /* bitpos */ |
282 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
283 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
284 |
"GPREL", /* name */ |
"GPREL", /* name */ |
285 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
286 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
287 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
288 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
289 |
|
|
290 |
/* A reference to a literal using an offset from the gp register. |
/* A reference to a literal using an offset from the gp register. |
291 |
Handled by the function mips_gprel_reloc. */ |
Handled by the function mips_gprel_reloc. */ |
293 |
0, /* rightshift */ |
0, /* rightshift */ |
294 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
295 |
16, /* bitsize */ |
16, /* bitsize */ |
296 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
297 |
0, /* bitpos */ |
0, /* bitpos */ |
298 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
299 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
300 |
"LITERAL", /* name */ |
"LITERAL", /* name */ |
301 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
302 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
303 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
304 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
305 |
|
|
306 |
EMPTY_HOWTO (8), |
EMPTY_HOWTO (8), |
307 |
EMPTY_HOWTO (9), |
EMPTY_HOWTO (9), |
333 |
0, /* rightshift */ |
0, /* rightshift */ |
334 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
335 |
32, /* bitsize */ |
32, /* bitsize */ |
336 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
337 |
0, /* bitpos */ |
0, /* bitpos */ |
338 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
339 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
340 |
"rva32", /* name */ |
"rva32", /* name */ |
341 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
342 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
343 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
344 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
345 |
EMPTY_HOWTO (35), |
EMPTY_HOWTO (35), |
346 |
EMPTY_HOWTO (36), |
EMPTY_HOWTO (36), |
347 |
HOWTO (MIPS_R_PAIR, /* type */ |
HOWTO (MIPS_R_PAIR, /* type */ |
348 |
0, /* rightshift */ |
0, /* rightshift */ |
349 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
350 |
32, /* bitsize */ |
32, /* bitsize */ |
351 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
352 |
0, /* bitpos */ |
0, /* bitpos */ |
353 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
354 |
coff_mips_reloc, /* special_function */ |
coff_mips_reloc, /* special_function */ |
355 |
"PAIR", /* name */ |
"PAIR", /* name */ |
356 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
357 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
358 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
359 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
360 |
}; |
}; |
361 |
|
|
362 |
/* Turn a howto into a reloc nunmber */ |
/* Turn a howto into a reloc nunmber */ |
448 |
|
|
449 |
#ifndef COFF_WITH_PE |
#ifndef COFF_WITH_PE |
450 |
/* If the output symbol is common (in which case this must be a |
/* If the output symbol is common (in which case this must be a |
451 |
relocateable link), we need to add in the final size of the |
relocatable link), we need to add in the final size of the |
452 |
common symbol. */ |
common symbol. */ |
453 |
if (h != NULL && h->root.type == bfd_link_hash_common) |
if (h != NULL && h->root.type == bfd_link_hash_common) |
454 |
*addendp += h->root.u.c.size; |
*addendp += h->root.u.c.size; |
515 |
case BFD_RELOC_MIPS_LITERAL: |
case BFD_RELOC_MIPS_LITERAL: |
516 |
mips_type = MIPS_R_LITERAL; |
mips_type = MIPS_R_LITERAL; |
517 |
break; |
break; |
|
/* FIXME? |
|
|
case BFD_RELOC_16_PCREL_S2: |
|
|
mips_type = MIPS_R_PCREL16; |
|
|
break; |
|
|
case BFD_RELOC_PCREL_HI16_S: |
|
|
mips_type = MIPS_R_RELHI; |
|
|
break; |
|
|
case BFD_RELOC_PCREL_LO16: |
|
|
mips_type = MIPS_R_RELLO; |
|
|
break; |
|
|
case BFD_RELOC_GPREL32: |
|
|
mips_type = MIPS_R_SWITCH; |
|
|
break; |
|
|
*/ |
|
518 |
case BFD_RELOC_RVA: |
case BFD_RELOC_RVA: |
519 |
mips_type = MIPS_R_RVA; |
mips_type = MIPS_R_RVA; |
520 |
break; |
break; |
600 |
#define coff_swap_reloc_out mips_swap_reloc_out |
#define coff_swap_reloc_out mips_swap_reloc_out |
601 |
#define NO_COFF_RELOCS |
#define NO_COFF_RELOCS |
602 |
|
|
603 |
static boolean |
static bfd_boolean |
604 |
coff_pe_mips_relocate_section (output_bfd, info, input_bfd, |
coff_pe_mips_relocate_section (output_bfd, info, input_bfd, |
605 |
input_section, contents, relocs, syms, |
input_section, contents, relocs, syms, |
606 |
sections) |
sections) |
614 |
asection **sections; |
asection **sections; |
615 |
{ |
{ |
616 |
bfd_vma gp; |
bfd_vma gp; |
617 |
boolean gp_undefined; |
bfd_boolean gp_undefined; |
618 |
size_t adjust; |
size_t adjust; |
619 |
struct internal_reloc *rel; |
struct internal_reloc *rel; |
620 |
struct internal_reloc *rel_end; |
struct internal_reloc *rel_end; |
621 |
unsigned int i; |
unsigned int i; |
622 |
boolean got_lo; |
bfd_boolean got_lo; |
623 |
|
|
624 |
if (info->relocateable) |
if (info->relocatable) |
625 |
{ |
{ |
626 |
(*_bfd_error_handler) (_("\ |
(*_bfd_error_handler) |
627 |
%s: `ld -r' not supported with PE MIPS objects\n"), |
(_("%B: `ld -r' not supported with PE MIPS objects\n"), input_bfd); |
|
bfd_archive_filename (input_bfd)); |
|
628 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
629 |
return false; |
return FALSE; |
630 |
} |
} |
631 |
|
|
632 |
BFD_ASSERT (input_bfd->xvec->byteorder |
BFD_ASSERT (input_bfd->xvec->byteorder |
633 |
== output_bfd->xvec->byteorder); |
== output_bfd->xvec->byteorder); |
634 |
|
|
|
#if 0 |
|
|
printf ("dj: relocate %s(%s) %08x\n", |
|
|
input_bfd->filename, input_section->name, |
|
|
input_section->output_section->vma + input_section->output_offset); |
|
|
#endif |
|
|
|
|
635 |
gp = _bfd_get_gp_value (output_bfd); |
gp = _bfd_get_gp_value (output_bfd); |
636 |
if (gp == 0) |
if (gp == 0) |
637 |
gp_undefined = true; |
gp_undefined = TRUE; |
638 |
else |
else |
639 |
gp_undefined = false; |
gp_undefined = FALSE; |
640 |
|
|
641 |
got_lo = false; |
got_lo = FALSE; |
642 |
|
|
643 |
adjust = 0; |
adjust = 0; |
644 |
|
|
680 |
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h, |
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h, |
681 |
sym, &addend); |
sym, &addend); |
682 |
if (howto == NULL) |
if (howto == NULL) |
683 |
return false; |
return FALSE; |
684 |
|
|
685 |
/* If we are doing a relocateable link, then we can just ignore |
/* If we are doing a relocatable link, then we can just ignore |
686 |
a PC relative reloc that is pcrel_offset. It will already |
a PC relative reloc that is pcrel_offset. It will already |
687 |
have the correct value. If this is not a relocateable link, |
have the correct value. If this is not a relocatable link, |
688 |
then we should ignore the symbol value. */ |
then we should ignore the symbol value. */ |
689 |
if (howto->pc_relative && howto->pcrel_offset) |
if (howto->pc_relative && howto->pcrel_offset) |
690 |
{ |
{ |
691 |
if (info->relocateable) |
if (info->relocatable) |
692 |
continue; |
continue; |
693 |
if (sym != NULL && sym->n_scnum != 0) |
if (sym != NULL && sym->n_scnum != 0) |
694 |
addend += sym->n_value; |
addend += sym->n_value; |
728 |
+ sec->output_offset); |
+ sec->output_offset); |
729 |
} |
} |
730 |
|
|
731 |
else if (! info->relocateable) |
else if (! info->relocatable) |
732 |
{ |
{ |
733 |
if (! ((*info->callbacks->undefined_symbol) |
if (! ((*info->callbacks->undefined_symbol) |
734 |
(info, h->root.root.string, input_bfd, input_section, |
(info, h->root.root.string, input_bfd, input_section, |
735 |
rel->r_vaddr - input_section->vma, true))) |
rel->r_vaddr - input_section->vma, TRUE))) |
736 |
return false; |
return FALSE; |
737 |
} |
} |
738 |
} |
} |
739 |
|
|
740 |
src = rel->r_vaddr + input_section->output_section->vma |
src = rel->r_vaddr + input_section->output_section->vma |
741 |
+ input_section->output_offset; |
+ input_section->output_offset; |
|
#if 0 |
|
|
printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n", |
|
|
rel->r_type, howto_table[rel->r_type].name, |
|
|
src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset, |
|
|
h?h->root.root.string:"(none)"); |
|
|
#endif |
|
742 |
|
|
743 |
/* OK, at this point the following variables are set up: |
/* OK, at this point the following variables are set up: |
744 |
src = VMA of the memory we're fixing up |
src = VMA of the memory we're fixing up |
746 |
val = VMA of what we need to refer to |
val = VMA of what we need to refer to |
747 |
*/ |
*/ |
748 |
|
|
749 |
#define UI(x) (*_bfd_error_handler) (_("%s: unimplemented %s\n"), \ |
#define UI(x) (*_bfd_error_handler) (_("%B: unimplemented %s\n"), \ |
750 |
bfd_archive_filename (input_bfd), x); \ |
input_bfd, x); \ |
751 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
752 |
|
|
753 |
switch (rel->r_type) |
switch (rel->r_type) |
772 |
targ = val + (tmp&0x03ffffff)*4; |
targ = val + (tmp&0x03ffffff)*4; |
773 |
if ((src & 0xf0000000) != (targ & 0xf0000000)) |
if ((src & 0xf0000000) != (targ & 0xf0000000)) |
774 |
{ |
{ |
775 |
(*_bfd_error_handler) (_("%s: jump too far away\n"), |
(*_bfd_error_handler) (_("%B: jump too far away\n"), input_bfd); |
|
bfd_archive_filename (input_bfd)); |
|
776 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
777 |
return false; |
return FALSE; |
778 |
} |
} |
779 |
tmp &= 0xfc000000; |
tmp &= 0xfc000000; |
780 |
tmp |= (targ/4) & 0x3ffffff; |
tmp |= (targ/4) & 0x3ffffff; |
798 |
targ = val + low + ((tmp & 0xffff) << 16); |
targ = val + low + ((tmp & 0xffff) << 16); |
799 |
break; |
break; |
800 |
default: |
default: |
801 |
(*_bfd_error_handler) (_("%s: bad pair/reflo after refhi\n"), |
(*_bfd_error_handler) (_("%B: bad pair/reflo after refhi\n"), |
802 |
bfd_archive_filename (input_bfd)); |
input_bfd); |
803 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
804 |
return false; |
return FALSE; |
805 |
} |
} |
806 |
tmp &= 0xffff0000; |
tmp &= 0xffff0000; |
807 |
tmp |= (targ >> 16) & 0xffff; |
tmp |= (targ >> 16) & 0xffff; |
852 |
} |
} |
853 |
} |
} |
854 |
|
|
855 |
return true; |
return TRUE; |
856 |
} |
} |
857 |
|
|
858 |
#define coff_relocate_section coff_pe_mips_relocate_section |
#define coff_relocate_section coff_pe_mips_relocate_section |
863 |
a leading dot for local labels, so if TARGET_UNDERSCORE is defined |
a leading dot for local labels, so if TARGET_UNDERSCORE is defined |
864 |
we treat all symbols starting with L as local. */ |
we treat all symbols starting with L as local. */ |
865 |
|
|
866 |
static boolean coff_mips_is_local_label_name PARAMS ((bfd *, const char *)); |
static bfd_boolean coff_mips_is_local_label_name |
867 |
|
PARAMS ((bfd *, const char *)); |
868 |
|
|
869 |
static boolean |
static bfd_boolean |
870 |
coff_mips_is_local_label_name (abfd, name) |
coff_mips_is_local_label_name (abfd, name) |
871 |
bfd *abfd; |
bfd *abfd; |
872 |
const char *name; |
const char *name; |
873 |
{ |
{ |
874 |
if (name[0] == 'L') |
if (name[0] == 'L') |
875 |
return true; |
return TRUE; |
876 |
|
|
877 |
return _bfd_coff_is_local_label_name (abfd, name); |
return _bfd_coff_is_local_label_name (abfd, name); |
878 |
} |
} |