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