1 |
/* BFD back-end for Intel 386 COFF files. |
/* BFD back-end for Intel 386 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, 2002 |
2000, 2001, 2002, 2003, 2004 |
4 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
5 |
Written by Cygnus Support. |
Written by Cygnus Support. |
6 |
|
|
7 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
8 |
|
|
9 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
10 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
11 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
12 |
(at your option) any later version. |
(at your option) any later version. |
13 |
|
|
14 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
15 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 |
GNU General Public License for more details. |
GNU General Public License for more details. |
18 |
|
|
19 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
20 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
21 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
22 |
|
|
23 |
#include "bfd.h" |
#include "bfd.h" |
24 |
#include "sysdep.h" |
#include "sysdep.h" |
56 |
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 |
57 |
any desired offset. Ian Taylor, Cygnus Support. */ |
any desired offset. Ian Taylor, Cygnus Support. */ |
58 |
|
|
59 |
/* If we are producing relocateable output, we need to do some |
/* If we are producing relocatable output, we need to do some |
60 |
adjustments to the object file that are not done by the |
adjustments to the object file that are not done by the |
61 |
bfd_perform_relocation function. This function is called by every |
bfd_perform_relocation function. This function is called by every |
62 |
reloc type to make any required adjustments. */ |
reloc type to make any required adjustments. */ |
103 |
{ |
{ |
104 |
/* For some reason bfd_perform_relocation always effectively |
/* For some reason bfd_perform_relocation always effectively |
105 |
ignores the addend for a COFF target when producing |
ignores the addend for a COFF target when producing |
106 |
relocateable output. This seems to be always wrong for 386 |
relocatable output. This seems to be always wrong for 386 |
107 |
COFF, so we handle the addend here instead. */ |
COFF, so we handle the addend here instead. */ |
108 |
#ifdef COFF_WITH_PE |
#ifdef COFF_WITH_PE |
109 |
if (output_bfd == (bfd *) NULL) |
if (output_bfd == (bfd *) NULL) |
119 |
here. */ |
here. */ |
120 |
if (howto->pc_relative && howto->pcrel_offset) |
if (howto->pc_relative && howto->pcrel_offset) |
121 |
diff = -(1 << howto->size); |
diff = -(1 << howto->size); |
122 |
|
else if (symbol->flags & BSF_WEAK) |
123 |
|
diff = reloc_entry->addend - symbol->value; |
124 |
else |
else |
125 |
diff = -reloc_entry->addend; |
diff = -reloc_entry->addend; |
126 |
} |
} |
181 |
} |
} |
182 |
|
|
183 |
#ifdef COFF_WITH_PE |
#ifdef COFF_WITH_PE |
184 |
/* Return true if this relocation should appear in the output .reloc |
/* Return TRUE if this relocation should appear in the output .reloc |
185 |
section. */ |
section. */ |
186 |
|
|
187 |
static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *)); |
static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *)); |
188 |
|
|
189 |
static boolean in_reloc_p (abfd, howto) |
static bfd_boolean in_reloc_p (abfd, howto) |
190 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd * abfd ATTRIBUTE_UNUSED; |
191 |
reloc_howto_type *howto; |
reloc_howto_type *howto; |
192 |
{ |
{ |
195 |
#endif /* COFF_WITH_PE */ |
#endif /* COFF_WITH_PE */ |
196 |
|
|
197 |
#ifndef PCRELOFFSET |
#ifndef PCRELOFFSET |
198 |
#define PCRELOFFSET false |
#define PCRELOFFSET FALSE |
199 |
#endif |
#endif |
200 |
|
|
201 |
static reloc_howto_type howto_table[] = |
static reloc_howto_type howto_table[] = |
210 |
0, /* rightshift */ |
0, /* rightshift */ |
211 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
212 |
32, /* bitsize */ |
32, /* bitsize */ |
213 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
214 |
0, /* bitpos */ |
0, /* bitpos */ |
215 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
216 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
217 |
"dir32", /* name */ |
"dir32", /* name */ |
218 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
219 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
220 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
221 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
222 |
/* PE IMAGE_REL_I386_DIR32NB relocation (7). */ |
/* PE IMAGE_REL_I386_DIR32NB relocation (7). */ |
223 |
HOWTO (R_IMAGEBASE, /* type */ |
HOWTO (R_IMAGEBASE, /* type */ |
224 |
0, /* rightshift */ |
0, /* rightshift */ |
225 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
226 |
32, /* bitsize */ |
32, /* bitsize */ |
227 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
228 |
0, /* bitpos */ |
0, /* bitpos */ |
229 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
230 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
231 |
"rva32", /* name */ |
"rva32", /* name */ |
232 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
233 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
234 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
235 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
236 |
EMPTY_HOWTO (010), |
EMPTY_HOWTO (010), |
237 |
EMPTY_HOWTO (011), |
EMPTY_HOWTO (011), |
238 |
EMPTY_HOWTO (012), |
EMPTY_HOWTO (012), |
239 |
|
#ifdef COFF_WITH_PE |
240 |
|
/* 32-bit longword section relative relocation (013). */ |
241 |
|
HOWTO (R_SECREL32, /* type */ |
242 |
|
0, /* rightshift */ |
243 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
244 |
|
32, /* bitsize */ |
245 |
|
FALSE, /* pc_relative */ |
246 |
|
0, /* bitpos */ |
247 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
248 |
|
coff_i386_reloc, /* special_function */ |
249 |
|
"secrel32", /* name */ |
250 |
|
TRUE, /* partial_inplace */ |
251 |
|
0xffffffff, /* src_mask */ |
252 |
|
0xffffffff, /* dst_mask */ |
253 |
|
TRUE), /* pcrel_offset */ |
254 |
|
#else |
255 |
EMPTY_HOWTO (013), |
EMPTY_HOWTO (013), |
256 |
|
#endif |
257 |
EMPTY_HOWTO (014), |
EMPTY_HOWTO (014), |
258 |
EMPTY_HOWTO (015), |
EMPTY_HOWTO (015), |
259 |
EMPTY_HOWTO (016), |
EMPTY_HOWTO (016), |
262 |
0, /* rightshift */ |
0, /* rightshift */ |
263 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
264 |
8, /* bitsize */ |
8, /* bitsize */ |
265 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
266 |
0, /* bitpos */ |
0, /* bitpos */ |
267 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
268 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
269 |
"8", /* name */ |
"8", /* name */ |
270 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
271 |
0x000000ff, /* src_mask */ |
0x000000ff, /* src_mask */ |
272 |
0x000000ff, /* dst_mask */ |
0x000000ff, /* dst_mask */ |
273 |
PCRELOFFSET), /* pcrel_offset */ |
PCRELOFFSET), /* pcrel_offset */ |
276 |
0, /* rightshift */ |
0, /* rightshift */ |
277 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
278 |
16, /* bitsize */ |
16, /* bitsize */ |
279 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
280 |
0, /* bitpos */ |
0, /* bitpos */ |
281 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
282 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
283 |
"16", /* name */ |
"16", /* name */ |
284 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
285 |
0x0000ffff, /* src_mask */ |
0x0000ffff, /* src_mask */ |
286 |
0x0000ffff, /* dst_mask */ |
0x0000ffff, /* dst_mask */ |
287 |
PCRELOFFSET), /* pcrel_offset */ |
PCRELOFFSET), /* pcrel_offset */ |
290 |
0, /* rightshift */ |
0, /* rightshift */ |
291 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
292 |
32, /* bitsize */ |
32, /* bitsize */ |
293 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
294 |
0, /* bitpos */ |
0, /* bitpos */ |
295 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
296 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
297 |
"32", /* name */ |
"32", /* name */ |
298 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
299 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
300 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
301 |
PCRELOFFSET), /* pcrel_offset */ |
PCRELOFFSET), /* pcrel_offset */ |
304 |
0, /* rightshift */ |
0, /* rightshift */ |
305 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
306 |
8, /* bitsize */ |
8, /* bitsize */ |
307 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
308 |
0, /* bitpos */ |
0, /* bitpos */ |
309 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
310 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
311 |
"DISP8", /* name */ |
"DISP8", /* name */ |
312 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
313 |
0x000000ff, /* src_mask */ |
0x000000ff, /* src_mask */ |
314 |
0x000000ff, /* dst_mask */ |
0x000000ff, /* dst_mask */ |
315 |
PCRELOFFSET), /* pcrel_offset */ |
PCRELOFFSET), /* pcrel_offset */ |
318 |
0, /* rightshift */ |
0, /* rightshift */ |
319 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
320 |
16, /* bitsize */ |
16, /* bitsize */ |
321 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
322 |
0, /* bitpos */ |
0, /* bitpos */ |
323 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
324 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
325 |
"DISP16", /* name */ |
"DISP16", /* name */ |
326 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
327 |
0x0000ffff, /* src_mask */ |
0x0000ffff, /* src_mask */ |
328 |
0x0000ffff, /* dst_mask */ |
0x0000ffff, /* dst_mask */ |
329 |
PCRELOFFSET), /* pcrel_offset */ |
PCRELOFFSET), /* pcrel_offset */ |
332 |
0, /* rightshift */ |
0, /* rightshift */ |
333 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
334 |
32, /* bitsize */ |
32, /* bitsize */ |
335 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
336 |
0, /* bitpos */ |
0, /* bitpos */ |
337 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
338 |
coff_i386_reloc, /* special_function */ |
coff_i386_reloc, /* special_function */ |
339 |
"DISP32", /* name */ |
"DISP32", /* name */ |
340 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
341 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
342 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
343 |
PCRELOFFSET) /* pcrel_offset */ |
PCRELOFFSET) /* pcrel_offset */ |
405 |
|
|
406 |
/* The PE relocate section routine. The only difference between this |
/* The PE relocate section routine. The only difference between this |
407 |
and the regular routine is that we don't want to do anything for a |
and the regular routine is that we don't want to do anything for a |
408 |
relocateable link. */ |
relocatable link. */ |
409 |
|
|
410 |
static boolean coff_pe_i386_relocate_section |
static bfd_boolean coff_pe_i386_relocate_section |
411 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
412 |
struct internal_reloc *, struct internal_syment *, asection **)); |
struct internal_reloc *, struct internal_syment *, asection **)); |
413 |
|
|
414 |
static boolean |
static bfd_boolean |
415 |
coff_pe_i386_relocate_section (output_bfd, info, input_bfd, |
coff_pe_i386_relocate_section (output_bfd, info, input_bfd, |
416 |
input_section, contents, relocs, syms, |
input_section, contents, relocs, syms, |
417 |
sections) |
sections) |
424 |
struct internal_syment *syms; |
struct internal_syment *syms; |
425 |
asection **sections; |
asection **sections; |
426 |
{ |
{ |
427 |
if (info->relocateable) |
if (info->relocatable) |
428 |
return true; |
return TRUE; |
429 |
|
|
430 |
return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd, |
return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd, |
431 |
input_section, contents, |
input_section, contents, |
489 |
|
|
490 |
#ifndef COFF_WITH_PE |
#ifndef COFF_WITH_PE |
491 |
/* 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 |
492 |
relocateable link), we need to add in the final size of the |
relocatable link), we need to add in the final size of the |
493 |
common symbol. */ |
common symbol. */ |
494 |
if (h != NULL && h->root.type == bfd_link_hash_common) |
if (h != NULL && h->root.type == bfd_link_hash_common) |
495 |
*addendp += h->root.u.c.size; |
*addendp += h->root.u.c.size; |
516 |
{ |
{ |
517 |
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase; |
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase; |
518 |
} |
} |
519 |
|
|
520 |
|
if (rel->r_type == R_SECREL32) |
521 |
|
{ |
522 |
|
bfd_vma osect_vma; |
523 |
|
|
524 |
|
if (h && (h->type == bfd_link_hash_defined |
525 |
|
|| h->type == bfd_link_hash_defweak)) |
526 |
|
osect_vma = h->root.u.def.section->output_section->vma; |
527 |
|
else |
528 |
|
{ |
529 |
|
asection *sec; |
530 |
|
int i; |
531 |
|
|
532 |
|
/* Sigh, the only way to get the section to offset against |
533 |
|
is to find it the hard way. */ |
534 |
|
|
535 |
|
for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++) |
536 |
|
sec = sec->next; |
537 |
|
|
538 |
|
osect_vma = sec->output_section->vma; |
539 |
|
} |
540 |
|
|
541 |
|
*addendp -= osect_vma; |
542 |
|
} |
543 |
#endif |
#endif |
544 |
|
|
545 |
return howto; |
return howto; |
568 |
return howto_table + R_RELBYTE; |
return howto_table + R_RELBYTE; |
569 |
case BFD_RELOC_8_PCREL: |
case BFD_RELOC_8_PCREL: |
570 |
return howto_table + R_PCRBYTE; |
return howto_table + R_PCRBYTE; |
571 |
|
#ifdef COFF_WITH_PE |
572 |
|
case BFD_RELOC_32_SECREL: |
573 |
|
return howto_table + R_SECREL32; |
574 |
|
#endif |
575 |
default: |
default: |
576 |
BFD_FAIL (); |
BFD_FAIL (); |
577 |
return 0; |
return 0; |
586 |
a leading dot for local labels, so if TARGET_UNDERSCORE is defined |
a leading dot for local labels, so if TARGET_UNDERSCORE is defined |
587 |
we treat all symbols starting with L as local. */ |
we treat all symbols starting with L as local. */ |
588 |
|
|
589 |
static boolean coff_i386_is_local_label_name PARAMS ((bfd *, const char *)); |
static bfd_boolean coff_i386_is_local_label_name |
590 |
|
PARAMS ((bfd *, const char *)); |
591 |
|
|
592 |
static boolean |
static bfd_boolean |
593 |
coff_i386_is_local_label_name (abfd, name) |
coff_i386_is_local_label_name (abfd, name) |
594 |
bfd *abfd; |
bfd *abfd; |
595 |
const char *name; |
const char *name; |
596 |
{ |
{ |
597 |
if (name[0] == 'L') |
if (name[0] == 'L') |
598 |
return true; |
return TRUE; |
599 |
|
|
600 |
return _bfd_coff_is_local_label_name (abfd, name); |
return _bfd_coff_is_local_label_name (abfd, name); |
601 |
} |
} |