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