This commit was manufactured by cvs2svn to create branch
[external/binutils.git] / bfd / coff-i960.c
1 /* BFD back-end for Intel 960 COFF files.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
3    2002 Free Software Foundation, Inc.
4    Written by Cygnus Support.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
32 static bfd_boolean coff_i960_is_local_label_name
33   PARAMS ((bfd *, const char *));
34 static bfd_reloc_status_type optcall_callback
35   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36 static bfd_reloc_status_type coff_i960_relocate
37   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38 static reloc_howto_type *coff_i960_reloc_type_lookup
39   PARAMS ((bfd *, bfd_reloc_code_real_type));
40 static bfd_boolean coff_i960_start_final_link
41   PARAMS ((bfd *, struct bfd_link_info *));
42 static 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 **));
45 static 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
63 static bfd_boolean
64 coff_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
103 static bfd_reloc_status_type
104 optcall_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 relocateable 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    relocateable 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
193 static bfd_reloc_status_type
194 coff_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 relocateable 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
269 static 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);
273 static 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);
276 static 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
280 static reloc_howto_type *
281 coff_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
322 static bfd_boolean
323 coff_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->relocateable)
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
370 static bfd_boolean
371 coff_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->relocateable)
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->relocateable && 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 = h->root.root.string;
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, name, howto->name, (bfd_vma) 0, input_bfd,
568                     input_section, rel->r_vaddr - input_section->vma)))
569               return FALSE;
570           }
571         }
572     }
573
574   return TRUE;
575 }
576
577 /* Adjust the symbol index of any reloc against a global symbol to
578    instead be a reloc against the internal symbol we created specially
579    for the section.  */
580
581 static bfd_boolean
582 coff_i960_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
583      bfd *obfd ATTRIBUTE_UNUSED;
584      struct bfd_link_info *info ATTRIBUTE_UNUSED;
585      bfd *ibfd;
586      asection *sec ATTRIBUTE_UNUSED;
587      struct internal_reloc *irel;
588      bfd_boolean *adjustedp;
589 {
590   struct coff_link_hash_entry *h;
591
592   *adjustedp = FALSE;
593
594   h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
595   if (h == NULL
596       || (h->root.type != bfd_link_hash_defined
597           && h->root.type != bfd_link_hash_defweak))
598     return TRUE;
599
600   irel->r_symndx = h->root.u.def.section->output_section->target_index - 1;
601   *adjustedp = TRUE;
602
603   return TRUE;
604 }
605
606 #define coff_bfd_is_local_label_name coff_i960_is_local_label_name
607
608 #define coff_start_final_link coff_i960_start_final_link
609
610 #define coff_relocate_section coff_i960_relocate_section
611
612 #define coff_adjust_symndx coff_i960_adjust_symndx
613
614 #define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
615
616 #include "coffcode.h"
617
618 extern const bfd_target icoff_big_vec;
619
620 CREATE_LITTLE_COFF_TARGET_VEC (icoff_little_vec, "coff-Intel-little", 0, 0, '_', & icoff_big_vec)
621
622 const bfd_target icoff_big_vec =
623 {
624   "coff-Intel-big",             /* name */
625   bfd_target_coff_flavour,
626   BFD_ENDIAN_LITTLE,            /* data byte order is little */
627   BFD_ENDIAN_BIG,               /* header byte order is big */
628
629   (HAS_RELOC | EXEC_P |         /* object flags */
630    HAS_LINENO | HAS_DEBUG |
631    HAS_SYMS | HAS_LOCALS | WP_TEXT),
632
633   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
634   '_',                          /* leading underscore */
635   '/',                          /* ar_pad_char */
636   15,                           /* ar_max_namelen */
637
638 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
639      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
640      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
641 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
642      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
643      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
644
645   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
646      bfd_generic_archive_p, _bfd_dummy_target},
647   {bfd_false, coff_mkobject,    /* bfd_set_format */
648      _bfd_generic_mkarchive, bfd_false},
649   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
650      _bfd_write_archive_contents, bfd_false},
651
652      BFD_JUMP_TABLE_GENERIC (coff),
653      BFD_JUMP_TABLE_COPY (coff),
654      BFD_JUMP_TABLE_CORE (_bfd_nocore),
655      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
656      BFD_JUMP_TABLE_SYMBOLS (coff),
657      BFD_JUMP_TABLE_RELOCS (coff),
658      BFD_JUMP_TABLE_WRITE (coff),
659      BFD_JUMP_TABLE_LINK (coff),
660      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
661
662   & icoff_little_vec,
663
664   COFF_SWAP_TABLE
665 };