12159047fSniklas /* BFD back-end for AMD 29000 COFF binaries.
2*007c2a45Smiod Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
3*007c2a45Smiod 2002, 2003
4b305b0f1Sespie Free Software Foundation, Inc.
52159047fSniklas Contributed by David Wood at New York University 7/8/91.
62159047fSniklas
72159047fSniklas This file is part of BFD, the Binary File Descriptor library.
82159047fSniklas
92159047fSniklas This program is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2 of the License, or
122159047fSniklas (at your option) any later version.
132159047fSniklas
142159047fSniklas This program is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas
192159047fSniklas You should have received a copy of the GNU General Public License
202159047fSniklas along with this program; if not, write to the Free Software
212159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
222159047fSniklas
232159047fSniklas #define A29K 1
242159047fSniklas
252159047fSniklas #include "bfd.h"
262159047fSniklas #include "sysdep.h"
272159047fSniklas #include "libbfd.h"
282159047fSniklas #include "coff/a29k.h"
292159047fSniklas #include "coff/internal.h"
302159047fSniklas #include "libcoff.h"
312159047fSniklas
322159047fSniklas static long get_symbol_value PARAMS ((asymbol *));
332159047fSniklas static bfd_reloc_status_type a29k_reloc
342159047fSniklas PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
35c074d1c9Sdrahn static bfd_boolean coff_a29k_relocate_section
362159047fSniklas PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
372159047fSniklas struct internal_reloc *, struct internal_syment *, asection **));
38c074d1c9Sdrahn static bfd_boolean coff_a29k_adjust_symndx
392159047fSniklas PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
40c074d1c9Sdrahn struct internal_reloc *, bfd_boolean *));
41c074d1c9Sdrahn static void reloc_processing
42c074d1c9Sdrahn PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
432159047fSniklas
442159047fSniklas #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
452159047fSniklas
462159047fSniklas #define INSERT_HWORD(WORD,HWORD) \
472159047fSniklas (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))
482159047fSniklas #define EXTRACT_HWORD(WORD) \
492159047fSniklas ((((WORD) & 0x00ff0000) >> 8) | ((WORD) & 0xff))
502159047fSniklas #define SIGN_EXTEND_HWORD(HWORD) \
51b55d4692Sfgsch (((HWORD) ^ 0x8000) - 0x8000)
522159047fSniklas
53c074d1c9Sdrahn /* Provided the symbol, returns the value reffed. */
54c074d1c9Sdrahn
552159047fSniklas static long
get_symbol_value(symbol)562159047fSniklas get_symbol_value (symbol)
572159047fSniklas asymbol *symbol;
582159047fSniklas {
592159047fSniklas long relocation = 0;
602159047fSniklas
612159047fSniklas if (bfd_is_com_section (symbol->section))
622159047fSniklas relocation = 0;
632159047fSniklas else
642159047fSniklas relocation = symbol->value +
652159047fSniklas symbol->section->output_section->vma +
662159047fSniklas symbol->section->output_offset;
67c074d1c9Sdrahn
68c074d1c9Sdrahn return relocation;
692159047fSniklas }
702159047fSniklas
71c074d1c9Sdrahn /* This function is in charge of performing all the 29k relocations. */
722159047fSniklas
732159047fSniklas static bfd_reloc_status_type
a29k_reloc(abfd,reloc_entry,symbol_in,data,input_section,output_bfd,error_message)742159047fSniklas a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
752159047fSniklas error_message)
762159047fSniklas bfd *abfd;
772159047fSniklas arelent *reloc_entry;
782159047fSniklas asymbol *symbol_in;
792159047fSniklas PTR data;
802159047fSniklas asection *input_section;
812159047fSniklas bfd *output_bfd;
822159047fSniklas char **error_message;
832159047fSniklas {
84c074d1c9Sdrahn /* The consth relocation comes in two parts, we have to remember
85c074d1c9Sdrahn the state between calls, in these variables. */
86c074d1c9Sdrahn static bfd_boolean part1_consth_active = FALSE;
872159047fSniklas static unsigned long part1_consth_value;
882159047fSniklas unsigned long insn;
892159047fSniklas unsigned long sym_value;
902159047fSniklas unsigned long unsigned_value;
912159047fSniklas unsigned short r_type;
922159047fSniklas long signed_value;
932159047fSniklas unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
942159047fSniklas bfd_byte *hit_data =addr + (bfd_byte *) (data);
952159047fSniklas
962159047fSniklas r_type = reloc_entry->howto->type;
972159047fSniklas
98b55d4692Sfgsch if (output_bfd)
99b55d4692Sfgsch {
100c074d1c9Sdrahn /* Partial linking - do nothing. */
1012159047fSniklas reloc_entry->address += input_section->output_offset;
1022159047fSniklas return bfd_reloc_ok;
1032159047fSniklas }
1042159047fSniklas
1052159047fSniklas if (symbol_in != NULL
1062159047fSniklas && bfd_is_und_section (symbol_in->section))
1072159047fSniklas {
108c074d1c9Sdrahn /* Keep the state machine happy in case we're called again. */
1092159047fSniklas if (r_type == R_IHIHALF)
1102159047fSniklas {
111c074d1c9Sdrahn part1_consth_active = TRUE;
1122159047fSniklas part1_consth_value = 0;
1132159047fSniklas }
114c074d1c9Sdrahn return bfd_reloc_undefined;
1152159047fSniklas }
1162159047fSniklas
1172159047fSniklas if ((part1_consth_active) && (r_type != R_IHCONST))
1182159047fSniklas {
119c074d1c9Sdrahn part1_consth_active = FALSE;
120b305b0f1Sespie *error_message = (char *) _("Missing IHCONST");
121c074d1c9Sdrahn
122c074d1c9Sdrahn return bfd_reloc_dangerous;
1232159047fSniklas }
1242159047fSniklas
1252159047fSniklas sym_value = get_symbol_value(symbol_in);
1262159047fSniklas
1272159047fSniklas switch (r_type)
1282159047fSniklas {
1292159047fSniklas case R_IREL:
1302159047fSniklas insn = bfd_get_32 (abfd, hit_data);
131c074d1c9Sdrahn /* Take the value in the field and sign extend it. */
1322159047fSniklas signed_value = EXTRACT_HWORD(insn);
1332159047fSniklas signed_value = SIGN_EXTEND_HWORD(signed_value);
1342159047fSniklas signed_value <<= 2;
1352159047fSniklas
1362159047fSniklas /* See the note on the R_IREL reloc in coff_a29k_relocate_section. */
1372159047fSniklas if (signed_value == - (long) reloc_entry->address)
1382159047fSniklas signed_value = 0;
1392159047fSniklas
1402159047fSniklas signed_value += sym_value + reloc_entry->addend;
1412159047fSniklas if ((signed_value & ~0x3ffff) == 0)
1422159047fSniklas { /* Absolute jmp/call */
1432159047fSniklas insn |= (1 << 24); /* Make it absolute */
144c074d1c9Sdrahn /* FIXME: Should we change r_type to R_IABS. */
1452159047fSniklas }
1462159047fSniklas else
1472159047fSniklas {
1482159047fSniklas /* Relative jmp/call, so subtract from the value the
149c074d1c9Sdrahn address of the place we're coming from. */
1502159047fSniklas signed_value -= (reloc_entry->address
1512159047fSniklas + input_section->output_section->vma
1522159047fSniklas + input_section->output_offset);
1532159047fSniklas if (signed_value > 0x1ffff || signed_value < -0x20000)
154c074d1c9Sdrahn return bfd_reloc_overflow;
1552159047fSniklas }
1562159047fSniklas signed_value >>= 2;
1572159047fSniklas insn = INSERT_HWORD (insn, signed_value);
158c074d1c9Sdrahn bfd_put_32 (abfd, (bfd_vma) insn ,hit_data);
1592159047fSniklas break;
1602159047fSniklas case R_ILOHALF:
1612159047fSniklas insn = bfd_get_32 (abfd, hit_data);
1622159047fSniklas unsigned_value = EXTRACT_HWORD(insn);
1632159047fSniklas unsigned_value += sym_value + reloc_entry->addend;
1642159047fSniklas insn = INSERT_HWORD(insn, unsigned_value);
165c074d1c9Sdrahn bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
1662159047fSniklas break;
1672159047fSniklas case R_IHIHALF:
1682159047fSniklas insn = bfd_get_32 (abfd, hit_data);
1692159047fSniklas /* consth, part 1
170c074d1c9Sdrahn Just get the symbol value that is referenced. */
171c074d1c9Sdrahn part1_consth_active = TRUE;
1722159047fSniklas part1_consth_value = sym_value + reloc_entry->addend;
173c074d1c9Sdrahn /* Don't modify insn until R_IHCONST. */
1742159047fSniklas break;
1752159047fSniklas case R_IHCONST:
1762159047fSniklas insn = bfd_get_32 (abfd, hit_data);
1772159047fSniklas /* consth, part 2
178c074d1c9Sdrahn Now relocate the reference. */
179c074d1c9Sdrahn if (! part1_consth_active)
180b55d4692Sfgsch {
181b305b0f1Sespie *error_message = (char *) _("Missing IHIHALF");
182c074d1c9Sdrahn return bfd_reloc_dangerous;
1832159047fSniklas }
1842159047fSniklas /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */
1852159047fSniklas unsigned_value = 0; /*EXTRACT_HWORD(insn) << 16;*/
1862159047fSniklas unsigned_value += reloc_entry->addend; /* r_symndx */
1872159047fSniklas unsigned_value += part1_consth_value;
1882159047fSniklas unsigned_value = unsigned_value >> 16;
1892159047fSniklas insn = INSERT_HWORD(insn, unsigned_value);
190c074d1c9Sdrahn part1_consth_active = FALSE;
191c074d1c9Sdrahn bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
1922159047fSniklas break;
1932159047fSniklas case R_BYTE:
1942159047fSniklas insn = bfd_get_8 (abfd, hit_data);
1952159047fSniklas unsigned_value = insn + sym_value + reloc_entry->addend;
1962159047fSniklas if (unsigned_value & 0xffffff00)
197c074d1c9Sdrahn return bfd_reloc_overflow;
1982159047fSniklas bfd_put_8 (abfd, unsigned_value, hit_data);
1992159047fSniklas break;
2002159047fSniklas case R_HWORD:
2012159047fSniklas insn = bfd_get_16 (abfd, hit_data);
2022159047fSniklas unsigned_value = insn + sym_value + reloc_entry->addend;
2032159047fSniklas if (unsigned_value & 0xffff0000)
204c074d1c9Sdrahn return bfd_reloc_overflow;
205c074d1c9Sdrahn bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
2062159047fSniklas break;
2072159047fSniklas case R_WORD:
2082159047fSniklas insn = bfd_get_32 (abfd, hit_data);
2092159047fSniklas insn += sym_value + reloc_entry->addend;
210c074d1c9Sdrahn bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
2112159047fSniklas break;
2122159047fSniklas default:
213b305b0f1Sespie *error_message = _("Unrecognized reloc");
214c074d1c9Sdrahn return bfd_reloc_dangerous;
2152159047fSniklas }
2162159047fSniklas
2172159047fSniklas return(bfd_reloc_ok);
2182159047fSniklas }
2192159047fSniklas
220c074d1c9Sdrahn /*FIXME: I'm not real sure about this table. */
2212159047fSniklas static reloc_howto_type howto_table[] =
2222159047fSniklas {
223c074d1c9Sdrahn {R_ABS, 0, 3, 32, FALSE, 0, complain_overflow_bitfield,a29k_reloc,"ABS", TRUE, 0xffffffff,0xffffffff, FALSE},
224b305b0f1Sespie EMPTY_HOWTO (1),
225b305b0f1Sespie EMPTY_HOWTO (2),
226b305b0f1Sespie EMPTY_HOWTO (3),
227b305b0f1Sespie EMPTY_HOWTO (4),
228b305b0f1Sespie EMPTY_HOWTO (5),
229b305b0f1Sespie EMPTY_HOWTO (6),
230b305b0f1Sespie EMPTY_HOWTO (7),
231b305b0f1Sespie EMPTY_HOWTO (8),
232b305b0f1Sespie EMPTY_HOWTO (9),
233b305b0f1Sespie EMPTY_HOWTO (10),
234b305b0f1Sespie EMPTY_HOWTO (11),
235b305b0f1Sespie EMPTY_HOWTO (12),
236b305b0f1Sespie EMPTY_HOWTO (13),
237b305b0f1Sespie EMPTY_HOWTO (14),
238b305b0f1Sespie EMPTY_HOWTO (15),
239b305b0f1Sespie EMPTY_HOWTO (16),
240b305b0f1Sespie EMPTY_HOWTO (17),
241b305b0f1Sespie EMPTY_HOWTO (18),
242b305b0f1Sespie EMPTY_HOWTO (19),
243b305b0f1Sespie EMPTY_HOWTO (20),
244b305b0f1Sespie EMPTY_HOWTO (21),
245b305b0f1Sespie EMPTY_HOWTO (22),
246b305b0f1Sespie EMPTY_HOWTO (23),
247c074d1c9Sdrahn {R_IREL, 0, 3, 32, TRUE, 0, complain_overflow_signed,a29k_reloc,"IREL", TRUE, 0xffffffff,0xffffffff, FALSE},
248c074d1c9Sdrahn {R_IABS, 0, 3, 32, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"IABS", TRUE, 0xffffffff,0xffffffff, FALSE},
249c074d1c9Sdrahn {R_ILOHALF, 0, 3, 16, TRUE, 0, complain_overflow_signed, a29k_reloc,"ILOHALF", TRUE, 0x0000ffff,0x0000ffff, FALSE},
250c074d1c9Sdrahn {R_IHIHALF, 0, 3, 16, TRUE, 16, complain_overflow_signed, a29k_reloc,"IHIHALF", TRUE, 0xffff0000,0xffff0000, FALSE},
251c074d1c9Sdrahn {R_IHCONST, 0, 3, 16, TRUE, 0, complain_overflow_signed, a29k_reloc,"IHCONST", TRUE, 0xffff0000,0xffff0000, FALSE},
252c074d1c9Sdrahn {R_BYTE, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"BYTE", TRUE, 0x000000ff,0x000000ff, FALSE},
253c074d1c9Sdrahn {R_HWORD, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"HWORD", TRUE, 0x0000ffff,0x0000ffff, FALSE},
254c074d1c9Sdrahn {R_WORD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"WORD", TRUE, 0xffffffff,0xffffffff, FALSE},
2552159047fSniklas };
2562159047fSniklas
2572159047fSniklas #define BADMAG(x) A29KBADMAG(x)
2582159047fSniklas
2592159047fSniklas #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
2602159047fSniklas reloc_processing(relent, reloc, symbols, abfd, section)
2612159047fSniklas
2622159047fSniklas static void
reloc_processing(relent,reloc,symbols,abfd,section)2632159047fSniklas reloc_processing (relent,reloc, symbols, abfd, section)
2642159047fSniklas arelent *relent;
2652159047fSniklas struct internal_reloc *reloc;
2662159047fSniklas asymbol **symbols;
2672159047fSniklas bfd *abfd;
2682159047fSniklas asection *section;
2692159047fSniklas {
2702159047fSniklas static bfd_vma ihihalf_vaddr = (bfd_vma) -1;
2712159047fSniklas
2722159047fSniklas relent->address = reloc->r_vaddr;
2732159047fSniklas relent->howto = howto_table + reloc->r_type;
2742159047fSniklas if (reloc->r_type == R_IHCONST)
2752159047fSniklas {
2762159047fSniklas /* The address of an R_IHCONST should always be the address of
2772159047fSniklas the immediately preceding R_IHIHALF. relocs generated by gas
2782159047fSniklas are correct, but relocs generated by High C are different (I
2792159047fSniklas can't figure out what the address means for High C). We can
2802159047fSniklas handle both gas and High C by ignoring the address here, and
2812159047fSniklas simply reusing the address saved for R_IHIHALF. */
2822159047fSniklas if (ihihalf_vaddr == (bfd_vma) -1)
2832159047fSniklas abort ();
2842159047fSniklas relent->address = ihihalf_vaddr;
2852159047fSniklas ihihalf_vaddr = (bfd_vma) -1;
2862159047fSniklas relent->addend = reloc->r_symndx;
2872159047fSniklas relent->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
2882159047fSniklas }
2892159047fSniklas else
2902159047fSniklas {
2912159047fSniklas asymbol *ptr;
292c074d1c9Sdrahn
2932159047fSniklas relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
2942159047fSniklas
2952159047fSniklas ptr = *(relent->sym_ptr_ptr);
2962159047fSniklas
2972159047fSniklas if (ptr
2982159047fSniklas && bfd_asymbol_bfd(ptr) == abfd
2992159047fSniklas && ((ptr->flags & BSF_OLD_COMMON) == 0))
3002159047fSniklas relent->addend = 0;
3012159047fSniklas else
3022159047fSniklas relent->addend = 0;
303c074d1c9Sdrahn
3042159047fSniklas relent->address-= section->vma;
3052159047fSniklas if (reloc->r_type == R_IHIHALF)
3062159047fSniklas ihihalf_vaddr = relent->address;
3072159047fSniklas else if (ihihalf_vaddr != (bfd_vma) -1)
3082159047fSniklas abort ();
3092159047fSniklas }
3102159047fSniklas }
3112159047fSniklas
3122159047fSniklas /* The reloc processing routine for the optimized COFF linker. */
3132159047fSniklas
314c074d1c9Sdrahn static bfd_boolean
coff_a29k_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,syms,sections)3152159047fSniklas coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
3162159047fSniklas contents, relocs, syms, sections)
317b305b0f1Sespie bfd *output_bfd ATTRIBUTE_UNUSED;
3182159047fSniklas struct bfd_link_info *info;
3192159047fSniklas bfd *input_bfd;
3202159047fSniklas asection *input_section;
3212159047fSniklas bfd_byte *contents;
3222159047fSniklas struct internal_reloc *relocs;
3232159047fSniklas struct internal_syment *syms;
3242159047fSniklas asection **sections;
3252159047fSniklas {
3262159047fSniklas struct internal_reloc *rel;
3272159047fSniklas struct internal_reloc *relend;
328c074d1c9Sdrahn bfd_boolean hihalf;
3292159047fSniklas bfd_vma hihalf_val;
3302159047fSniklas
331*007c2a45Smiod /* If we are performing a relocatable link, we don't need to do a
3322159047fSniklas thing. The caller will take care of adjusting the reloc
3332159047fSniklas addresses and symbol indices. */
334*007c2a45Smiod if (info->relocatable)
335c074d1c9Sdrahn return TRUE;
3362159047fSniklas
337c074d1c9Sdrahn hihalf = FALSE;
3382159047fSniklas hihalf_val = 0;
3392159047fSniklas
3402159047fSniklas rel = relocs;
3412159047fSniklas relend = rel + input_section->reloc_count;
3422159047fSniklas for (; rel < relend; rel++)
3432159047fSniklas {
3442159047fSniklas long symndx;
3452159047fSniklas bfd_byte *loc;
3462159047fSniklas struct coff_link_hash_entry *h;
3472159047fSniklas struct internal_syment *sym;
3482159047fSniklas asection *sec;
3492159047fSniklas bfd_vma val;
350c074d1c9Sdrahn bfd_boolean overflow;
3512159047fSniklas unsigned long insn;
3522159047fSniklas long signed_value;
3532159047fSniklas unsigned long unsigned_value;
3542159047fSniklas bfd_reloc_status_type rstat;
3552159047fSniklas
3562159047fSniklas symndx = rel->r_symndx;
3572159047fSniklas loc = contents + rel->r_vaddr - input_section->vma;
3582159047fSniklas
359b305b0f1Sespie if (symndx == -1 || rel->r_type == R_IHCONST)
3602159047fSniklas h = NULL;
3612159047fSniklas else
3622159047fSniklas h = obj_coff_sym_hashes (input_bfd)[symndx];
3632159047fSniklas
3642159047fSniklas sym = NULL;
3652159047fSniklas sec = NULL;
3662159047fSniklas val = 0;
3672159047fSniklas
3682159047fSniklas /* An R_IHCONST reloc does not have a symbol. Instead, the
3692159047fSniklas symbol index is an addend. R_IHCONST is always used in
3702159047fSniklas conjunction with R_IHHALF. */
3712159047fSniklas if (rel->r_type != R_IHCONST)
3722159047fSniklas {
3732159047fSniklas if (h == NULL)
3742159047fSniklas {
3752159047fSniklas if (symndx == -1)
3762159047fSniklas sec = bfd_abs_section_ptr;
3772159047fSniklas else
3782159047fSniklas {
3792159047fSniklas sym = syms + symndx;
3802159047fSniklas sec = sections[symndx];
3812159047fSniklas val = (sec->output_section->vma
3822159047fSniklas + sec->output_offset
3832159047fSniklas + sym->n_value
3842159047fSniklas - sec->vma);
3852159047fSniklas }
3862159047fSniklas }
3872159047fSniklas else
3882159047fSniklas {
3892159047fSniklas if ( h->root.type == bfd_link_hash_defined
3902159047fSniklas || h->root.type == bfd_link_hash_defweak)
3912159047fSniklas {
3922159047fSniklas sec = h->root.u.def.section;
3932159047fSniklas val = (h->root.u.def.value
3942159047fSniklas + sec->output_section->vma
3952159047fSniklas + sec->output_offset);
3962159047fSniklas }
3972159047fSniklas else
3982159047fSniklas {
3992159047fSniklas if (! ((*info->callbacks->undefined_symbol)
4002159047fSniklas (info, h->root.root.string, input_bfd, input_section,
401c074d1c9Sdrahn rel->r_vaddr - input_section->vma, TRUE)))
402c074d1c9Sdrahn return FALSE;
4032159047fSniklas }
4042159047fSniklas }
4052159047fSniklas
4062159047fSniklas if (hihalf)
4072159047fSniklas {
4082159047fSniklas if (! ((*info->callbacks->reloc_dangerous)
409b305b0f1Sespie (info, _("missing IHCONST reloc"), input_bfd,
4102159047fSniklas input_section, rel->r_vaddr - input_section->vma)))
411c074d1c9Sdrahn return FALSE;
412c074d1c9Sdrahn hihalf = FALSE;
4132159047fSniklas }
4142159047fSniklas }
4152159047fSniklas
416c074d1c9Sdrahn overflow = FALSE;
4172159047fSniklas
4182159047fSniklas switch (rel->r_type)
4192159047fSniklas {
4202159047fSniklas default:
4212159047fSniklas bfd_set_error (bfd_error_bad_value);
422c074d1c9Sdrahn return FALSE;
4232159047fSniklas
4242159047fSniklas case R_IREL:
4252159047fSniklas insn = bfd_get_32 (input_bfd, loc);
4262159047fSniklas
4272159047fSniklas /* Extract the addend. */
4282159047fSniklas signed_value = EXTRACT_HWORD (insn);
4292159047fSniklas signed_value = SIGN_EXTEND_HWORD (signed_value);
4302159047fSniklas signed_value <<= 2;
4312159047fSniklas
4322159047fSniklas /* Unfortunately, there are two different versions of COFF
4332159047fSniklas a29k. In the original AMD version, the value stored in
4342159047fSniklas the field for the R_IREL reloc is a simple addend. In
4352159047fSniklas the GNU version, the value is the negative of the address
4362159047fSniklas of the reloc within section. We try to cope here by
4372159047fSniklas assuming the AMD version, unless the addend is exactly
4382159047fSniklas the negative of the address; in the latter case we assume
4392159047fSniklas the GNU version. This means that something like
4402159047fSniklas .text
4412159047fSniklas nop
4422159047fSniklas jmp i-4
4432159047fSniklas will fail, because the addend of -4 will happen to equal
4442159047fSniklas the negative of the address within the section. The
4452159047fSniklas compiler will never generate code like this.
4462159047fSniklas
4472159047fSniklas At some point in the future we may want to take out this
4482159047fSniklas check. */
4492159047fSniklas
4502159047fSniklas if (signed_value == - (long) (rel->r_vaddr - input_section->vma))
4512159047fSniklas signed_value = 0;
4522159047fSniklas
4532159047fSniklas /* Determine the destination of the jump. */
4542159047fSniklas signed_value += val;
4552159047fSniklas
4562159047fSniklas if ((signed_value & ~0x3ffff) == 0)
4572159047fSniklas {
4582159047fSniklas /* We can use an absolute jump. */
4592159047fSniklas insn |= (1 << 24);
4602159047fSniklas }
4612159047fSniklas else
4622159047fSniklas {
4632159047fSniklas /* Make the destination PC relative. */
4642159047fSniklas signed_value -= (input_section->output_section->vma
4652159047fSniklas + input_section->output_offset
4662159047fSniklas + (rel->r_vaddr - input_section->vma));
4672159047fSniklas if (signed_value > 0x1ffff || signed_value < - 0x20000)
4682159047fSniklas {
469c074d1c9Sdrahn overflow = TRUE;
4702159047fSniklas signed_value = 0;
4712159047fSniklas }
4722159047fSniklas }
4732159047fSniklas
4742159047fSniklas /* Put the adjusted value back into the instruction. */
4752159047fSniklas signed_value >>= 2;
4762159047fSniklas insn = INSERT_HWORD (insn, signed_value);
4772159047fSniklas
4782159047fSniklas bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
4792159047fSniklas break;
4802159047fSniklas
4812159047fSniklas case R_ILOHALF:
4822159047fSniklas insn = bfd_get_32 (input_bfd, loc);
4832159047fSniklas unsigned_value = EXTRACT_HWORD (insn);
4842159047fSniklas unsigned_value += val;
4852159047fSniklas insn = INSERT_HWORD (insn, unsigned_value);
486c074d1c9Sdrahn bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
4872159047fSniklas break;
4882159047fSniklas
4892159047fSniklas case R_IHIHALF:
4902159047fSniklas /* Save the value for the R_IHCONST reloc. */
491c074d1c9Sdrahn hihalf = TRUE;
4922159047fSniklas hihalf_val = val;
4932159047fSniklas break;
4942159047fSniklas
4952159047fSniklas case R_IHCONST:
4962159047fSniklas if (! hihalf)
4972159047fSniklas {
4982159047fSniklas if (! ((*info->callbacks->reloc_dangerous)
499b305b0f1Sespie (info, _("missing IHIHALF reloc"), input_bfd,
5002159047fSniklas input_section, rel->r_vaddr - input_section->vma)))
501c074d1c9Sdrahn return FALSE;
5022159047fSniklas hihalf_val = 0;
5032159047fSniklas }
5042159047fSniklas
5052159047fSniklas insn = bfd_get_32 (input_bfd, loc);
5062159047fSniklas unsigned_value = rel->r_symndx + hihalf_val;
5072159047fSniklas unsigned_value >>= 16;
5082159047fSniklas insn = INSERT_HWORD (insn, unsigned_value);
5092159047fSniklas bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
5102159047fSniklas
511c074d1c9Sdrahn hihalf = FALSE;
5122159047fSniklas
5132159047fSniklas break;
5142159047fSniklas
5152159047fSniklas case R_BYTE:
5162159047fSniklas case R_HWORD:
5172159047fSniklas case R_WORD:
5182159047fSniklas rstat = _bfd_relocate_contents (howto_table + rel->r_type,
5192159047fSniklas input_bfd, val, loc);
5202159047fSniklas if (rstat == bfd_reloc_overflow)
521c074d1c9Sdrahn overflow = TRUE;
5222159047fSniklas else if (rstat != bfd_reloc_ok)
5232159047fSniklas abort ();
5242159047fSniklas break;
5252159047fSniklas }
5262159047fSniklas
5272159047fSniklas if (overflow)
5282159047fSniklas {
5292159047fSniklas const char *name;
5302159047fSniklas char buf[SYMNMLEN + 1];
5312159047fSniklas
5322159047fSniklas if (symndx == -1)
5332159047fSniklas name = "*ABS*";
5342159047fSniklas else if (h != NULL)
5352159047fSniklas name = h->root.root.string;
5362159047fSniklas else if (sym == NULL)
5372159047fSniklas name = "*unknown*";
5382159047fSniklas else if (sym->_n._n_n._n_zeroes == 0
5392159047fSniklas && sym->_n._n_n._n_offset != 0)
5402159047fSniklas name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
5412159047fSniklas else
5422159047fSniklas {
5432159047fSniklas strncpy (buf, sym->_n._n_name, SYMNMLEN);
5442159047fSniklas buf[SYMNMLEN] = '\0';
5452159047fSniklas name = buf;
5462159047fSniklas }
5472159047fSniklas
5482159047fSniklas if (! ((*info->callbacks->reloc_overflow)
5492159047fSniklas (info, name, howto_table[rel->r_type].name, (bfd_vma) 0,
5502159047fSniklas input_bfd, input_section,
5512159047fSniklas rel->r_vaddr - input_section->vma)))
552c074d1c9Sdrahn return FALSE;
5532159047fSniklas }
5542159047fSniklas }
5552159047fSniklas
556c074d1c9Sdrahn return TRUE;
5572159047fSniklas }
5582159047fSniklas
5592159047fSniklas #define coff_relocate_section coff_a29k_relocate_section
5602159047fSniklas
5612159047fSniklas /* We don't want to change the symndx of a R_IHCONST reloc, since it
5622159047fSniklas is actually an addend, not a symbol index at all. */
5632159047fSniklas
564c074d1c9Sdrahn static bfd_boolean
coff_a29k_adjust_symndx(obfd,info,ibfd,sec,irel,adjustedp)5652159047fSniklas coff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
566b305b0f1Sespie bfd *obfd ATTRIBUTE_UNUSED;
567b305b0f1Sespie struct bfd_link_info *info ATTRIBUTE_UNUSED;
568b305b0f1Sespie bfd *ibfd ATTRIBUTE_UNUSED;
569b305b0f1Sespie asection *sec ATTRIBUTE_UNUSED;
5702159047fSniklas struct internal_reloc *irel;
571c074d1c9Sdrahn bfd_boolean *adjustedp;
5722159047fSniklas {
5732159047fSniklas if (irel->r_type == R_IHCONST)
574c074d1c9Sdrahn *adjustedp = TRUE;
5752159047fSniklas else
576c074d1c9Sdrahn *adjustedp = FALSE;
577c074d1c9Sdrahn return TRUE;
5782159047fSniklas }
5792159047fSniklas
5802159047fSniklas #define coff_adjust_symndx coff_a29k_adjust_symndx
5812159047fSniklas
5822159047fSniklas #include "coffcode.h"
5832159047fSniklas
584*007c2a45Smiod CREATE_BIG_COFF_TARGET_VEC (a29kcoff_big_vec, "coff-a29k-big", 0, SEC_READONLY, '_', NULL, COFF_SWAP_TABLE)
585