1/* BFD back-end for Intel 960 COFF files.
2   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
3   2002, 2003, 2004 Free Software Foundation, Inc.
4   Written by Cygnus Support.
5
6This file is part of BFD, the Binary File Descriptor library.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21
22#define I960 1
23#define BADMAG(x) I960BADMAG(x)
24
25#include "bfd.h"
26#include "sysdep.h"
27#include "libbfd.h"
28#include "coff/i960.h"
29#include "coff/internal.h"
30#include "libcoff.h"		/* to allow easier abstraction-breaking */
31
32static bfd_boolean coff_i960_is_local_label_name
33  PARAMS ((bfd *, const char *));
34static bfd_reloc_status_type optcall_callback
35  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36static bfd_reloc_status_type coff_i960_relocate
37  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38static reloc_howto_type *coff_i960_reloc_type_lookup
39  PARAMS ((bfd *, bfd_reloc_code_real_type));
40static bfd_boolean coff_i960_start_final_link
41  PARAMS ((bfd *, struct bfd_link_info *));
42static bfd_boolean coff_i960_relocate_section
43  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
44	   struct internal_reloc *, struct internal_syment *, asection **));
45static bfd_boolean coff_i960_adjust_symndx
46  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
47	   struct internal_reloc *, bfd_boolean *));
48
49#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
50#define COFF_ALIGN_IN_SECTION_HEADER 1
51
52#define GET_SCNHDR_ALIGN H_GET_32
53#define PUT_SCNHDR_ALIGN H_PUT_32
54
55/* The i960 does not support an MMU, so COFF_PAGE_SIZE can be
56   arbitrarily small.  */
57#define COFF_PAGE_SIZE 1
58
59#define COFF_LONG_FILENAMES
60
61/* This set of local label names is taken from gas.  */
62
63static bfd_boolean
64coff_i960_is_local_label_name (abfd, name)
65     bfd *abfd ATTRIBUTE_UNUSED;
66     const char *name;
67{
68  return (name[0] == 'L'
69	  || (name[0] == '.'
70	      && (name[1] == 'C'
71		  || name[1] == 'I'
72		  || name[1] == '.')));
73}
74
75/* This is just like the usual CALC_ADDEND, but it includes the
76   section VMA for PC relative relocs.  */
77#ifndef CALC_ADDEND
78#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
79  {                                                             \
80    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
81    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
82      coffsym = (obj_symbols (abfd)                             \
83                 + (cache_ptr->sym_ptr_ptr - symbols));         \
84    else if (ptr)                                               \
85      coffsym = coff_symbol_from (abfd, ptr);                   \
86    if (coffsym != (coff_symbol_type *) NULL                    \
87        && coffsym->native->u.syment.n_scnum == 0)              \
88      cache_ptr->addend = 0;                                    \
89    else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
90             && ptr->section != (asection *) NULL)              \
91      cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
92    else                                                        \
93      cache_ptr->addend = 0;                                    \
94    if (ptr && (reloc.r_type == 25 || reloc.r_type == 27))	\
95      cache_ptr->addend += asect->vma;				\
96  }
97#endif
98
99#define CALLS	 0x66003800	/* Template for 'calls' instruction	*/
100#define BAL	 0x0b000000	/* Template for 'bal' instruction	*/
101#define BAL_MASK 0x00ffffff
102
103static bfd_reloc_status_type
104optcall_callback (abfd, reloc_entry, symbol_in, data,
105		  input_section, ignore_bfd, error_message)
106     bfd *abfd;
107     arelent *reloc_entry;
108     asymbol *symbol_in;
109     PTR data;
110     asection *input_section;
111     bfd *ignore_bfd ATTRIBUTE_UNUSED;
112     char **error_message;
113{
114  /* This item has already been relocated correctly, but we may be
115   * able to patch in yet better code - done by digging out the
116   * correct info on this symbol */
117  bfd_reloc_status_type result;
118  coff_symbol_type *cs = coffsymbol(symbol_in);
119
120  /* Don't do anything with symbols which aren't tied up yet,
121     except move the reloc.  */
122  if (bfd_is_und_section (cs->symbol.section)) {
123    reloc_entry->address += input_section->output_offset;
124    return bfd_reloc_ok;
125  }
126
127  /* So the target symbol has to be of coff type, and the symbol
128     has to have the correct native information within it */
129  if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour)
130      || (cs->native == (combined_entry_type *)NULL))
131    {
132      /* This is interesting, consider the case where we're outputting coff
133	 from a mix n match input, linking from coff to a symbol defined in a
134	 bout file will cause this match to be true. Should I complain?  This
135	 will only work if the bout symbol is non leaf.  */
136      *error_message =
137	(char *) _("uncertain calling convention for non-COFF symbol");
138      result = bfd_reloc_dangerous;
139    }
140  else
141    {
142    switch (cs->native->u.syment.n_sclass)
143      {
144      case C_LEAFSTAT:
145      case C_LEAFEXT:
146  	/* This is a call to a leaf procedure, replace instruction with a bal
147	   to the correct location.  */
148	{
149	  union internal_auxent *aux = &((cs->native+2)->u.auxent);
150	  int word = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
151	  int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
152	  BFD_ASSERT(cs->native->u.syment.n_numaux==2);
153
154	  /* We replace the original call instruction with a bal to
155	     the bal entry point - the offset of which is described in
156	     the 2nd auxent of the original symbol. We keep the native
157	     sym and auxents untouched, so the delta between the two
158	     is the offset of the bal entry point.  */
159	  word = ((word +  olf)  & BAL_MASK) | BAL;
160  	  bfd_put_32 (abfd, (bfd_vma) word,
161		      (bfd_byte *) data + reloc_entry->address);
162  	}
163	result = bfd_reloc_ok;
164	break;
165      case C_SCALL:
166	/* This is a call to a system call, replace with a calls to # */
167	BFD_ASSERT(0);
168	result = bfd_reloc_ok;
169	break;
170      default:
171	result = bfd_reloc_ok;
172	break;
173      }
174  }
175  return result;
176}
177
178/* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not
179   appear to correctly handle a reloc against a symbol defined in the
180   same object file.  It appears to simply discard such relocs, rather
181   than adding their values into the object file.  We handle this here
182   by converting all relocs against defined symbols into relocs
183   against the section symbol, when generating a relocatable output
184   file.
185
186   Note that this function is only called if we are not using the COFF
187   specific backend linker.  It only does something when doing a
188   relocatable link, which will almost certainly fail when not
189   generating COFF i960 output, so this function is actually no longer
190   useful.  It was used before this target was converted to use the
191   COFF specific backend linker.  */
192
193static bfd_reloc_status_type
194coff_i960_relocate (abfd, reloc_entry, symbol, data, input_section,
195		    output_bfd, error_message)
196     bfd *abfd;
197     arelent *reloc_entry;
198     asymbol *symbol;
199     PTR data ATTRIBUTE_UNUSED;
200     asection *input_section ATTRIBUTE_UNUSED;
201     bfd *output_bfd;
202     char **error_message ATTRIBUTE_UNUSED;
203{
204  asection *osec;
205
206  if (output_bfd == NULL)
207    {
208      /* Not generating relocatable output file.  */
209      return bfd_reloc_continue;
210    }
211
212  if (bfd_is_und_section (bfd_get_section (symbol)))
213    {
214      /* Symbol is not defined, so no need to worry about it.  */
215      return bfd_reloc_continue;
216    }
217
218  if (bfd_is_com_section (bfd_get_section (symbol)))
219    {
220      /* I don't really know what the right action is for a common
221         symbol.  */
222      return bfd_reloc_continue;
223    }
224
225  /* Convert the reloc to use the section symbol.  FIXME: This method
226     is ridiculous.  */
227  osec = bfd_get_section (symbol)->output_section;
228  if (coff_section_data (output_bfd, osec) != NULL
229      && coff_section_data (output_bfd, osec)->tdata != NULL)
230    reloc_entry->sym_ptr_ptr =
231      (asymbol **) coff_section_data (output_bfd, osec)->tdata;
232  else
233    {
234      const char *sec_name;
235      asymbol **syms, **sym_end;
236
237      sec_name = bfd_get_section_name (output_bfd, osec);
238      syms = bfd_get_outsymbols (output_bfd);
239      sym_end = syms + bfd_get_symcount (output_bfd);
240      for (; syms < sym_end; syms++)
241	{
242	  if (bfd_asymbol_name (*syms) != NULL
243	      && (*syms)->value == 0
244	      && strcmp ((*syms)->section->output_section->name,
245			 sec_name) == 0)
246	    break;
247	}
248
249      if (syms >= sym_end)
250	abort ();
251
252      reloc_entry->sym_ptr_ptr = syms;
253
254      if (coff_section_data (output_bfd, osec) == NULL)
255	{
256	  bfd_size_type amt = sizeof (struct coff_section_tdata);
257	  osec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
258	  if (osec->used_by_bfd == NULL)
259	    return bfd_reloc_overflow;
260	}
261      coff_section_data (output_bfd, osec)->tdata = (PTR) syms;
262    }
263
264  /* Let bfd_perform_relocation do its thing, which will include
265     stuffing the symbol addend into the object file.  */
266  return bfd_reloc_continue;
267}
268
269static reloc_howto_type howto_rellong =
270  HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,FALSE, 0,
271	 complain_overflow_bitfield, coff_i960_relocate,"rellong", TRUE,
272	 0xffffffff, 0xffffffff, 0);
273static reloc_howto_type howto_iprmed =
274  HOWTO (R_IPRMED, 0, 2, 24,TRUE,0, complain_overflow_signed,
275	 coff_i960_relocate, "iprmed ", TRUE, 0x00ffffff, 0x00ffffff, 0);
276static reloc_howto_type howto_optcall =
277  HOWTO (R_OPTCALL, 0,2,24,TRUE,0, complain_overflow_signed,
278	 optcall_callback, "optcall", TRUE, 0x00ffffff, 0x00ffffff, 0);
279
280static reloc_howto_type *
281coff_i960_reloc_type_lookup (abfd, code)
282     bfd *abfd ATTRIBUTE_UNUSED;
283     bfd_reloc_code_real_type code;
284{
285  switch (code)
286    {
287    default:
288      return 0;
289    case BFD_RELOC_I960_CALLJ:
290      return &howto_optcall;
291    case BFD_RELOC_32:
292    case BFD_RELOC_CTOR:
293      return &howto_rellong;
294    case BFD_RELOC_24_PCREL:
295      return &howto_iprmed;
296    }
297}
298
299/* The real code is in coffcode.h */
300
301#define RTYPE2HOWTO(cache_ptr, dst) \
302{							\
303   reloc_howto_type *howto_ptr;				\
304   switch ((dst)->r_type) {				\
305     case 17: howto_ptr = &howto_rellong; break;	\
306     case 25: howto_ptr = &howto_iprmed; break;		\
307     case 27: howto_ptr = &howto_optcall; break;	\
308     default: howto_ptr = 0; break;			\
309     }							\
310   (cache_ptr)->howto = howto_ptr;			\
311 }
312
313/* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not
314   appear to correctly handle a reloc against a symbol defined in the
315   same object file.  It appears to simply discard such relocs, rather
316   than adding their values into the object file.  We handle this by
317   converting all relocs against global symbols into relocs against
318   internal symbols at the start of the section.  This routine is
319   called at the start of the linking process, and it creates the
320   necessary symbols.  */
321
322static bfd_boolean
323coff_i960_start_final_link (abfd, info)
324     bfd *abfd;
325     struct bfd_link_info *info;
326{
327  bfd_size_type symesz = bfd_coff_symesz (abfd);
328  asection *o;
329  bfd_byte *esym;
330
331  if (! info->relocatable)
332    return TRUE;
333
334  esym = (bfd_byte *) bfd_malloc (symesz);
335  if (esym == NULL)
336    return FALSE;
337
338  if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
339    return FALSE;
340
341  for (o = abfd->sections; o != NULL; o = o->next)
342    {
343      struct internal_syment isym;
344
345      strncpy (isym._n._n_name, o->name, SYMNMLEN);
346      isym.n_value = 0;
347      isym.n_scnum = o->target_index;
348      isym.n_type = T_NULL;
349      isym.n_sclass = C_STAT;
350      isym.n_numaux = 0;
351
352      bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
353
354      if (bfd_bwrite (esym, symesz, abfd) != symesz)
355	{
356	  free (esym);
357	  return FALSE;
358	}
359
360      obj_raw_syment_count (abfd) += 1;
361    }
362
363  free (esym);
364
365  return TRUE;
366}
367
368/* The reloc processing routine for the optimized COFF linker.  */
369
370static bfd_boolean
371coff_i960_relocate_section (output_bfd, info, input_bfd, input_section,
372			    contents, relocs, syms, sections)
373     bfd *output_bfd ATTRIBUTE_UNUSED;
374     struct bfd_link_info *info;
375     bfd *input_bfd;
376     asection *input_section;
377     bfd_byte *contents;
378     struct internal_reloc *relocs;
379     struct internal_syment *syms;
380     asection **sections;
381{
382  struct internal_reloc *rel;
383  struct internal_reloc *relend;
384
385  rel = relocs;
386  relend = rel + input_section->reloc_count;
387  for (; rel < relend; rel++)
388    {
389      long symndx;
390      struct coff_link_hash_entry *h;
391      struct internal_syment *sym;
392      bfd_vma addend;
393      bfd_vma val;
394      reloc_howto_type *howto;
395      bfd_reloc_status_type rstat = bfd_reloc_ok;
396      bfd_boolean done;
397
398      symndx = rel->r_symndx;
399
400      if (symndx == -1)
401	{
402	  h = NULL;
403	  sym = NULL;
404	}
405      else
406	{
407	  h = obj_coff_sym_hashes (input_bfd)[symndx];
408	  sym = syms + symndx;
409	}
410
411      if (sym != NULL && sym->n_scnum != 0)
412	addend = - sym->n_value;
413      else
414	addend = 0;
415
416      switch (rel->r_type)
417	{
418	case 17: howto = &howto_rellong; break;
419	case 25: howto = &howto_iprmed; break;
420	case 27: howto = &howto_optcall; break;
421	default:
422	  bfd_set_error (bfd_error_bad_value);
423	  return FALSE;
424	}
425
426      val = 0;
427
428      if (h == NULL)
429	{
430	  asection *sec;
431
432	  if (symndx == -1)
433	    {
434	      sec = bfd_abs_section_ptr;
435	      val = 0;
436	    }
437	  else
438	    {
439	      sec = sections[symndx];
440              val = (sec->output_section->vma
441		     + sec->output_offset
442		     + sym->n_value
443		     - sec->vma);
444	    }
445	}
446      else
447	{
448	  if (h->root.type == bfd_link_hash_defined
449	      || h->root.type == bfd_link_hash_defweak)
450	    {
451	      asection *sec;
452
453	      sec = h->root.u.def.section;
454	      val = (h->root.u.def.value
455		     + sec->output_section->vma
456		     + sec->output_offset);
457	    }
458	  else if (! info->relocatable)
459	    {
460	      if (! ((*info->callbacks->undefined_symbol)
461		     (info, h->root.root.string, input_bfd, input_section,
462		      rel->r_vaddr - input_section->vma, TRUE)))
463		return FALSE;
464	    }
465	}
466
467      done = FALSE;
468
469      if (howto->type == R_OPTCALL && ! info->relocatable && symndx != -1)
470	{
471	  int class;
472
473	  if (h != NULL)
474	    class = h->class;
475	  else
476	    class = sym->n_sclass;
477
478	  switch (class)
479	    {
480	    case C_NULL:
481	      /* This symbol is apparently not from a COFF input file.
482                 We warn, and then assume that it is not a leaf
483                 function.  */
484	      if (! ((*info->callbacks->reloc_dangerous)
485		     (info,
486		      _("uncertain calling convention for non-COFF symbol"),
487		      input_bfd, input_section,
488		      rel->r_vaddr - input_section->vma)))
489		return FALSE;
490	      break;
491	    case C_LEAFSTAT:
492	    case C_LEAFEXT:
493	      /* This is a call to a leaf procedure; use the bal
494                 instruction.  */
495	      {
496		long olf;
497		unsigned long word;
498
499		if (h != NULL)
500		  {
501		    BFD_ASSERT (h->numaux == 2);
502		    olf = h->aux[1].x_bal.x_balntry;
503		  }
504		else
505		  {
506		    bfd_byte *esyms;
507		    union internal_auxent aux;
508
509		    BFD_ASSERT (sym->n_numaux == 2);
510		    esyms = (bfd_byte *) obj_coff_external_syms (input_bfd);
511		    esyms += (symndx + 2) * bfd_coff_symesz (input_bfd);
512		    bfd_coff_swap_aux_in (input_bfd, (PTR) esyms, sym->n_type,
513					  sym->n_sclass, 1, sym->n_numaux,
514					  (PTR) &aux);
515		    olf = aux.x_bal.x_balntry;
516		  }
517
518		word = bfd_get_32 (input_bfd,
519				   (contents
520				    + (rel->r_vaddr - input_section->vma)));
521		word = ((word + olf - val) & BAL_MASK) | BAL;
522		bfd_put_32 (input_bfd,
523			    (bfd_vma) word,
524			    contents + (rel->r_vaddr - input_section->vma));
525		done = TRUE;
526	      }
527	      break;
528	    case C_SCALL:
529	      BFD_ASSERT (0);
530	      break;
531	    }
532	}
533
534      if (! done)
535	{
536	  if (howto->pc_relative)
537	    addend += input_section->vma;
538	  rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
539					    contents,
540					    rel->r_vaddr - input_section->vma,
541					    val, addend);
542	}
543
544      switch (rstat)
545	{
546	default:
547	  abort ();
548	case bfd_reloc_ok:
549	  break;
550	case bfd_reloc_overflow:
551	  {
552	    const char *name;
553	    char buf[SYMNMLEN + 1];
554
555	    if (symndx == -1)
556	      name = "*ABS*";
557	    else if (h != NULL)
558	      name = NULL;
559	    else
560	      {
561		name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
562		if (name == NULL)
563		  return FALSE;
564	      }
565
566	    if (! ((*info->callbacks->reloc_overflow)
567		   (info, (h ? &h->root : NULL), name, howto->name,
568		    (bfd_vma) 0, input_bfd, input_section,
569		    rel->r_vaddr - input_section->vma)))
570	      return FALSE;
571	  }
572	}
573    }
574
575  return TRUE;
576}
577
578/* Adjust the symbol index of any reloc against a global symbol to
579   instead be a reloc against the internal symbol we created specially
580   for the section.  */
581
582static bfd_boolean
583coff_i960_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
584     bfd *obfd ATTRIBUTE_UNUSED;
585     struct bfd_link_info *info ATTRIBUTE_UNUSED;
586     bfd *ibfd;
587     asection *sec ATTRIBUTE_UNUSED;
588     struct internal_reloc *irel;
589     bfd_boolean *adjustedp;
590{
591  struct coff_link_hash_entry *h;
592
593  *adjustedp = FALSE;
594
595  h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
596  if (h == NULL
597      || (h->root.type != bfd_link_hash_defined
598	  && h->root.type != bfd_link_hash_defweak))
599    return TRUE;
600
601  irel->r_symndx = h->root.u.def.section->output_section->target_index - 1;
602  *adjustedp = TRUE;
603
604  return TRUE;
605}
606
607#define coff_bfd_is_local_label_name coff_i960_is_local_label_name
608
609#define coff_start_final_link coff_i960_start_final_link
610
611#define coff_relocate_section coff_i960_relocate_section
612
613#define coff_adjust_symndx coff_i960_adjust_symndx
614
615#define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
616
617#include "coffcode.h"
618
619extern const bfd_target icoff_big_vec;
620
621CREATE_LITTLE_COFF_TARGET_VEC (icoff_little_vec, "coff-Intel-little", 0, 0, '_', & icoff_big_vec, COFF_SWAP_TABLE)
622
623const bfd_target icoff_big_vec =
624{
625  "coff-Intel-big",		/* name */
626  bfd_target_coff_flavour,
627  BFD_ENDIAN_LITTLE,		/* data byte order is little */
628  BFD_ENDIAN_BIG,		/* header byte order is big */
629
630  (HAS_RELOC | EXEC_P |		/* object flags */
631   HAS_LINENO | HAS_DEBUG |
632   HAS_SYMS | HAS_LOCALS | WP_TEXT),
633
634  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
635  '_',				/* leading underscore */
636  '/',				/* ar_pad_char */
637  15,				/* ar_max_namelen */
638
639bfd_getl64, bfd_getl_signed_64, bfd_putl64,
640     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
641     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
642bfd_getb64, bfd_getb_signed_64, bfd_putb64,
643     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
644     bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
645
646  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
647     bfd_generic_archive_p, _bfd_dummy_target},
648  {bfd_false, coff_mkobject,	/* bfd_set_format */
649     _bfd_generic_mkarchive, bfd_false},
650  {bfd_false, coff_write_object_contents,	/* bfd_write_contents */
651     _bfd_write_archive_contents, bfd_false},
652
653     BFD_JUMP_TABLE_GENERIC (coff),
654     BFD_JUMP_TABLE_COPY (coff),
655     BFD_JUMP_TABLE_CORE (_bfd_nocore),
656     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
657     BFD_JUMP_TABLE_SYMBOLS (coff),
658     BFD_JUMP_TABLE_RELOCS (coff),
659     BFD_JUMP_TABLE_WRITE (coff),
660     BFD_JUMP_TABLE_LINK (coff),
661     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
662
663  & icoff_little_vec,
664
665  COFF_SWAP_TABLE
666};
667