1 |
/* BFD back-end for AMD 29000 COFF binaries. |
/* BFD back-end for AMD 29000 COFF binaries. |
2 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001, |
3 |
|
2002, 2003, 2004 |
4 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
5 |
Contributed by David Wood at New York University 7/8/91. |
Contributed by David Wood at New York University 7/8/91. |
6 |
|
|
32 |
static long get_symbol_value PARAMS ((asymbol *)); |
static long get_symbol_value PARAMS ((asymbol *)); |
33 |
static bfd_reloc_status_type a29k_reloc |
static bfd_reloc_status_type a29k_reloc |
34 |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
35 |
static boolean coff_a29k_relocate_section |
static bfd_boolean coff_a29k_relocate_section |
36 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
37 |
struct internal_reloc *, struct internal_syment *, asection **)); |
struct internal_reloc *, struct internal_syment *, asection **)); |
38 |
static boolean coff_a29k_adjust_symndx |
static bfd_boolean coff_a29k_adjust_symndx |
39 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, |
40 |
struct internal_reloc *, boolean *)); |
struct internal_reloc *, bfd_boolean *)); |
41 |
static void reloc_processing |
static void reloc_processing |
42 |
PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *)); |
PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *)); |
43 |
|
|
83 |
{ |
{ |
84 |
/* The consth relocation comes in two parts, we have to remember |
/* The consth relocation comes in two parts, we have to remember |
85 |
the state between calls, in these variables. */ |
the state between calls, in these variables. */ |
86 |
static boolean part1_consth_active = false; |
static bfd_boolean part1_consth_active = FALSE; |
87 |
static unsigned long part1_consth_value; |
static unsigned long part1_consth_value; |
88 |
unsigned long insn; |
unsigned long insn; |
89 |
unsigned long sym_value; |
unsigned long sym_value; |
108 |
/* Keep the state machine happy in case we're called again. */ |
/* Keep the state machine happy in case we're called again. */ |
109 |
if (r_type == R_IHIHALF) |
if (r_type == R_IHIHALF) |
110 |
{ |
{ |
111 |
part1_consth_active = true; |
part1_consth_active = TRUE; |
112 |
part1_consth_value = 0; |
part1_consth_value = 0; |
113 |
} |
} |
114 |
return bfd_reloc_undefined; |
return bfd_reloc_undefined; |
116 |
|
|
117 |
if ((part1_consth_active) && (r_type != R_IHCONST)) |
if ((part1_consth_active) && (r_type != R_IHCONST)) |
118 |
{ |
{ |
119 |
part1_consth_active = false; |
part1_consth_active = FALSE; |
120 |
*error_message = (char *) _("Missing IHCONST"); |
*error_message = (char *) _("Missing IHCONST"); |
121 |
|
|
122 |
return bfd_reloc_dangerous; |
return bfd_reloc_dangerous; |
168 |
insn = bfd_get_32 (abfd, hit_data); |
insn = bfd_get_32 (abfd, hit_data); |
169 |
/* consth, part 1 |
/* consth, part 1 |
170 |
Just get the symbol value that is referenced. */ |
Just get the symbol value that is referenced. */ |
171 |
part1_consth_active = true; |
part1_consth_active = TRUE; |
172 |
part1_consth_value = sym_value + reloc_entry->addend; |
part1_consth_value = sym_value + reloc_entry->addend; |
173 |
/* Don't modify insn until R_IHCONST. */ |
/* Don't modify insn until R_IHCONST. */ |
174 |
break; |
break; |
187 |
unsigned_value += part1_consth_value; |
unsigned_value += part1_consth_value; |
188 |
unsigned_value = unsigned_value >> 16; |
unsigned_value = unsigned_value >> 16; |
189 |
insn = INSERT_HWORD(insn, unsigned_value); |
insn = INSERT_HWORD(insn, unsigned_value); |
190 |
part1_consth_active = false; |
part1_consth_active = FALSE; |
191 |
bfd_put_32 (abfd, (bfd_vma) insn, hit_data); |
bfd_put_32 (abfd, (bfd_vma) insn, hit_data); |
192 |
break; |
break; |
193 |
case R_BYTE: |
case R_BYTE: |
220 |
/*FIXME: I'm not real sure about this table. */ |
/*FIXME: I'm not real sure about this table. */ |
221 |
static reloc_howto_type howto_table[] = |
static reloc_howto_type howto_table[] = |
222 |
{ |
{ |
223 |
{R_ABS, 0, 3, 32, false, 0, complain_overflow_bitfield,a29k_reloc,"ABS", true, 0xffffffff,0xffffffff, false}, |
{R_ABS, 0, 3, 32, FALSE, 0, complain_overflow_bitfield,a29k_reloc,"ABS", TRUE, 0xffffffff,0xffffffff, FALSE}, |
224 |
EMPTY_HOWTO (1), |
EMPTY_HOWTO (1), |
225 |
EMPTY_HOWTO (2), |
EMPTY_HOWTO (2), |
226 |
EMPTY_HOWTO (3), |
EMPTY_HOWTO (3), |
244 |
EMPTY_HOWTO (21), |
EMPTY_HOWTO (21), |
245 |
EMPTY_HOWTO (22), |
EMPTY_HOWTO (22), |
246 |
EMPTY_HOWTO (23), |
EMPTY_HOWTO (23), |
247 |
{R_IREL, 0, 3, 32, true, 0, complain_overflow_signed,a29k_reloc,"IREL", true, 0xffffffff,0xffffffff, false}, |
{R_IREL, 0, 3, 32, TRUE, 0, complain_overflow_signed,a29k_reloc,"IREL", TRUE, 0xffffffff,0xffffffff, FALSE}, |
248 |
{R_IABS, 0, 3, 32, false, 0, complain_overflow_bitfield, a29k_reloc,"IABS", true, 0xffffffff,0xffffffff, false}, |
{R_IABS, 0, 3, 32, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"IABS", TRUE, 0xffffffff,0xffffffff, FALSE}, |
249 |
{R_ILOHALF, 0, 3, 16, true, 0, complain_overflow_signed, a29k_reloc,"ILOHALF", true, 0x0000ffff,0x0000ffff, false}, |
{R_ILOHALF, 0, 3, 16, TRUE, 0, complain_overflow_signed, a29k_reloc,"ILOHALF", TRUE, 0x0000ffff,0x0000ffff, FALSE}, |
250 |
{R_IHIHALF, 0, 3, 16, true, 16, complain_overflow_signed, a29k_reloc,"IHIHALF", true, 0xffff0000,0xffff0000, false}, |
{R_IHIHALF, 0, 3, 16, TRUE, 16, complain_overflow_signed, a29k_reloc,"IHIHALF", TRUE, 0xffff0000,0xffff0000, FALSE}, |
251 |
{R_IHCONST, 0, 3, 16, true, 0, complain_overflow_signed, a29k_reloc,"IHCONST", true, 0xffff0000,0xffff0000, false}, |
{R_IHCONST, 0, 3, 16, TRUE, 0, complain_overflow_signed, a29k_reloc,"IHCONST", TRUE, 0xffff0000,0xffff0000, FALSE}, |
252 |
{R_BYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, a29k_reloc,"BYTE", true, 0x000000ff,0x000000ff, false}, |
{R_BYTE, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"BYTE", TRUE, 0x000000ff,0x000000ff, FALSE}, |
253 |
{R_HWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, a29k_reloc,"HWORD", true, 0x0000ffff,0x0000ffff, false}, |
{R_HWORD, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"HWORD", TRUE, 0x0000ffff,0x0000ffff, FALSE}, |
254 |
{R_WORD, 0, 2, 32, false, 0, complain_overflow_bitfield, a29k_reloc,"WORD", true, 0xffffffff,0xffffffff, false}, |
{R_WORD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"WORD", TRUE, 0xffffffff,0xffffffff, FALSE}, |
255 |
}; |
}; |
256 |
|
|
257 |
#define BADMAG(x) A29KBADMAG(x) |
#define BADMAG(x) A29KBADMAG(x) |
311 |
|
|
312 |
/* The reloc processing routine for the optimized COFF linker. */ |
/* The reloc processing routine for the optimized COFF linker. */ |
313 |
|
|
314 |
static boolean |
static bfd_boolean |
315 |
coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section, |
coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section, |
316 |
contents, relocs, syms, sections) |
contents, relocs, syms, sections) |
317 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
bfd *output_bfd ATTRIBUTE_UNUSED; |
325 |
{ |
{ |
326 |
struct internal_reloc *rel; |
struct internal_reloc *rel; |
327 |
struct internal_reloc *relend; |
struct internal_reloc *relend; |
328 |
boolean hihalf; |
bfd_boolean hihalf; |
329 |
bfd_vma hihalf_val; |
bfd_vma hihalf_val; |
330 |
|
|
331 |
/* If we are performing a relocateable link, we don't need to do a |
/* If we are performing a relocatable link, we don't need to do a |
332 |
thing. The caller will take care of adjusting the reloc |
thing. The caller will take care of adjusting the reloc |
333 |
addresses and symbol indices. */ |
addresses and symbol indices. */ |
334 |
if (info->relocateable) |
if (info->relocatable) |
335 |
return true; |
return TRUE; |
336 |
|
|
337 |
hihalf = false; |
hihalf = FALSE; |
338 |
hihalf_val = 0; |
hihalf_val = 0; |
339 |
|
|
340 |
rel = relocs; |
rel = relocs; |
347 |
struct internal_syment *sym; |
struct internal_syment *sym; |
348 |
asection *sec; |
asection *sec; |
349 |
bfd_vma val; |
bfd_vma val; |
350 |
boolean overflow; |
bfd_boolean overflow; |
351 |
unsigned long insn; |
unsigned long insn; |
352 |
long signed_value; |
long signed_value; |
353 |
unsigned long unsigned_value; |
unsigned long unsigned_value; |
398 |
{ |
{ |
399 |
if (! ((*info->callbacks->undefined_symbol) |
if (! ((*info->callbacks->undefined_symbol) |
400 |
(info, h->root.root.string, input_bfd, input_section, |
(info, h->root.root.string, input_bfd, input_section, |
401 |
rel->r_vaddr - input_section->vma, true))) |
rel->r_vaddr - input_section->vma, TRUE))) |
402 |
return false; |
return FALSE; |
403 |
} |
} |
404 |
} |
} |
405 |
|
|
408 |
if (! ((*info->callbacks->reloc_dangerous) |
if (! ((*info->callbacks->reloc_dangerous) |
409 |
(info, _("missing IHCONST reloc"), input_bfd, |
(info, _("missing IHCONST reloc"), input_bfd, |
410 |
input_section, rel->r_vaddr - input_section->vma))) |
input_section, rel->r_vaddr - input_section->vma))) |
411 |
return false; |
return FALSE; |
412 |
hihalf = false; |
hihalf = FALSE; |
413 |
} |
} |
414 |
} |
} |
415 |
|
|
416 |
overflow = false; |
overflow = FALSE; |
417 |
|
|
418 |
switch (rel->r_type) |
switch (rel->r_type) |
419 |
{ |
{ |
420 |
default: |
default: |
421 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
422 |
return false; |
return FALSE; |
423 |
|
|
424 |
case R_IREL: |
case R_IREL: |
425 |
insn = bfd_get_32 (input_bfd, loc); |
insn = bfd_get_32 (input_bfd, loc); |
466 |
+ (rel->r_vaddr - input_section->vma)); |
+ (rel->r_vaddr - input_section->vma)); |
467 |
if (signed_value > 0x1ffff || signed_value < - 0x20000) |
if (signed_value > 0x1ffff || signed_value < - 0x20000) |
468 |
{ |
{ |
469 |
overflow = true; |
overflow = TRUE; |
470 |
signed_value = 0; |
signed_value = 0; |
471 |
} |
} |
472 |
} |
} |
488 |
|
|
489 |
case R_IHIHALF: |
case R_IHIHALF: |
490 |
/* Save the value for the R_IHCONST reloc. */ |
/* Save the value for the R_IHCONST reloc. */ |
491 |
hihalf = true; |
hihalf = TRUE; |
492 |
hihalf_val = val; |
hihalf_val = val; |
493 |
break; |
break; |
494 |
|
|
498 |
if (! ((*info->callbacks->reloc_dangerous) |
if (! ((*info->callbacks->reloc_dangerous) |
499 |
(info, _("missing IHIHALF reloc"), input_bfd, |
(info, _("missing IHIHALF reloc"), input_bfd, |
500 |
input_section, rel->r_vaddr - input_section->vma))) |
input_section, rel->r_vaddr - input_section->vma))) |
501 |
return false; |
return FALSE; |
502 |
hihalf_val = 0; |
hihalf_val = 0; |
503 |
} |
} |
504 |
|
|
508 |
insn = INSERT_HWORD (insn, unsigned_value); |
insn = INSERT_HWORD (insn, unsigned_value); |
509 |
bfd_put_32 (input_bfd, (bfd_vma) insn, loc); |
bfd_put_32 (input_bfd, (bfd_vma) insn, loc); |
510 |
|
|
511 |
hihalf = false; |
hihalf = FALSE; |
512 |
|
|
513 |
break; |
break; |
514 |
|
|
518 |
rstat = _bfd_relocate_contents (howto_table + rel->r_type, |
rstat = _bfd_relocate_contents (howto_table + rel->r_type, |
519 |
input_bfd, val, loc); |
input_bfd, val, loc); |
520 |
if (rstat == bfd_reloc_overflow) |
if (rstat == bfd_reloc_overflow) |
521 |
overflow = true; |
overflow = TRUE; |
522 |
else if (rstat != bfd_reloc_ok) |
else if (rstat != bfd_reloc_ok) |
523 |
abort (); |
abort (); |
524 |
break; |
break; |
532 |
if (symndx == -1) |
if (symndx == -1) |
533 |
name = "*ABS*"; |
name = "*ABS*"; |
534 |
else if (h != NULL) |
else if (h != NULL) |
535 |
name = h->root.root.string; |
name = NULL; |
536 |
else if (sym == NULL) |
else if (sym == NULL) |
537 |
name = "*unknown*"; |
name = "*unknown*"; |
538 |
else if (sym->_n._n_n._n_zeroes == 0 |
else if (sym->_n._n_n._n_zeroes == 0 |
546 |
} |
} |
547 |
|
|
548 |
if (! ((*info->callbacks->reloc_overflow) |
if (! ((*info->callbacks->reloc_overflow) |
549 |
(info, name, howto_table[rel->r_type].name, (bfd_vma) 0, |
(info, (h ? &h->root : NULL), name, |
550 |
input_bfd, input_section, |
howto_table[rel->r_type].name, (bfd_vma) 0, input_bfd, |
551 |
rel->r_vaddr - input_section->vma))) |
input_section, rel->r_vaddr - input_section->vma))) |
552 |
return false; |
return FALSE; |
553 |
} |
} |
554 |
} |
} |
555 |
|
|
556 |
return true; |
return TRUE; |
557 |
} |
} |
558 |
|
|
559 |
#define coff_relocate_section coff_a29k_relocate_section |
#define coff_relocate_section coff_a29k_relocate_section |
561 |
/* We don't want to change the symndx of a R_IHCONST reloc, since it |
/* We don't want to change the symndx of a R_IHCONST reloc, since it |
562 |
is actually an addend, not a symbol index at all. */ |
is actually an addend, not a symbol index at all. */ |
563 |
|
|
564 |
static boolean |
static bfd_boolean |
565 |
coff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp) |
coff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp) |
566 |
bfd *obfd ATTRIBUTE_UNUSED; |
bfd *obfd ATTRIBUTE_UNUSED; |
567 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
568 |
bfd *ibfd ATTRIBUTE_UNUSED; |
bfd *ibfd ATTRIBUTE_UNUSED; |
569 |
asection *sec ATTRIBUTE_UNUSED; |
asection *sec ATTRIBUTE_UNUSED; |
570 |
struct internal_reloc *irel; |
struct internal_reloc *irel; |
571 |
boolean *adjustedp; |
bfd_boolean *adjustedp; |
572 |
{ |
{ |
573 |
if (irel->r_type == R_IHCONST) |
if (irel->r_type == R_IHCONST) |
574 |
*adjustedp = true; |
*adjustedp = TRUE; |
575 |
else |
else |
576 |
*adjustedp = false; |
*adjustedp = FALSE; |
577 |
return true; |
return TRUE; |
578 |
} |
} |
579 |
|
|
580 |
#define coff_adjust_symndx coff_a29k_adjust_symndx |
#define coff_adjust_symndx coff_a29k_adjust_symndx |
581 |
|
|
582 |
#include "coffcode.h" |
#include "coffcode.h" |
583 |
|
|
584 |
CREATE_BIG_COFF_TARGET_VEC (a29kcoff_big_vec, "coff-a29k-big", 0, SEC_READONLY, '_', NULL) |
CREATE_BIG_COFF_TARGET_VEC (a29kcoff_big_vec, "coff-a29k-big", 0, SEC_READONLY, '_', NULL, COFF_SWAP_TABLE) |