OSDN Git Service

2000-03-01 H.J. Lu <hjl@gnu.org>
[pf3gnuchains/pf3gnuchains3x.git] / bfd / coff-i960.c
1 /* BFD back-end for Intel 960 COFF files.
2    Copyright (C) 1990, 91, 92, 93, 94, 95, 97, 98, 1999
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 bfd_h_get_32
52 #define PUT_SCNHDR_ALIGN bfd_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, word, (bfd_byte *) data + reloc_entry->address);
160         }
161         result = bfd_reloc_ok;
162         break;
163       case C_SCALL:
164         /* This is a call to a system call, replace with a calls to # */
165         BFD_ASSERT(0);
166         result = bfd_reloc_ok;
167         break;
168       default:
169         result = bfd_reloc_ok;
170         break;
171       }
172   }
173   return result;
174 }
175
176 /* i960 COFF is used by VxWorks 5.1.  However, VxWorks 5.1 does not
177    appear to correctly handle a reloc against a symbol defined in the
178    same object file.  It appears to simply discard such relocs, rather
179    than adding their values into the object file.  We handle this here
180    by converting all relocs against defined symbols into relocs
181    against the section symbol, when generating a relocateable output
182    file.
183
184    Note that this function is only called if we are not using the COFF
185    specific backend linker.  It only does something when doing a
186    relocateable link, which will almost certainly fail when not
187    generating COFF i960 output, so this function is actually no longer
188    useful.  It was used before this target was converted to use the
189    COFF specific backend linker.  */
190
191 static bfd_reloc_status_type 
192 coff_i960_relocate (abfd, reloc_entry, symbol, data, input_section,
193                     output_bfd, error_message)
194      bfd *abfd;
195      arelent *reloc_entry;
196      asymbol *symbol;
197      PTR data ATTRIBUTE_UNUSED;
198      asection *input_section ATTRIBUTE_UNUSED;
199      bfd *output_bfd;
200      char **error_message ATTRIBUTE_UNUSED;
201 {
202   asection *osec;
203
204   if (output_bfd == NULL)
205     {
206       /* Not generating relocateable output file.  */
207       return bfd_reloc_continue;
208     }
209
210   if (bfd_is_und_section (bfd_get_section (symbol)))
211     {
212       /* Symbol is not defined, so no need to worry about it.  */
213       return bfd_reloc_continue;
214     }
215
216   if (bfd_is_com_section (bfd_get_section (symbol)))
217     {
218       /* I don't really know what the right action is for a common
219          symbol.  */
220       return bfd_reloc_continue;
221     }
222
223   /* Convert the reloc to use the section symbol.  FIXME: This method
224      is ridiculous.  */
225   osec = bfd_get_section (symbol)->output_section;
226   if (coff_section_data (output_bfd, osec) != NULL
227       && coff_section_data (output_bfd, osec)->tdata != NULL)
228     reloc_entry->sym_ptr_ptr =
229       (asymbol **) coff_section_data (output_bfd, osec)->tdata;
230   else
231     {
232       const char *sec_name;
233       asymbol **syms, **sym_end;
234
235       sec_name = bfd_get_section_name (output_bfd, osec);
236       syms = bfd_get_outsymbols (output_bfd);
237       sym_end = syms + bfd_get_symcount (output_bfd);
238       for (; syms < sym_end; syms++)
239         {
240           if (bfd_asymbol_name (*syms) != NULL
241               && (*syms)->value == 0
242               && strcmp ((*syms)->section->output_section->name,
243                          sec_name) == 0)
244             break;
245         }
246
247       if (syms >= sym_end)
248         abort ();
249
250       reloc_entry->sym_ptr_ptr = syms;
251
252       if (coff_section_data (output_bfd, osec) == NULL)
253         {
254           osec->used_by_bfd =
255             ((PTR) bfd_zalloc (abfd,
256                                sizeof (struct coff_section_tdata)));
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_write (esym, symesz, 1, 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                             word,
523                             (contents
524                              + (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 /*ARGSUSED*/
582 static boolean
583 coff_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      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
619 extern const bfd_target icoff_big_vec;
620
621 CREATE_LITTLE_COFF_TARGET_VEC (icoff_little_vec, "coff-Intel-little", 0, 0, '_', & icoff_big_vec)
622
623 const 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
639 bfd_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 */
642 bfd_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 };