121288Sdavidn/* BFD back-end for AMD 29000 COFF binaries. 221288Sdavidn Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001, 321288Sdavidn 2002, 2003 421288Sdavidn Free Software Foundation, Inc. 521288Sdavidn Contributed by David Wood at New York University 7/8/91. 621288Sdavidn 721288SdavidnThis file is part of BFD, the Binary File Descriptor library. 821288Sdavidn 921288SdavidnThis program is free software; you can redistribute it and/or modify 1021288Sdavidnit under the terms of the GNU General Public License as published by 1121288Sdavidnthe Free Software Foundation; either version 2 of the License, or 1221288Sdavidn(at your option) any later version. 1321288Sdavidn 1421288SdavidnThis program is distributed in the hope that it will be useful, 1521288Sdavidnbut WITHOUT ANY WARRANTY; without even the implied warranty of 1621288SdavidnMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1721288SdavidnGNU General Public License for more details. 1821288Sdavidn 1921288SdavidnYou should have received a copy of the GNU General Public License 2021288Sdavidnalong with this program; if not, write to the Free Software 2121288SdavidnFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2221288Sdavidn 2321288Sdavidn#define A29K 1 2436607Sjb 2521288Sdavidn#include "bfd.h" 2621288Sdavidn#include "sysdep.h" 2721288Sdavidn#include "libbfd.h" 2821288Sdavidn#include "coff/a29k.h" 2921288Sdavidn#include "coff/internal.h" 3021288Sdavidn#include "libcoff.h" 3121288Sdavidn 3221288Sdavidnstatic long get_symbol_value PARAMS ((asymbol *)); 3322084Sdavidnstatic bfd_reloc_status_type a29k_reloc 3421288Sdavidn PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 3521288Sdavidnstatic bfd_boolean coff_a29k_relocate_section 3621288Sdavidn PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 3721288Sdavidn struct internal_reloc *, struct internal_syment *, asection **)); 3821288Sdavidnstatic bfd_boolean coff_a29k_adjust_symndx 3921288Sdavidn PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, 4021288Sdavidn struct internal_reloc *, bfd_boolean *)); 4136351Sstevestatic void reloc_processing 4221288Sdavidn PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *)); 4321288Sdavidn 4421288Sdavidn#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) 4521288Sdavidn 4621288Sdavidn#define INSERT_HWORD(WORD,HWORD) \ 4721288Sdavidn (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff)) 4821288Sdavidn#define EXTRACT_HWORD(WORD) \ 4925670Sdavidn ((((WORD) & 0x00ff0000) >> 8) | ((WORD) & 0xff)) 5025670Sdavidn#define SIGN_EXTEND_HWORD(HWORD) \ 5125670Sdavidn (((HWORD) ^ 0x8000) - 0x8000) 5221288Sdavidn 5325670Sdavidn/* Provided the symbol, returns the value reffed. */ 5425670Sdavidn 5525670Sdavidnstatic long 5625670Sdavidnget_symbol_value (symbol) 5725670Sdavidn asymbol *symbol; 5825670Sdavidn{ 5925670Sdavidn long relocation = 0; 6025670Sdavidn 6125670Sdavidn if (bfd_is_com_section (symbol->section)) 6225670Sdavidn relocation = 0; 6321288Sdavidn else 6421288Sdavidn relocation = symbol->value + 6521288Sdavidn symbol->section->output_section->vma + 6621288Sdavidn symbol->section->output_offset; 6721288Sdavidn 6821288Sdavidn return relocation; 6925670Sdavidn} 7021288Sdavidn 7125670Sdavidn/* This function is in charge of performing all the 29k relocations. */ 7225670Sdavidn 7321402Sdavidnstatic bfd_reloc_status_type 7425670Sdavidna29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, 7525670Sdavidn error_message) 7621288Sdavidn bfd *abfd; 7725670Sdavidn arelent *reloc_entry; 7825670Sdavidn asymbol *symbol_in; 7925670Sdavidn PTR data; 8025670Sdavidn asection *input_section; 8125670Sdavidn bfd *output_bfd; 8225670Sdavidn char **error_message; 8325670Sdavidn{ 8425670Sdavidn /* The consth relocation comes in two parts, we have to remember 8525670Sdavidn the state between calls, in these variables. */ 8625670Sdavidn static bfd_boolean part1_consth_active = FALSE; 8725670Sdavidn static unsigned long part1_consth_value; 8821288Sdavidn unsigned long insn; 8925670Sdavidn unsigned long sym_value; 9025670Sdavidn unsigned long unsigned_value; 9125670Sdavidn unsigned short r_type; 9225670Sdavidn long signed_value; 9325670Sdavidn unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/ 9425670Sdavidn bfd_byte *hit_data =addr + (bfd_byte *) (data); 9525670Sdavidn 9621288Sdavidn r_type = reloc_entry->howto->type; 9725670Sdavidn 9825670Sdavidn if (output_bfd) 9921288Sdavidn { 10025670Sdavidn /* Partial linking - do nothing. */ 10125670Sdavidn reloc_entry->address += input_section->output_offset; 10225670Sdavidn return bfd_reloc_ok; 10325670Sdavidn } 10421288Sdavidn 10525670Sdavidn if (symbol_in != NULL 10625670Sdavidn && bfd_is_und_section (symbol_in->section)) 10725670Sdavidn { 10825670Sdavidn /* Keep the state machine happy in case we're called again. */ 10921288Sdavidn if (r_type == R_IHIHALF) 11021288Sdavidn { 11125670Sdavidn part1_consth_active = TRUE; 11225670Sdavidn part1_consth_value = 0; 11321288Sdavidn } 11425670Sdavidn return bfd_reloc_undefined; 11525670Sdavidn } 11625670Sdavidn 11721288Sdavidn if ((part1_consth_active) && (r_type != R_IHCONST)) 11825670Sdavidn { 11925670Sdavidn part1_consth_active = FALSE; 12025670Sdavidn *error_message = (char *) _("Missing IHCONST"); 12125670Sdavidn 12221288Sdavidn return bfd_reloc_dangerous; 12325670Sdavidn } 12425670Sdavidn 12525670Sdavidn sym_value = get_symbol_value(symbol_in); 12625670Sdavidn 12725670Sdavidn switch (r_type) 12821288Sdavidn { 12921288Sdavidn case R_IREL: 13021288Sdavidn insn = bfd_get_32 (abfd, hit_data); 13121288Sdavidn /* Take the value in the field and sign extend it. */ 13221288Sdavidn signed_value = EXTRACT_HWORD(insn); 13325670Sdavidn signed_value = SIGN_EXTEND_HWORD(signed_value); 13421288Sdavidn signed_value <<= 2; 13525670Sdavidn 13625670Sdavidn /* See the note on the R_IREL reloc in coff_a29k_relocate_section. */ 13725670Sdavidn if (signed_value == - (long) reloc_entry->address) 13825670Sdavidn signed_value = 0; 13921288Sdavidn 14025670Sdavidn signed_value += sym_value + reloc_entry->addend; 14125670Sdavidn if ((signed_value & ~0x3ffff) == 0) 14225670Sdavidn { /* Absolute jmp/call */ 14325670Sdavidn insn |= (1 << 24); /* Make it absolute */ 14425670Sdavidn /* FIXME: Should we change r_type to R_IABS. */ 14525670Sdavidn } 14625670Sdavidn else 14725670Sdavidn { 14825670Sdavidn /* Relative jmp/call, so subtract from the value the 14925670Sdavidn address of the place we're coming from. */ 15021288Sdavidn signed_value -= (reloc_entry->address 15125670Sdavidn + input_section->output_section->vma 15225670Sdavidn + input_section->output_offset); 15325670Sdavidn if (signed_value > 0x1ffff || signed_value < -0x20000) 15421288Sdavidn return bfd_reloc_overflow; 15525670Sdavidn } 15625670Sdavidn signed_value >>= 2; 15721288Sdavidn insn = INSERT_HWORD (insn, signed_value); 15825670Sdavidn bfd_put_32 (abfd, (bfd_vma) insn ,hit_data); 15925670Sdavidn break; 16025670Sdavidn case R_ILOHALF: 16125670Sdavidn insn = bfd_get_32 (abfd, hit_data); 16225670Sdavidn unsigned_value = EXTRACT_HWORD(insn); 16325670Sdavidn unsigned_value += sym_value + reloc_entry->addend; 16425670Sdavidn insn = INSERT_HWORD(insn, unsigned_value); 16521288Sdavidn bfd_put_32 (abfd, (bfd_vma) insn, hit_data); 16625670Sdavidn break; 16725670Sdavidn case R_IHIHALF: 16825670Sdavidn insn = bfd_get_32 (abfd, hit_data); 16925670Sdavidn /* consth, part 1 17025670Sdavidn Just get the symbol value that is referenced. */ 17125670Sdavidn part1_consth_active = TRUE; 17225670Sdavidn part1_consth_value = sym_value + reloc_entry->addend; 17325670Sdavidn /* Don't modify insn until R_IHCONST. */ 17425670Sdavidn break; 17525670Sdavidn case R_IHCONST: 17625670Sdavidn insn = bfd_get_32 (abfd, hit_data); 17725670Sdavidn /* consth, part 2 17825670Sdavidn Now relocate the reference. */ 17925670Sdavidn if (! part1_consth_active) 18025670Sdavidn { 18125670Sdavidn *error_message = (char *) _("Missing IHIHALF"); 18225670Sdavidn return bfd_reloc_dangerous; 18321288Sdavidn } 18421288Sdavidn /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */ 18525670Sdavidn unsigned_value = 0; /*EXTRACT_HWORD(insn) << 16;*/ 18625670Sdavidn unsigned_value += reloc_entry->addend; /* r_symndx */ 18721288Sdavidn unsigned_value += part1_consth_value; 18821288Sdavidn unsigned_value = unsigned_value >> 16; 18921288Sdavidn insn = INSERT_HWORD(insn, unsigned_value); 19021288Sdavidn part1_consth_active = FALSE; 19121288Sdavidn bfd_put_32 (abfd, (bfd_vma) insn, hit_data); 19221288Sdavidn break; 19325670Sdavidn case R_BYTE: 19425670Sdavidn insn = bfd_get_8 (abfd, hit_data); 19525670Sdavidn unsigned_value = insn + sym_value + reloc_entry->addend; 19625670Sdavidn if (unsigned_value & 0xffffff00) 19721288Sdavidn return bfd_reloc_overflow; 19825670Sdavidn bfd_put_8 (abfd, unsigned_value, hit_data); 19925670Sdavidn break; 20021288Sdavidn case R_HWORD: 20125670Sdavidn insn = bfd_get_16 (abfd, hit_data); 20225670Sdavidn unsigned_value = insn + sym_value + reloc_entry->addend; 20325670Sdavidn if (unsigned_value & 0xffff0000) 20421288Sdavidn return bfd_reloc_overflow; 20525670Sdavidn bfd_put_16 (abfd, (bfd_vma) insn, hit_data); 20621288Sdavidn break; 20725670Sdavidn case R_WORD: 20825670Sdavidn insn = bfd_get_32 (abfd, hit_data); 20925670Sdavidn insn += sym_value + reloc_entry->addend; 21025670Sdavidn bfd_put_32 (abfd, (bfd_vma) insn, hit_data); 21125670Sdavidn break; 21225670Sdavidn default: 21325670Sdavidn *error_message = _("Unrecognized reloc"); 21421288Sdavidn return bfd_reloc_dangerous; 21521288Sdavidn } 21625670Sdavidn 21725670Sdavidn return(bfd_reloc_ok); 21825670Sdavidn} 21925670Sdavidn 22025670Sdavidn/*FIXME: I'm not real sure about this table. */ 22125670Sdavidnstatic reloc_howto_type howto_table[] = 22221402Sdavidn { 22325670Sdavidn {R_ABS, 0, 3, 32, FALSE, 0, complain_overflow_bitfield,a29k_reloc,"ABS", TRUE, 0xffffffff,0xffffffff, FALSE}, 22425670Sdavidn EMPTY_HOWTO (1), 22525670Sdavidn EMPTY_HOWTO (2), 22621402Sdavidn EMPTY_HOWTO (3), 22725670Sdavidn EMPTY_HOWTO (4), 22825670Sdavidn EMPTY_HOWTO (5), 22925670Sdavidn EMPTY_HOWTO (6), 23025670Sdavidn EMPTY_HOWTO (7), 23125670Sdavidn EMPTY_HOWTO (8), 23225670Sdavidn EMPTY_HOWTO (9), 23325670Sdavidn EMPTY_HOWTO (10), 23425670Sdavidn EMPTY_HOWTO (11), 23525670Sdavidn EMPTY_HOWTO (12), 23625670Sdavidn EMPTY_HOWTO (13), 23725670Sdavidn EMPTY_HOWTO (14), 23821288Sdavidn EMPTY_HOWTO (15), 23921288Sdavidn EMPTY_HOWTO (16), 24021288Sdavidn EMPTY_HOWTO (17), 24121288Sdavidn EMPTY_HOWTO (18), 24221288Sdavidn EMPTY_HOWTO (19), 24321288Sdavidn EMPTY_HOWTO (20), 24421288Sdavidn EMPTY_HOWTO (21), 24521288Sdavidn EMPTY_HOWTO (22), 24621288Sdavidn EMPTY_HOWTO (23), 24721288Sdavidn {R_IREL, 0, 3, 32, TRUE, 0, complain_overflow_signed,a29k_reloc,"IREL", TRUE, 0xffffffff,0xffffffff, FALSE}, 24821288Sdavidn {R_IABS, 0, 3, 32, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"IABS", TRUE, 0xffffffff,0xffffffff, FALSE}, 24921288Sdavidn {R_ILOHALF, 0, 3, 16, TRUE, 0, complain_overflow_signed, a29k_reloc,"ILOHALF", TRUE, 0x0000ffff,0x0000ffff, FALSE}, 25021288Sdavidn {R_IHIHALF, 0, 3, 16, TRUE, 16, complain_overflow_signed, a29k_reloc,"IHIHALF", TRUE, 0xffff0000,0xffff0000, FALSE}, 25121288Sdavidn {R_IHCONST, 0, 3, 16, TRUE, 0, complain_overflow_signed, a29k_reloc,"IHCONST", TRUE, 0xffff0000,0xffff0000, FALSE}, 25221288Sdavidn {R_BYTE, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"BYTE", TRUE, 0x000000ff,0x000000ff, FALSE}, 25321288Sdavidn {R_HWORD, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"HWORD", TRUE, 0x0000ffff,0x0000ffff, FALSE}, 25421288Sdavidn {R_WORD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, a29k_reloc,"WORD", TRUE, 0xffffffff,0xffffffff, FALSE}, 25521288Sdavidn }; 25621288Sdavidn 25725670Sdavidn#define BADMAG(x) A29KBADMAG(x) 25825670Sdavidn 25925670Sdavidn#define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \ 26025670Sdavidn reloc_processing(relent, reloc, symbols, abfd, section) 26125670Sdavidn 26225670Sdavidnstatic void 26325670Sdavidnreloc_processing (relent,reloc, symbols, abfd, section) 26425670Sdavidn arelent *relent; 26525670Sdavidn struct internal_reloc *reloc; 26625670Sdavidn asymbol **symbols; 26725670Sdavidn bfd *abfd; 26821288Sdavidn asection *section; 26921288Sdavidn{ 27021288Sdavidn static bfd_vma ihihalf_vaddr = (bfd_vma) -1; 27125670Sdavidn 27221288Sdavidn relent->address = reloc->r_vaddr; 27325670Sdavidn relent->howto = howto_table + reloc->r_type; 27425670Sdavidn if (reloc->r_type == R_IHCONST) 27525670Sdavidn { 27625670Sdavidn /* The address of an R_IHCONST should always be the address of 27725670Sdavidn the immediately preceding R_IHIHALF. relocs generated by gas 27825670Sdavidn are correct, but relocs generated by High C are different (I 27925670Sdavidn can't figure out what the address means for High C). We can 28025670Sdavidn handle both gas and High C by ignoring the address here, and 28125670Sdavidn simply reusing the address saved for R_IHIHALF. */ 28225670Sdavidn if (ihihalf_vaddr == (bfd_vma) -1) 28325670Sdavidn abort (); 28425670Sdavidn relent->address = ihihalf_vaddr; 28525670Sdavidn ihihalf_vaddr = (bfd_vma) -1; 28625670Sdavidn relent->addend = reloc->r_symndx; 28725670Sdavidn relent->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr; 28825670Sdavidn } 28925670Sdavidn else 29025670Sdavidn { 29125670Sdavidn asymbol *ptr; 29225670Sdavidn 29325670Sdavidn relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx]; 29425670Sdavidn 29525670Sdavidn ptr = *(relent->sym_ptr_ptr); 29625670Sdavidn 29725670Sdavidn if (ptr 29825670Sdavidn && bfd_asymbol_bfd(ptr) == abfd 29925670Sdavidn && ((ptr->flags & BSF_OLD_COMMON) == 0)) 30021288Sdavidn relent->addend = 0; 30121288Sdavidn else 30221288Sdavidn relent->addend = 0; 30321288Sdavidn 30421288Sdavidn relent->address-= section->vma; 30521288Sdavidn if (reloc->r_type == R_IHIHALF) 30621288Sdavidn ihihalf_vaddr = relent->address; 30721288Sdavidn else if (ihihalf_vaddr != (bfd_vma) -1) 30821288Sdavidn abort (); 30921288Sdavidn } 31021288Sdavidn} 31121288Sdavidn 31221288Sdavidn/* The reloc processing routine for the optimized COFF linker. */ 31321288Sdavidn 31421288Sdavidnstatic bfd_boolean 31521288Sdavidncoff_a29k_relocate_section (output_bfd, info, input_bfd, input_section, 31625670Sdavidn contents, relocs, syms, sections) 31725670Sdavidn bfd *output_bfd ATTRIBUTE_UNUSED; 31825670Sdavidn struct bfd_link_info *info; 31936607Sjb bfd *input_bfd; 32036351Ssteve asection *input_section; 32136607Sjb bfd_byte *contents; 32221288Sdavidn struct internal_reloc *relocs; 32325670Sdavidn struct internal_syment *syms; 32425670Sdavidn asection **sections; 32525670Sdavidn{ 32625670Sdavidn struct internal_reloc *rel; 32721288Sdavidn struct internal_reloc *relend; 32825670Sdavidn bfd_boolean hihalf; 32925670Sdavidn bfd_vma hihalf_val; 33021288Sdavidn 33125670Sdavidn /* If we are performing a relocatable link, we don't need to do a 33225670Sdavidn thing. The caller will take care of adjusting the reloc 33325670Sdavidn addresses and symbol indices. */ 33421288Sdavidn if (info->relocatable) 33525670Sdavidn return TRUE; 33625670Sdavidn 33725670Sdavidn hihalf = FALSE; 33821288Sdavidn hihalf_val = 0; 33936351Ssteve 34036607Sjb rel = relocs; 34136351Ssteve relend = rel + input_section->reloc_count; 34236351Ssteve for (; rel < relend; rel++) 34336351Ssteve { 34436351Ssteve long symndx; 34536351Ssteve bfd_byte *loc; 34636351Ssteve struct coff_link_hash_entry *h; 34736607Sjb struct internal_syment *sym; 34836351Ssteve asection *sec; 34936607Sjb bfd_vma val; 35036351Ssteve bfd_boolean overflow; 35136351Ssteve unsigned long insn; 35236351Ssteve long signed_value; 35336351Ssteve unsigned long unsigned_value; 35436351Ssteve bfd_reloc_status_type rstat; 35536351Ssteve 35636607Sjb symndx = rel->r_symndx; 35736351Ssteve loc = contents + rel->r_vaddr - input_section->vma; 35836351Ssteve 35936351Ssteve if (symndx == -1 || rel->r_type == R_IHCONST) 36036351Ssteve h = NULL; 36136351Ssteve else 36225670Sdavidn h = obj_coff_sym_hashes (input_bfd)[symndx]; 36321288Sdavidn 36425670Sdavidn sym = NULL; 36525670Sdavidn sec = NULL; 36625670Sdavidn val = 0; 36725670Sdavidn 36825670Sdavidn /* An R_IHCONST reloc does not have a symbol. Instead, the 36925670Sdavidn symbol index is an addend. R_IHCONST is always used in 37025670Sdavidn conjunction with R_IHHALF. */ 37125670Sdavidn if (rel->r_type != R_IHCONST) 37225670Sdavidn { 37325670Sdavidn if (h == NULL) 37425670Sdavidn { 37525670Sdavidn if (symndx == -1) 37625670Sdavidn sec = bfd_abs_section_ptr; 37725670Sdavidn else 37821288Sdavidn { 37925670Sdavidn sym = syms + symndx; 38025670Sdavidn sec = sections[symndx]; 38125670Sdavidn val = (sec->output_section->vma 38225670Sdavidn + sec->output_offset 38325670Sdavidn + sym->n_value 38425670Sdavidn - sec->vma); 38521288Sdavidn } 38625670Sdavidn } 38725670Sdavidn else 38825670Sdavidn { 38921288Sdavidn if ( h->root.type == bfd_link_hash_defined 39025670Sdavidn || h->root.type == bfd_link_hash_defweak) 39125670Sdavidn { 39225670Sdavidn sec = h->root.u.def.section; 39325670Sdavidn val = (h->root.u.def.value 39421288Sdavidn + sec->output_section->vma 39521288Sdavidn + sec->output_offset); 39625670Sdavidn } 39725670Sdavidn else 39825670Sdavidn { 39925670Sdavidn if (! ((*info->callbacks->undefined_symbol) 40025670Sdavidn (info, h->root.root.string, input_bfd, input_section, 40125670Sdavidn rel->r_vaddr - input_section->vma, TRUE))) 40225670Sdavidn return FALSE; 40321288Sdavidn } 40425670Sdavidn } 40525670Sdavidn 40625670Sdavidn if (hihalf) 40721288Sdavidn { 40825670Sdavidn if (! ((*info->callbacks->reloc_dangerous) 40921288Sdavidn (info, _("missing IHCONST reloc"), input_bfd, 41021288Sdavidn input_section, rel->r_vaddr - input_section->vma))) 411 return FALSE; 412 hihalf = FALSE; 413 } 414 } 415 416 overflow = FALSE; 417 418 switch (rel->r_type) 419 { 420 default: 421 bfd_set_error (bfd_error_bad_value); 422 return FALSE; 423 424 case R_IREL: 425 insn = bfd_get_32 (input_bfd, loc); 426 427 /* Extract the addend. */ 428 signed_value = EXTRACT_HWORD (insn); 429 signed_value = SIGN_EXTEND_HWORD (signed_value); 430 signed_value <<= 2; 431 432 /* Unfortunately, there are two different versions of COFF 433 a29k. In the original AMD version, the value stored in 434 the field for the R_IREL reloc is a simple addend. In 435 the GNU version, the value is the negative of the address 436 of the reloc within section. We try to cope here by 437 assuming the AMD version, unless the addend is exactly 438 the negative of the address; in the latter case we assume 439 the GNU version. This means that something like 440 .text 441 nop 442 jmp i-4 443 will fail, because the addend of -4 will happen to equal 444 the negative of the address within the section. The 445 compiler will never generate code like this. 446 447 At some point in the future we may want to take out this 448 check. */ 449 450 if (signed_value == - (long) (rel->r_vaddr - input_section->vma)) 451 signed_value = 0; 452 453 /* Determine the destination of the jump. */ 454 signed_value += val; 455 456 if ((signed_value & ~0x3ffff) == 0) 457 { 458 /* We can use an absolute jump. */ 459 insn |= (1 << 24); 460 } 461 else 462 { 463 /* Make the destination PC relative. */ 464 signed_value -= (input_section->output_section->vma 465 + input_section->output_offset 466 + (rel->r_vaddr - input_section->vma)); 467 if (signed_value > 0x1ffff || signed_value < - 0x20000) 468 { 469 overflow = TRUE; 470 signed_value = 0; 471 } 472 } 473 474 /* Put the adjusted value back into the instruction. */ 475 signed_value >>= 2; 476 insn = INSERT_HWORD (insn, signed_value); 477 478 bfd_put_32 (input_bfd, (bfd_vma) insn, loc); 479 break; 480 481 case R_ILOHALF: 482 insn = bfd_get_32 (input_bfd, loc); 483 unsigned_value = EXTRACT_HWORD (insn); 484 unsigned_value += val; 485 insn = INSERT_HWORD (insn, unsigned_value); 486 bfd_put_32 (input_bfd, (bfd_vma) insn, loc); 487 break; 488 489 case R_IHIHALF: 490 /* Save the value for the R_IHCONST reloc. */ 491 hihalf = TRUE; 492 hihalf_val = val; 493 break; 494 495 case R_IHCONST: 496 if (! hihalf) 497 { 498 if (! ((*info->callbacks->reloc_dangerous) 499 (info, _("missing IHIHALF reloc"), input_bfd, 500 input_section, rel->r_vaddr - input_section->vma))) 501 return FALSE; 502 hihalf_val = 0; 503 } 504 505 insn = bfd_get_32 (input_bfd, loc); 506 unsigned_value = rel->r_symndx + hihalf_val; 507 unsigned_value >>= 16; 508 insn = INSERT_HWORD (insn, unsigned_value); 509 bfd_put_32 (input_bfd, (bfd_vma) insn, loc); 510 511 hihalf = FALSE; 512 513 break; 514 515 case R_BYTE: 516 case R_HWORD: 517 case R_WORD: 518 rstat = _bfd_relocate_contents (howto_table + rel->r_type, 519 input_bfd, val, loc); 520 if (rstat == bfd_reloc_overflow) 521 overflow = TRUE; 522 else if (rstat != bfd_reloc_ok) 523 abort (); 524 break; 525 } 526 527 if (overflow) 528 { 529 const char *name; 530 char buf[SYMNMLEN + 1]; 531 532 if (symndx == -1) 533 name = "*ABS*"; 534 else if (h != NULL) 535 name = h->root.root.string; 536 else if (sym == NULL) 537 name = "*unknown*"; 538 else if (sym->_n._n_n._n_zeroes == 0 539 && sym->_n._n_n._n_offset != 0) 540 name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset; 541 else 542 { 543 strncpy (buf, sym->_n._n_name, SYMNMLEN); 544 buf[SYMNMLEN] = '\0'; 545 name = buf; 546 } 547 548 if (! ((*info->callbacks->reloc_overflow) 549 (info, name, howto_table[rel->r_type].name, (bfd_vma) 0, 550 input_bfd, input_section, 551 rel->r_vaddr - input_section->vma))) 552 return FALSE; 553 } 554 } 555 556 return TRUE; 557} 558 559#define coff_relocate_section coff_a29k_relocate_section 560 561/* 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. */ 563 564static bfd_boolean 565coff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp) 566 bfd *obfd ATTRIBUTE_UNUSED; 567 struct bfd_link_info *info ATTRIBUTE_UNUSED; 568 bfd *ibfd ATTRIBUTE_UNUSED; 569 asection *sec ATTRIBUTE_UNUSED; 570 struct internal_reloc *irel; 571 bfd_boolean *adjustedp; 572{ 573 if (irel->r_type == R_IHCONST) 574 *adjustedp = TRUE; 575 else 576 *adjustedp = FALSE; 577 return TRUE; 578} 579 580#define coff_adjust_symndx coff_a29k_adjust_symndx 581 582#include "coffcode.h" 583 584CREATE_BIG_COFF_TARGET_VEC (a29kcoff_big_vec, "coff-a29k-big", 0, SEC_READONLY, '_', NULL, COFF_SWAP_TABLE) 585