OSDN Git Service

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