| /* BFD back-end for Intel 960 COFF files. | 
 |    Copyright (C) 1990-2016 Free Software Foundation, Inc. | 
 |    Written by Cygnus Support. | 
 |  | 
 |    This file is part of BFD, the Binary File Descriptor library. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program; if not, write to the Free Software | 
 |    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | 
 |    MA 02110-1301, USA.  */ | 
 |  | 
 | #define I960 1 | 
 | #define BADMAG(x) I960BADMAG(x) | 
 |  | 
 | #include "sysdep.h" | 
 | #include "bfd.h" | 
 | #include "libbfd.h" | 
 | #include "coff/i960.h" | 
 | #include "coff/internal.h" | 
 |  | 
 | #ifndef bfd_pe_print_pdata | 
 | #define bfd_pe_print_pdata	NULL | 
 | #endif | 
 |  | 
 | #include "libcoff.h"		/* To allow easier abstraction-breaking.  */ | 
 |  | 
 |  | 
 | #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) | 
 | #define COFF_ALIGN_IN_SECTION_HEADER 1 | 
 |  | 
 | #define GET_SCNHDR_ALIGN H_GET_32 | 
 | #define PUT_SCNHDR_ALIGN H_PUT_32 | 
 |  | 
 | /* The i960 does not support an MMU, so COFF_PAGE_SIZE can be | 
 |    arbitrarily small.  */ | 
 | #define COFF_PAGE_SIZE 1 | 
 |  | 
 | #define COFF_LONG_FILENAMES | 
 |  | 
 | /* This set of local label names is taken from gas.  */ | 
 |  | 
 | static bfd_boolean | 
 | coff_i960_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) | 
 | { | 
 |   return (name[0] == 'L' | 
 | 	  || (name[0] == '.' | 
 | 	      && (name[1] == 'C' | 
 | 		  || name[1] == 'I' | 
 | 		  || name[1] == '.'))); | 
 | } | 
 |  | 
 | /* This is just like the usual CALC_ADDEND, but it includes the | 
 |    section VMA for PC relative relocs.  */ | 
 | #ifndef CALC_ADDEND | 
 | #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)		\ | 
 |   {								\ | 
 |     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;	\ | 
 |     if (ptr && bfd_asymbol_bfd (ptr) != abfd)			\ | 
 |       coffsym = (obj_symbols (abfd)				\ | 
 | 		 + (cache_ptr->sym_ptr_ptr - symbols));		\ | 
 |     else if (ptr)						\ | 
 |       coffsym = coff_symbol_from (ptr);				\ | 
 |     if (coffsym != (coff_symbol_type *) NULL			\ | 
 | 	&& coffsym->native->u.syment.n_scnum == 0)		\ | 
 |       cache_ptr->addend = 0;					\ | 
 |     else if (ptr && bfd_asymbol_bfd (ptr) == abfd		\ | 
 | 	     && ptr->section != (asection *) NULL)		\ | 
 |       cache_ptr->addend = - (ptr->section->vma + ptr->value);	\ | 
 |     else							\ | 
 |       cache_ptr->addend = 0;					\ | 
 |     if (ptr && (reloc.r_type == 25 || reloc.r_type == 27))	\ | 
 |       cache_ptr->addend += asect->vma;				\ | 
 |   } | 
 | #endif | 
 |  | 
 | #define CALLS	 0x66003800	/* Template for 'calls' instruction	*/ | 
 | #define BAL	 0x0b000000	/* Template for 'bal' instruction	*/ | 
 | #define BAL_MASK 0x00ffffff | 
 |  | 
 | static bfd_reloc_status_type | 
 | optcall_callback (bfd *abfd, | 
 | 		  arelent *reloc_entry, | 
 | 		  asymbol *symbol_in, | 
 | 		  void * data, | 
 | 		  asection *input_section, | 
 | 		  bfd *ignore_bfd ATTRIBUTE_UNUSED, | 
 | 		  char **error_message) | 
 | { | 
 |   /* This item has already been relocated correctly, but we may be | 
 |    * able to patch in yet better code - done by digging out the | 
 |    * correct info on this symbol */ | 
 |   bfd_reloc_status_type result; | 
 |   coff_symbol_type *cs = coffsymbol(symbol_in); | 
 |  | 
 |   /* Don't do anything with symbols which aren't tied up yet, | 
 |      except move the reloc.  */ | 
 |   if (bfd_is_und_section (cs->symbol.section)) { | 
 |     reloc_entry->address += input_section->output_offset; | 
 |     return bfd_reloc_ok; | 
 |   } | 
 |  | 
 |   /* So the target symbol has to be of coff type, and the symbol | 
 |      has to have the correct native information within it */ | 
 |   if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour) | 
 |       || (cs->native == (combined_entry_type *)NULL)) | 
 |     { | 
 |       /* This is interesting, consider the case where we're outputting coff | 
 | 	 from a mix n match input, linking from coff to a symbol defined in a | 
 | 	 bout file will cause this match to be true. Should I complain?  This | 
 | 	 will only work if the bout symbol is non leaf.  */ | 
 |       *error_message = | 
 | 	(char *) _("uncertain calling convention for non-COFF symbol"); | 
 |       result = bfd_reloc_dangerous; | 
 |     } | 
 |   else | 
 |     { | 
 |     switch (cs->native->u.syment.n_sclass) | 
 |       { | 
 |       case C_LEAFSTAT: | 
 |       case C_LEAFEXT: | 
 |   	/* This is a call to a leaf procedure, replace instruction with a bal | 
 | 	   to the correct location.  */ | 
 | 	{ | 
 | 	  union internal_auxent *aux = &((cs->native+2)->u.auxent); | 
 | 	  int word = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address); | 
 | 	  int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value); | 
 | 	  BFD_ASSERT(cs->native->u.syment.n_numaux==2); | 
 |  | 
 | 	  /* We replace the original call instruction with a bal to | 
 | 	     the bal entry point - the offset of which is described in | 
 | 	     the 2nd auxent of the original symbol. We keep the native | 
 | 	     sym and auxents untouched, so the delta between the two | 
 | 	     is the offset of the bal entry point.  */ | 
 | 	  word = ((word +  olf)  & BAL_MASK) | BAL; | 
 |   	  bfd_put_32 (abfd, (bfd_vma) word, | 
 | 		      (bfd_byte *) data + reloc_entry->address); | 
 |   	} | 
 | 	result = bfd_reloc_ok; | 
 | 	break; | 
 |       case C_SCALL: | 
 | 	/* This is a call to a system call, replace with a calls to # */ | 
 | 	BFD_ASSERT(0); | 
 | 	result = bfd_reloc_ok; | 
 | 	break; | 
 |       default: | 
 | 	result = bfd_reloc_ok; | 
 | 	break; | 
 |       } | 
 |   } | 
 |   return result; | 
 | } | 
 |  | 
 | /* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not | 
 |    appear to correctly handle a reloc against a symbol defined in the | 
 |    same object file.  It appears to simply discard such relocs, rather | 
 |    than adding their values into the object file.  We handle this here | 
 |    by converting all relocs against defined symbols into relocs | 
 |    against the section symbol, when generating a relocatable output | 
 |    file. | 
 |  | 
 |    Note that this function is only called if we are not using the COFF | 
 |    specific backend linker.  It only does something when doing a | 
 |    relocatable link, which will almost certainly fail when not | 
 |    generating COFF i960 output, so this function is actually no longer | 
 |    useful.  It was used before this target was converted to use the | 
 |    COFF specific backend linker.  */ | 
 |  | 
 | static bfd_reloc_status_type | 
 | coff_i960_relocate (bfd *abfd, | 
 | 		    arelent *reloc_entry, | 
 | 		    asymbol *symbol, | 
 | 		    void * data ATTRIBUTE_UNUSED, | 
 | 		    asection *input_section ATTRIBUTE_UNUSED, | 
 | 		    bfd *output_bfd, | 
 | 		    char **error_message ATTRIBUTE_UNUSED) | 
 | { | 
 |   asection *osec; | 
 |  | 
 |   if (output_bfd == NULL) | 
 |     { | 
 |       /* Not generating relocatable output file.  */ | 
 |       return bfd_reloc_continue; | 
 |     } | 
 |  | 
 |   if (bfd_is_und_section (bfd_get_section (symbol))) | 
 |     { | 
 |       /* Symbol is not defined, so no need to worry about it.  */ | 
 |       return bfd_reloc_continue; | 
 |     } | 
 |  | 
 |   if (bfd_is_com_section (bfd_get_section (symbol))) | 
 |     { | 
 |       /* I don't really know what the right action is for a common | 
 |          symbol.  */ | 
 |       return bfd_reloc_continue; | 
 |     } | 
 |  | 
 |   /* Convert the reloc to use the section symbol.  FIXME: This method | 
 |      is ridiculous.  */ | 
 |   osec = bfd_get_section (symbol)->output_section; | 
 |   if (coff_section_data (output_bfd, osec) != NULL | 
 |       && coff_section_data (output_bfd, osec)->tdata != NULL) | 
 |     reloc_entry->sym_ptr_ptr = | 
 |       (asymbol **) coff_section_data (output_bfd, osec)->tdata; | 
 |   else | 
 |     { | 
 |       const char *sec_name; | 
 |       asymbol **syms, **sym_end; | 
 |  | 
 |       sec_name = bfd_get_section_name (output_bfd, osec); | 
 |       syms = bfd_get_outsymbols (output_bfd); | 
 |       sym_end = syms + bfd_get_symcount (output_bfd); | 
 |       for (; syms < sym_end; syms++) | 
 | 	{ | 
 | 	  if (bfd_asymbol_name (*syms) != NULL | 
 | 	      && (*syms)->value == 0 | 
 | 	      && strcmp ((*syms)->section->output_section->name, | 
 | 			 sec_name) == 0) | 
 | 	    break; | 
 | 	} | 
 |  | 
 |       if (syms >= sym_end) | 
 | 	abort (); | 
 |  | 
 |       reloc_entry->sym_ptr_ptr = syms; | 
 |  | 
 |       if (coff_section_data (output_bfd, osec) == NULL) | 
 | 	{ | 
 | 	  bfd_size_type amt = sizeof (struct coff_section_tdata); | 
 | 	  osec->used_by_bfd = bfd_zalloc (abfd, amt); | 
 | 	  if (osec->used_by_bfd == NULL) | 
 | 	    return bfd_reloc_overflow; | 
 | 	} | 
 |       coff_section_data (output_bfd, osec)->tdata = syms; | 
 |     } | 
 |  | 
 |   /* Let bfd_perform_relocation do its thing, which will include | 
 |      stuffing the symbol addend into the object file.  */ | 
 |   return bfd_reloc_continue; | 
 | } | 
 |  | 
 | static reloc_howto_type howto_rellong = | 
 |   HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,FALSE, 0, | 
 | 	 complain_overflow_bitfield, coff_i960_relocate,"rellong", TRUE, | 
 | 	 0xffffffff, 0xffffffff, 0); | 
 | static reloc_howto_type howto_iprmed = | 
 |   HOWTO (R_IPRMED, 0, 2, 24,TRUE,0, complain_overflow_signed, | 
 | 	 coff_i960_relocate, "iprmed ", TRUE, 0x00ffffff, 0x00ffffff, 0); | 
 | static reloc_howto_type howto_optcall = | 
 |   HOWTO (R_OPTCALL, 0,2,24,TRUE,0, complain_overflow_signed, | 
 | 	 optcall_callback, "optcall", TRUE, 0x00ffffff, 0x00ffffff, 0); | 
 |  | 
 | static reloc_howto_type * | 
 | coff_i960_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 			     bfd_reloc_code_real_type code) | 
 | { | 
 |   switch (code) | 
 |     { | 
 |     default: | 
 |       return 0; | 
 |     case BFD_RELOC_I960_CALLJ: | 
 |       return &howto_optcall; | 
 |     case BFD_RELOC_32: | 
 |     case BFD_RELOC_CTOR: | 
 |       return &howto_rellong; | 
 |     case BFD_RELOC_24_PCREL: | 
 |       return &howto_iprmed; | 
 |     } | 
 | } | 
 |  | 
 | static reloc_howto_type * | 
 | coff_i960_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 			     const char *r_name) | 
 | { | 
 |   if (strcasecmp (howto_optcall.name, r_name) == 0) | 
 |     return &howto_optcall; | 
 |   if (strcasecmp (howto_rellong.name, r_name) == 0) | 
 |     return &howto_rellong; | 
 |   if (strcasecmp (howto_iprmed.name, r_name) == 0) | 
 |     return &howto_iprmed; | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* The real code is in coffcode.h */ | 
 |  | 
 | #define RTYPE2HOWTO(cache_ptr, dst) \ | 
 | {							\ | 
 |    reloc_howto_type *howto_ptr;				\ | 
 |    switch ((dst)->r_type) {				\ | 
 |      case 17: howto_ptr = &howto_rellong; break;	\ | 
 |      case 25: howto_ptr = &howto_iprmed; break;		\ | 
 |      case 27: howto_ptr = &howto_optcall; break;	\ | 
 |      default: howto_ptr = 0; break;			\ | 
 |      }							\ | 
 |    (cache_ptr)->howto = howto_ptr;			\ | 
 |  } | 
 |  | 
 | /* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not | 
 |    appear to correctly handle a reloc against a symbol defined in the | 
 |    same object file.  It appears to simply discard such relocs, rather | 
 |    than adding their values into the object file.  We handle this by | 
 |    converting all relocs against global symbols into relocs against | 
 |    internal symbols at the start of the section.  This routine is | 
 |    called at the start of the linking process, and it creates the | 
 |    necessary symbols.  */ | 
 |  | 
 | static bfd_boolean | 
 | coff_i960_start_final_link (bfd *abfd, struct bfd_link_info *info) | 
 | { | 
 |   bfd_size_type symesz = bfd_coff_symesz (abfd); | 
 |   asection *o; | 
 |   bfd_byte *esym; | 
 |  | 
 |   if (! bfd_link_relocatable (info)) | 
 |     return TRUE; | 
 |  | 
 |   esym = (bfd_byte *) bfd_malloc (symesz); | 
 |   if (esym == NULL) | 
 |     return FALSE; | 
 |  | 
 |   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) | 
 |     return FALSE; | 
 |  | 
 |   for (o = abfd->sections; o != NULL; o = o->next) | 
 |     { | 
 |       struct internal_syment isym; | 
 |  | 
 |       strncpy (isym._n._n_name, o->name, SYMNMLEN); | 
 |       isym.n_value = 0; | 
 |       isym.n_scnum = o->target_index; | 
 |       isym.n_type = T_NULL; | 
 |       isym.n_sclass = C_STAT; | 
 |       isym.n_numaux = 0; | 
 |  | 
 |       bfd_coff_swap_sym_out (abfd, &isym, esym); | 
 |  | 
 |       if (bfd_bwrite (esym, symesz, abfd) != symesz) | 
 | 	{ | 
 | 	  free (esym); | 
 | 	  return FALSE; | 
 | 	} | 
 |  | 
 |       obj_raw_syment_count (abfd) += 1; | 
 |     } | 
 |  | 
 |   free (esym); | 
 |  | 
 |   return TRUE; | 
 | } | 
 |  | 
 | /* The reloc processing routine for the optimized COFF linker.  */ | 
 |  | 
 | static bfd_boolean | 
 | coff_i960_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, | 
 | 			    struct bfd_link_info *info, | 
 | 			    bfd *input_bfd, | 
 | 			    asection *input_section, | 
 | 			    bfd_byte *contents, | 
 | 			    struct internal_reloc *relocs, | 
 | 			    struct internal_syment *syms, | 
 | 			    asection **sections) | 
 | { | 
 |   struct internal_reloc *rel; | 
 |   struct internal_reloc *relend; | 
 |  | 
 |   rel = relocs; | 
 |   relend = rel + input_section->reloc_count; | 
 |   for (; rel < relend; rel++) | 
 |     { | 
 |       long symndx; | 
 |       struct coff_link_hash_entry *h; | 
 |       struct internal_syment *sym; | 
 |       bfd_vma addend; | 
 |       bfd_vma val; | 
 |       reloc_howto_type *howto; | 
 |       bfd_reloc_status_type rstat = bfd_reloc_ok; | 
 |       bfd_boolean done; | 
 |  | 
 |       symndx = rel->r_symndx; | 
 |  | 
 |       if (symndx == -1) | 
 | 	{ | 
 | 	  h = NULL; | 
 | 	  sym = NULL; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  h = obj_coff_sym_hashes (input_bfd)[symndx]; | 
 | 	  sym = syms + symndx; | 
 | 	} | 
 |  | 
 |       if (sym != NULL && sym->n_scnum != 0) | 
 | 	addend = - sym->n_value; | 
 |       else | 
 | 	addend = 0; | 
 |  | 
 |       switch (rel->r_type) | 
 | 	{ | 
 | 	case 17: howto = &howto_rellong; break; | 
 | 	case 25: howto = &howto_iprmed; break; | 
 | 	case 27: howto = &howto_optcall; break; | 
 | 	default: | 
 | 	  bfd_set_error (bfd_error_bad_value); | 
 | 	  return FALSE; | 
 | 	} | 
 |  | 
 |       val = 0; | 
 |  | 
 |       if (h == NULL) | 
 | 	{ | 
 | 	  asection *sec; | 
 |  | 
 | 	  if (symndx == -1) | 
 | 	    { | 
 | 	      sec = bfd_abs_section_ptr; | 
 | 	      val = 0; | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      sec = sections[symndx]; | 
 |               val = (sec->output_section->vma | 
 | 		     + sec->output_offset | 
 | 		     + sym->n_value | 
 | 		     - sec->vma); | 
 | 	    } | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  if (h->root.type == bfd_link_hash_defined | 
 | 	      || h->root.type == bfd_link_hash_defweak) | 
 | 	    { | 
 | 	      asection *sec; | 
 |  | 
 | 	      sec = h->root.u.def.section; | 
 | 	      val = (h->root.u.def.value | 
 | 		     + sec->output_section->vma | 
 | 		     + sec->output_offset); | 
 | 	    } | 
 | 	  else if (! bfd_link_relocatable (info)) | 
 | 	    { | 
 | 	      if (! ((*info->callbacks->undefined_symbol) | 
 | 		     (info, h->root.root.string, input_bfd, input_section, | 
 | 		      rel->r_vaddr - input_section->vma, TRUE))) | 
 | 		return FALSE; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       done = FALSE; | 
 |  | 
 |       if (howto->type == R_OPTCALL && ! bfd_link_relocatable (info) && symndx != -1) | 
 | 	{ | 
 | 	  int class_val; | 
 |  | 
 | 	  if (h != NULL) | 
 | 	    class_val = h->symbol_class; | 
 | 	  else | 
 | 	    class_val = sym->n_sclass; | 
 |  | 
 | 	  switch (class_val) | 
 | 	    { | 
 | 	    case C_NULL: | 
 | 	      /* This symbol is apparently not from a COFF input file. | 
 |                  We warn, and then assume that it is not a leaf | 
 |                  function.  */ | 
 | 	      if (! ((*info->callbacks->reloc_dangerous) | 
 | 		     (info, | 
 | 		      _("uncertain calling convention for non-COFF symbol"), | 
 | 		      input_bfd, input_section, | 
 | 		      rel->r_vaddr - input_section->vma))) | 
 | 		return FALSE; | 
 | 	      break; | 
 | 	    case C_LEAFSTAT: | 
 | 	    case C_LEAFEXT: | 
 | 	      /* This is a call to a leaf procedure; use the bal | 
 |                  instruction.  */ | 
 | 	      { | 
 | 		long olf; | 
 | 		unsigned long word; | 
 |  | 
 | 		if (h != NULL) | 
 | 		  { | 
 | 		    BFD_ASSERT (h->numaux == 2); | 
 | 		    olf = h->aux[1].x_bal.x_balntry; | 
 | 		  } | 
 | 		else | 
 | 		  { | 
 | 		    bfd_byte *esyms; | 
 | 		    union internal_auxent aux; | 
 |  | 
 | 		    BFD_ASSERT (sym->n_numaux == 2); | 
 | 		    esyms = (bfd_byte *) obj_coff_external_syms (input_bfd); | 
 | 		    esyms += (symndx + 2) * bfd_coff_symesz (input_bfd); | 
 | 		    bfd_coff_swap_aux_in (input_bfd, esyms, sym->n_type, | 
 | 					  sym->n_sclass, 1, sym->n_numaux, | 
 | 					  &aux); | 
 | 		    olf = aux.x_bal.x_balntry; | 
 | 		  } | 
 |  | 
 | 		word = bfd_get_32 (input_bfd, | 
 | 				   (contents | 
 | 				    + (rel->r_vaddr - input_section->vma))); | 
 | 		word = ((word + olf - val) & BAL_MASK) | BAL; | 
 | 		bfd_put_32 (input_bfd, | 
 | 			    (bfd_vma) word, | 
 | 			    contents + (rel->r_vaddr - input_section->vma)); | 
 | 		done = TRUE; | 
 | 	      } | 
 | 	      break; | 
 | 	    case C_SCALL: | 
 | 	      BFD_ASSERT (0); | 
 | 	      break; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       if (! done) | 
 | 	{ | 
 | 	  if (howto->pc_relative) | 
 | 	    addend += input_section->vma; | 
 | 	  rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, | 
 | 					    contents, | 
 | 					    rel->r_vaddr - input_section->vma, | 
 | 					    val, addend); | 
 | 	} | 
 |  | 
 |       switch (rstat) | 
 | 	{ | 
 | 	default: | 
 | 	  abort (); | 
 | 	case bfd_reloc_ok: | 
 | 	  break; | 
 | 	case bfd_reloc_overflow: | 
 | 	  { | 
 | 	    const char *name; | 
 | 	    char buf[SYMNMLEN + 1]; | 
 |  | 
 | 	    if (symndx == -1) | 
 | 	      name = "*ABS*"; | 
 | 	    else if (h != NULL) | 
 | 	      name = NULL; | 
 | 	    else | 
 | 	      { | 
 | 		name = _bfd_coff_internal_syment_name (input_bfd, sym, buf); | 
 | 		if (name == NULL) | 
 | 		  return FALSE; | 
 | 	      } | 
 |  | 
 | 	    if (! ((*info->callbacks->reloc_overflow) | 
 | 		   (info, (h ? &h->root : NULL), name, howto->name, | 
 | 		    (bfd_vma) 0, input_bfd, input_section, | 
 | 		    rel->r_vaddr - input_section->vma))) | 
 | 	      return FALSE; | 
 | 	  } | 
 | 	} | 
 |     } | 
 |  | 
 |   return TRUE; | 
 | } | 
 |  | 
 | /* Adjust the symbol index of any reloc against a global symbol to | 
 |    instead be a reloc against the internal symbol we created specially | 
 |    for the section.  */ | 
 |  | 
 | static bfd_boolean | 
 | coff_i960_adjust_symndx (bfd *obfd ATTRIBUTE_UNUSED, | 
 | 			 struct bfd_link_info *info ATTRIBUTE_UNUSED, | 
 | 			 bfd *ibfd, | 
 | 			 asection *sec ATTRIBUTE_UNUSED, | 
 | 			 struct internal_reloc *irel, | 
 | 			 bfd_boolean *adjustedp) | 
 | { | 
 |   struct coff_link_hash_entry *h; | 
 |  | 
 |   *adjustedp = FALSE; | 
 |  | 
 |   h = obj_coff_sym_hashes (ibfd)[irel->r_symndx]; | 
 |   if (h == NULL | 
 |       || (h->root.type != bfd_link_hash_defined | 
 | 	  && h->root.type != bfd_link_hash_defweak)) | 
 |     return TRUE; | 
 |  | 
 |   irel->r_symndx = h->root.u.def.section->output_section->target_index - 1; | 
 |   *adjustedp = TRUE; | 
 |  | 
 |   return TRUE; | 
 | } | 
 |  | 
 | #define coff_bfd_is_local_label_name coff_i960_is_local_label_name | 
 |  | 
 | #define coff_start_final_link coff_i960_start_final_link | 
 |  | 
 | #define coff_relocate_section coff_i960_relocate_section | 
 |  | 
 | #define coff_adjust_symndx coff_i960_adjust_symndx | 
 |  | 
 | #define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup | 
 | #define coff_bfd_reloc_name_lookup coff_i960_reloc_name_lookup | 
 |  | 
 | #include "coffcode.h" | 
 |  | 
 | extern const bfd_target icoff_be_vec; | 
 |  | 
 | CREATE_LITTLE_COFF_TARGET_VEC (icoff_le_vec, "coff-Intel-little", 0, 0, '_', & icoff_be_vec, COFF_SWAP_TABLE) | 
 |  | 
 | const bfd_target icoff_be_vec = | 
 | { | 
 |   "coff-Intel-big",		/* name */ | 
 |   bfd_target_coff_flavour, | 
 |   BFD_ENDIAN_LITTLE,		/* data byte order is little */ | 
 |   BFD_ENDIAN_BIG,		/* header byte order is big */ | 
 |  | 
 |   (HAS_RELOC | EXEC_P |		/* object flags */ | 
 |    HAS_LINENO | HAS_DEBUG | | 
 |    HAS_SYMS | HAS_LOCALS | WP_TEXT), | 
 |  | 
 |   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ | 
 |   '_',				/* leading underscore */ | 
 |   '/',				/* ar_pad_char */ | 
 |   15,				/* ar_max_namelen */ | 
 |   0,				/* match priority.  */ | 
 |  | 
 | bfd_getl64, bfd_getl_signed_64, bfd_putl64, | 
 |      bfd_getl32, bfd_getl_signed_32, bfd_putl32, | 
 |      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ | 
 | bfd_getb64, bfd_getb_signed_64, bfd_putb64, | 
 |      bfd_getb32, bfd_getb_signed_32, bfd_putb32, | 
 |      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ | 
 |  | 
 |   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */ | 
 |      bfd_generic_archive_p, _bfd_dummy_target}, | 
 |   {bfd_false, coff_mkobject,	/* bfd_set_format */ | 
 |      _bfd_generic_mkarchive, bfd_false}, | 
 |   {bfd_false, coff_write_object_contents,	/* bfd_write_contents */ | 
 |      _bfd_write_archive_contents, bfd_false}, | 
 |  | 
 |      BFD_JUMP_TABLE_GENERIC (coff), | 
 |      BFD_JUMP_TABLE_COPY (coff), | 
 |      BFD_JUMP_TABLE_CORE (_bfd_nocore), | 
 |      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), | 
 |      BFD_JUMP_TABLE_SYMBOLS (coff), | 
 |      BFD_JUMP_TABLE_RELOCS (coff), | 
 |      BFD_JUMP_TABLE_WRITE (coff), | 
 |      BFD_JUMP_TABLE_LINK (coff), | 
 |      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), | 
 |  | 
 |   & icoff_le_vec, | 
 |  | 
 |   COFF_SWAP_TABLE | 
 | }; |