]> Git Repo - binutils.git/blob - bfd/coff-arm.c
This commit was generated by cvs2svn to track changes on a CVS vendor
[binutils.git] / bfd / coff-arm.c
1 /* BFD back-end for ARM COFF files.
2    Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
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 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25
26 #include "coff/arm.h"
27
28 #include "coff/internal.h"
29
30 #ifdef COFF_WITH_PE
31 #include "coff/pe.h"
32 #endif
33
34 #include "libcoff.h"
35
36 /* Macros for manipulation the bits in the flags field of the coff data
37    structure.  */
38 #define APCS_26_FLAG(       abfd )      (coff_data (abfd)->flags & F_APCS_26)
39 #define APCS_FLOAT_FLAG(    abfd )      (coff_data (abfd)->flags & F_APCS_FLOAT)
40 #define PIC_FLAG(           abfd )      (coff_data (abfd)->flags & F_PIC)
41 #define APCS_SET(           abfd )      (coff_data (abfd)->flags & F_APCS_SET)
42 #define SET_APCS_FLAGS(     abfd, flgs) (coff_data (abfd)->flags = \
43                                         (coff_data (abfd)->flags & ~ (F_APCS_26 | F_APCS_FLOAT | F_PIC)) \
44                                          | (flgs | F_APCS_SET))
45 #define INTERWORK_FLAG(     abfd )      (coff_data (abfd)->flags & F_INTERWORK)
46 #define INTERWORK_SET(      abfd )      (coff_data (abfd)->flags & F_INTERWORK_SET)
47 #define SET_INTERWORK_FLAG( abfd, flg ) (coff_data (abfd)->flags = \
48                                         (coff_data (abfd)->flags & ~ F_INTERWORK) \
49                                          | (flg | F_INTERWORK_SET))
50      
51 typedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;
52 /* some typedefs for holding instructions */
53 typedef unsigned long int insn32;
54 typedef unsigned short int insn16;
55
56
57      /* Forward declarations for stupid compilers.  */
58 static boolean coff_arm_relocate_section
59   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
60            struct internal_reloc *, struct internal_syment *, asection **));
61 static bfd_reloc_status_type aoutarm_fix_pcrel_26_done
62   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
63 static bfd_reloc_status_type aoutarm_fix_pcrel_26
64   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
65 static bfd_reloc_status_type coff_thumb_pcrel_23
66   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
67 static bfd_reloc_status_type coff_thumb_pcrel_12
68   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
69 static bfd_reloc_status_type coff_thumb_pcrel_9
70   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
71 static bfd_reloc_status_type coff_arm_reloc
72   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
73 static boolean coff_arm_adjust_symndx
74   PARAMS ((bfd *, struct bfd_link_info *, bfd *,
75            asection *, struct internal_reloc *, boolean *));
76 static reloc_howto_type * coff_arm_rtype_to_howto 
77   PARAMS ((bfd *, asection *, struct internal_reloc *,
78            struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
79 static bfd_reloc_status_type coff_thumb_pcrel_common
80   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **,
81            thumb_pcrel_branchtype));
82 static CONST struct reloc_howto_struct * coff_arm_reloc_type_lookup
83   PARAMS ((bfd *, bfd_reloc_code_real_type));
84 static struct bfd_link_hash_table * coff_arm_link_hash_table_create
85   PARAMS ((bfd *));
86 static insn32 insert_thumb_branch
87   PARAMS ((insn32, int));
88 static struct coff_link_hash_entry * find_thumb_glue
89   PARAMS ((struct bfd_link_info *, CONST char *, bfd *));
90 static struct coff_link_hash_entry * find_arm_glue
91   PARAMS ((struct bfd_link_info *, CONST char *, bfd *));
92 static void record_arm_to_thumb_glue
93   PARAMS ((struct bfd_link_info *, struct coff_link_hash_entry *));
94 static void record_thumb_to_arm_glue
95   PARAMS ((struct bfd_link_info *, struct coff_link_hash_entry *));
96 static boolean coff_arm_merge_private_bfd_data
97   PARAMS ((bfd *, bfd *));
98 static boolean coff_arm_print_private_bfd_data
99   PARAMS ((bfd *, PTR));
100 static boolean _bfd_coff_arm_set_private_flags
101   PARAMS ((bfd *, flagword));
102 static boolean coff_arm_copy_private_bfd_data
103   PARAMS ((bfd *, bfd *));
104 static boolean coff_arm_is_local_label_name
105   PARAMS ((bfd *, const char *));
106 static boolean coff_arm_link_output_has_begun
107   PARAMS ((bfd *, struct coff_final_link_info *));
108 static boolean coff_arm_final_link_postscript
109   PARAMS ((bfd *, struct coff_final_link_info *));
110
111 /* The linker script knows the section names for placement.
112    The entry_names are used to do simple name mangling on the stubs.
113    Given a function name, and its type, the stub can be found. The
114    name can be changed. The only requirement is the %s be present.
115    */
116    
117 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
118 #define THUMB2ARM_GLUE_ENTRY_NAME   "__%s_from_thumb"
119
120 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
121 #define ARM2THUMB_GLUE_ENTRY_NAME   "__%s_from_arm"
122
123 /* Used by the assembler. */
124 static bfd_reloc_status_type
125 coff_arm_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
126                  error_message)
127      bfd *abfd;
128      arelent *reloc_entry;
129      asymbol *symbol;
130      PTR data;
131      asection *input_section;
132      bfd *output_bfd;
133      char **error_message;
134 {
135   symvalue diff;
136   if (output_bfd == (bfd *) NULL)
137     return bfd_reloc_continue;
138
139   diff = reloc_entry->addend;
140
141 #define DOIT(x) \
142   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
143
144     if (diff != 0)
145       {
146         reloc_howto_type *howto = reloc_entry->howto;
147         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
148
149         switch (howto->size)
150           {
151           case 0:
152             {
153               char x = bfd_get_8 (abfd, addr);
154               DOIT (x);
155               bfd_put_8 (abfd, x, addr);
156             }
157             break;
158
159           case 1:
160             {
161               short x = bfd_get_16 (abfd, addr);
162               DOIT (x);
163               bfd_put_16 (abfd, x, addr);
164             }
165             break;
166
167           case 2:
168             {
169               long x = bfd_get_32 (abfd, addr);
170               DOIT (x);
171               bfd_put_32 (abfd, x, addr);
172             }
173             break;
174
175           default:
176             abort ();
177           }
178       }
179
180   /* Now let bfd_perform_relocation finish everything up.  */
181   return bfd_reloc_continue;
182 }
183
184 #define TARGET_UNDERSCORE '_'
185
186 #ifndef PCRELOFFSET
187 #define PCRELOFFSET true
188 #endif
189
190 /* These most certainly belong somewhere else. Just had to get rid of
191    the manifest constants in the code. */
192
193 #define ARM_8        0
194 #define ARM_16       1
195 #define ARM_32       2
196 #define ARM_26       3
197 #define ARM_DISP8    4
198 #define ARM_DISP16   5
199 #define ARM_DISP32   6
200 #define ARM_26D      7
201 /* 8 is unused */
202 #define ARM_NEG16    9
203 #define ARM_NEG32   10
204 #define ARM_RVA32   11
205 #define ARM_THUMB9  12
206 #define ARM_THUMB12 13
207 #define ARM_THUMB23 14
208
209 static reloc_howto_type aoutarm_std_reloc_howto[] = 
210 {
211   /* type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
212   HOWTO(ARM_8,                  /* type */
213         0,                      /* rightshift */
214         0,                      /* size */
215         8,                      /* bitsize */
216         false,                  /* pc_relative */
217         0,                      /* bitpos */
218         complain_overflow_bitfield, /* complain_on_overflow */
219         coff_arm_reloc,         /* special_function */
220         "ARM_8",                /* name */
221         true,                   /* partial_inplace */
222         0x000000ff,             /* src_mask */
223         0x000000ff,             /* dst_mask */
224         PCRELOFFSET             /* pcrel_offset */),
225   HOWTO(ARM_16,  
226         0, 
227         1, 
228         16, 
229         false,
230         0,
231         complain_overflow_bitfield,
232         coff_arm_reloc,
233         "ARM_16", 
234         true,
235         0x0000ffff,
236         0x0000ffff, 
237         PCRELOFFSET),
238   HOWTO(ARM_32, 
239         0,
240         2, 
241         32,
242         false,
243         0,
244         complain_overflow_bitfield,
245         coff_arm_reloc,
246         "ARM_32",
247         true,
248         0xffffffff,
249         0xffffffff,
250         PCRELOFFSET),
251   HOWTO(ARM_26,
252         2,
253         2,
254         24,
255         true,
256         0,
257         complain_overflow_signed,
258         aoutarm_fix_pcrel_26 ,
259         "ARM_26",
260         false,
261         0x00ffffff,
262         0x00ffffff, 
263         PCRELOFFSET),
264   HOWTO(ARM_DISP8,        
265         0,
266         0,
267         8, 
268         true,
269         0,
270         complain_overflow_signed, 
271         coff_arm_reloc,
272         "ARM_DISP8",  
273         true,
274         0x000000ff,
275         0x000000ff,
276         true),
277   HOWTO( ARM_DISP16, 
278         0,
279         1,
280         16,
281         true,
282         0,
283         complain_overflow_signed, 
284         coff_arm_reloc,
285         "ARM_DISP16",
286         true,
287         0x0000ffff,
288         0x0000ffff,
289         true),
290   HOWTO( ARM_DISP32,
291         0,
292         2,
293         32,
294         true,
295         0,
296         complain_overflow_signed, 
297         coff_arm_reloc,
298         "ARM_DISP32",
299         true,
300         0xffffffff,
301         0xffffffff,
302         true),
303   HOWTO( ARM_26D,  
304         2, 
305         2,
306         24,
307         false,
308         0,
309         complain_overflow_dont,
310         aoutarm_fix_pcrel_26_done, 
311         "ARM_26D",
312         true,
313         0x00ffffff,
314         0x0,
315         false),
316   /* 8 is unused */
317   {-1},
318   HOWTO( ARM_NEG16,
319         0,
320         -1,
321         16,
322         false,
323         0, 
324         complain_overflow_bitfield,
325         coff_arm_reloc,
326         "ARM_NEG16",
327         true, 
328         0x0000ffff,
329         0x0000ffff, 
330         false),
331   HOWTO( ARM_NEG32, 
332         0, 
333         -2,
334         32,
335         false,
336         0,
337         complain_overflow_bitfield,
338         coff_arm_reloc,
339         "ARM_NEG32",
340         true,
341         0xffffffff,
342         0xffffffff,
343         false),
344   HOWTO( ARM_RVA32, 
345         0,
346         2, 
347         32,
348         false,
349         0,
350         complain_overflow_bitfield,
351         coff_arm_reloc,
352         "ARM_RVA32",
353         true,
354         0xffffffff,
355         0xffffffff,
356         PCRELOFFSET),
357   HOWTO( ARM_THUMB9,
358         1,
359         1,
360         8,
361         true,
362         0,
363         complain_overflow_signed,
364         coff_thumb_pcrel_9 ,
365         "ARM_THUMB9",
366         false,
367         0x000000ff,
368         0x000000ff, 
369         PCRELOFFSET),
370   HOWTO( ARM_THUMB12,
371         1,
372         1,
373         11,
374         true,
375         0,
376         complain_overflow_signed,
377         coff_thumb_pcrel_12 ,
378         "ARM_THUMB12",
379         false,
380         0x000007ff,
381         0x000007ff, 
382         PCRELOFFSET),
383   HOWTO( ARM_THUMB23,
384         1,
385         2,
386         22,
387         true,
388         0,
389         complain_overflow_signed,
390         coff_thumb_pcrel_23 ,
391         "ARM_THUMB23",
392         false,
393         0x07ff07ff,
394         0x07ff07ff, 
395         PCRELOFFSET),
396 };
397
398 #ifdef COFF_WITH_PE
399 /* Return true if this relocation should
400    appear in the output .reloc section. */
401
402 static boolean
403 in_reloc_p (abfd, howto)
404      bfd * abfd;
405      reloc_howto_type * howto;
406 {
407   return !howto->pc_relative && howto->type != ARM_RVA32;
408 }     
409 #endif
410
411
412 #define RTYPE2HOWTO(cache_ptr, dst) \
413             (cache_ptr)->howto = aoutarm_std_reloc_howto + (dst)->r_type;
414
415 #define coff_rtype_to_howto coff_arm_rtype_to_howto
416
417 static reloc_howto_type *
418 coff_arm_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
419      bfd *abfd;
420      asection *sec;
421      struct internal_reloc *rel;
422      struct coff_link_hash_entry *h;
423      struct internal_syment *sym;
424      bfd_vma *addendp;
425 {
426   reloc_howto_type *howto;
427
428   howto = aoutarm_std_reloc_howto + rel->r_type;
429
430   if (rel->r_type == ARM_RVA32)
431     {
432       *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
433     }
434
435   /* The relocation_section function will skip pcrel_offset relocs
436      when doing a relocateable link.  However, we want to convert
437      ARM26 to ARM26D relocs if possible.  We return a fake howto in
438      this case without pcrel_offset set, and adjust the addend to
439      compensate.  */
440   if (rel->r_type == ARM_26
441       && h != NULL
442       && (h->root.type == bfd_link_hash_defined
443           || h->root.type == bfd_link_hash_defweak)
444       && h->root.u.def.section->output_section == sec->output_section)
445     {
446       static reloc_howto_type fake_arm26_reloc = 
447         HOWTO (ARM_26,
448                2,
449                2,
450                24,
451                true,
452                0,
453                complain_overflow_signed,
454                aoutarm_fix_pcrel_26 ,
455                "ARM_26",
456                false,
457                0x00ffffff,
458                0x00ffffff, 
459                false);
460
461       *addendp -= rel->r_vaddr - sec->vma;
462       return & fake_arm26_reloc;
463     }
464
465   return howto;
466
467 }
468 /* Used by the assembler. */
469
470 static bfd_reloc_status_type
471 aoutarm_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section,
472                           output_bfd, error_message)
473      bfd *abfd;
474      arelent *reloc_entry;
475      asymbol *symbol;
476      PTR data;
477      asection *input_section;
478      bfd *output_bfd;
479      char **error_message;
480 {
481   /* This is dead simple at present.  */
482   return bfd_reloc_ok;
483 }
484
485 /* Used by the assembler. */
486
487 static bfd_reloc_status_type
488 aoutarm_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section,
489                      output_bfd, error_message)
490      bfd *abfd;
491      arelent *reloc_entry;
492      asymbol *symbol;
493      PTR data;
494      asection *input_section;
495      bfd *output_bfd;
496      char **error_message;
497 {
498   bfd_vma relocation;
499   bfd_size_type addr = reloc_entry->address;
500   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
501   bfd_reloc_status_type flag = bfd_reloc_ok;
502   
503   /* If this is an undefined symbol, return error */
504   if (symbol->section == &bfd_und_section
505       && (symbol->flags & BSF_WEAK) == 0)
506     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
507
508   /* If the sections are different, and we are doing a partial relocation,
509      just ignore it for now.  */
510   if (symbol->section->name != input_section->name
511       && output_bfd != (bfd *)NULL)
512     return bfd_reloc_continue;
513
514   relocation = (target & 0x00ffffff) << 2;
515   relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */
516   relocation += symbol->value;
517   relocation += symbol->section->output_section->vma;
518   relocation += symbol->section->output_offset;
519   relocation += reloc_entry->addend;
520   relocation -= input_section->output_section->vma;
521   relocation -= input_section->output_offset;
522   relocation -= addr;
523   
524   if (relocation & 3)
525     return bfd_reloc_overflow;
526
527   /* Check for overflow */
528   if (relocation & 0x02000000)
529     {
530       if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
531         flag = bfd_reloc_overflow;
532     }
533   else if (relocation & ~0x03ffffff)
534     flag = bfd_reloc_overflow;
535
536   target &= ~0x00ffffff;
537   target |= (relocation >> 2) & 0x00ffffff;
538   bfd_put_32 (abfd, target, (bfd_byte *) data + addr);
539
540   /* Now the ARM magic... Change the reloc type so that it is marked as done.
541      Strictly this is only necessary if we are doing a partial relocation.  */
542   reloc_entry->howto = &aoutarm_std_reloc_howto[ARM_26D];
543
544   return flag;
545 }
546
547 static bfd_reloc_status_type
548 coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data, input_section,
549                      output_bfd, error_message, btype)
550      bfd *abfd;
551      arelent *reloc_entry;
552      asymbol *symbol;
553      PTR data;
554      asection *input_section;
555      bfd *output_bfd;
556      char **error_message;
557      thumb_pcrel_branchtype btype;
558 {
559   bfd_vma relocation = 0;
560   bfd_size_type addr = reloc_entry->address;
561   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
562   bfd_reloc_status_type flag = bfd_reloc_ok;
563   bfd_vma dstmsk;
564   bfd_vma offmsk;
565   bfd_vma signbit;
566
567   /* NOTE: This routine is currently used by GAS, but not by the link
568      phase.  */
569
570   switch (btype)
571     {
572     case b9:
573       dstmsk  = 0x000000ff;
574       offmsk  = 0x000001fe;
575       signbit = 0x00000100;
576       break;
577
578     case b12:
579       dstmsk  = 0x000007ff;
580       offmsk  = 0x00000ffe;
581       signbit = 0x00000800;
582       break;
583
584     case b23:
585       dstmsk  = 0x07ff07ff;
586       offmsk  = 0x007fffff;
587       signbit = 0x00400000;
588       break;
589
590     default:
591       abort ();
592     }
593   
594   /* If this is an undefined symbol, return error */
595   if (symbol->section == &bfd_und_section
596       && (symbol->flags & BSF_WEAK) == 0)
597     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
598
599   /* If the sections are different, and we are doing a partial relocation,
600      just ignore it for now.  */
601   if (symbol->section->name != input_section->name
602       && output_bfd != (bfd *)NULL)
603     return bfd_reloc_continue;
604
605   switch (btype)
606     {
607     case b9:
608     case b12:
609       relocation = ((target & dstmsk) << 1);
610       break;
611
612     case b23:
613       if (bfd_big_endian (abfd))
614         relocation = ((target & 0x7ff) << 1)  | ((target & 0x07ff0000) >> 4);
615       else
616         relocation = ((target & 0x7ff) << 12) | ((target & 0x07ff0000) >> 15);
617       break;
618
619     default:
620       abort ();
621     }
622
623   relocation = (relocation ^ signbit) - signbit; /* Sign extend */
624   relocation += symbol->value;
625   relocation += symbol->section->output_section->vma;
626   relocation += symbol->section->output_offset;
627   relocation += reloc_entry->addend;
628   relocation -= input_section->output_section->vma;
629   relocation -= input_section->output_offset;
630   relocation -= addr;
631
632   if (relocation & 1)
633     return bfd_reloc_overflow;
634
635   /* Check for overflow */
636   if (relocation & signbit)
637     {
638       if ((relocation & ~offmsk) != ~offmsk)
639         flag = bfd_reloc_overflow;
640     }
641   else if (relocation & ~offmsk)
642     flag = bfd_reloc_overflow;
643
644   target &= ~dstmsk;
645   switch (btype)
646    {
647    case b9:
648    case b12:
649      target |= (relocation >> 1);
650      break;
651
652    case b23:
653      if (bfd_big_endian (abfd))
654        target |= ((relocation & 0xfff) >> 1)  | ((relocation << 4)  & 0x07ff0000);
655      else
656        target |= ((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff);
657      break;
658
659    default:
660      abort ();
661    }
662
663   bfd_put_32 (abfd, target, (bfd_byte *) data + addr);
664
665   /* Now the ARM magic... Change the reloc type so that it is marked as done.
666      Strictly this is only necessary if we are doing a partial relocation.  */
667   reloc_entry->howto = & aoutarm_std_reloc_howto [ARM_26D];
668   
669   /* TODO: We should possibly have DONE entries for the THUMB PCREL relocations */
670   return flag;
671 }
672
673 static bfd_reloc_status_type
674 coff_thumb_pcrel_23 (abfd, reloc_entry, symbol, data, input_section,
675                      output_bfd, error_message)
676      bfd *abfd;
677      arelent *reloc_entry;
678      asymbol *symbol;
679      PTR data;
680      asection *input_section;
681      bfd *output_bfd;
682      char **error_message;
683 {
684   return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
685                                   input_section, output_bfd, error_message, b23);
686 }
687
688 static bfd_reloc_status_type
689 coff_thumb_pcrel_12 (abfd, reloc_entry, symbol, data, input_section,
690                      output_bfd, error_message)
691      bfd *abfd;
692      arelent *reloc_entry;
693      asymbol *symbol;
694      PTR data;
695      asection *input_section;
696      bfd *output_bfd;
697      char **error_message;
698 {
699   return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
700                                   input_section, output_bfd, error_message, b12);
701 }
702
703 static bfd_reloc_status_type
704 coff_thumb_pcrel_9 (abfd, reloc_entry, symbol, data, input_section,
705                      output_bfd, error_message)
706      bfd *abfd;
707      arelent *reloc_entry;
708      asymbol *symbol;
709      PTR data;
710      asection *input_section;
711      bfd *output_bfd;
712      char **error_message;
713 {
714   return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
715                                   input_section, output_bfd, error_message, b9);
716 }
717
718
719 static CONST struct reloc_howto_struct *
720 coff_arm_reloc_type_lookup (abfd, code)
721       bfd * abfd;
722       bfd_reloc_code_real_type code;
723 {
724 #define ASTD(i,j)       case i: return &aoutarm_std_reloc_howto[j]
725   if (code == BFD_RELOC_CTOR)
726     switch (bfd_get_arch_info (abfd)->bits_per_address)
727       {
728       case 32:
729         code = BFD_RELOC_32;
730         break;
731       default: return (CONST struct reloc_howto_struct *) 0;
732       }
733
734   switch (code)
735     {
736       ASTD (BFD_RELOC_8,                    ARM_8);
737       ASTD (BFD_RELOC_16,                   ARM_16);
738       ASTD (BFD_RELOC_32,                   ARM_32);
739       ASTD (BFD_RELOC_ARM_PCREL_BRANCH,     ARM_26);
740       ASTD (BFD_RELOC_8_PCREL,              ARM_DISP8);
741       ASTD (BFD_RELOC_16_PCREL,             ARM_DISP16);
742       ASTD (BFD_RELOC_32_PCREL,             ARM_DISP32);
743       ASTD (BFD_RELOC_RVA,                  ARM_RVA32);
744       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH9,  ARM_THUMB9);
745       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
746       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH23, ARM_THUMB23);
747     default: return (CONST struct reloc_howto_struct *) 0;
748     }
749 }
750
751 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
752 #define COFF_PAGE_SIZE 0x1000
753 /* Turn a howto into a reloc  nunmber */
754
755 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
756 #define BADMAG(x) ARMBADMAG(x)
757 #define ARM 1                   /* Customize coffcode.h */
758
759 /* Extend the coff_link_hash_table structure with a few ARM specific fields.
760    This allows us to store global data here without actually creating any
761    global variables, which is a no-no in the BFD world.  */
762 struct coff_arm_link_hash_table
763 {
764   /* The original coff_link_hash_table structure.  MUST be first field.  */
765   struct coff_link_hash_table   root;
766   
767   /* The size in bytes of the section containg the Thumb-to-ARM glue.  */
768   long int                      thumb_glue_size;
769   
770   /* The size in bytes of the section containg the ARM-to-Thumb glue.  */
771   long int                      arm_glue_size;
772
773   /* An arbitary input BFD chosen to hold the glue sections.  */
774   bfd *                         bfd_of_glue_owner;
775
776   /* Support interworking with old, non-interworking aware ARM code. */
777   int                           support_old_code;
778 };
779
780 /* Get the ARM coff linker hash table from a link_info structure.  */
781 #define coff_arm_hash_table(info) \
782   ((struct coff_arm_link_hash_table *) ((info)->hash))
783
784 /* Create an ARM coff linker hash table.  */
785
786 static struct bfd_link_hash_table *
787 coff_arm_link_hash_table_create (abfd)
788      bfd * abfd;
789 {
790   struct coff_arm_link_hash_table * ret;
791
792   ret = ((struct coff_arm_link_hash_table *)
793          bfd_alloc (abfd, sizeof (struct coff_arm_link_hash_table)));
794   if (ret == (struct coff_arm_link_hash_table *) NULL)
795     return NULL;
796
797   if (! _bfd_coff_link_hash_table_init
798       (& ret->root, abfd, _bfd_coff_link_hash_newfunc))
799     {
800       bfd_release (abfd, ret);
801       return (struct bfd_link_hash_table *) NULL;
802     }
803
804   ret->thumb_glue_size   = 0;
805   ret->arm_glue_size     = 0;
806   ret->bfd_of_glue_owner = NULL;
807
808   return & ret->root.root;
809 }
810
811 \f
812 /* The thumb form of a long branch is a bit finicky, because the offset
813    encoding is split over two fields, each in it's own instruction. They
814    can occur in any order. So given a thumb form of long branch, and an 
815    offset, insert the offset into the thumb branch and return finished
816    instruction. 
817
818    It takes two thumb instructions to encode the target address. Each has 
819    11 bits to invest. The upper 11 bits are stored in one (identifed by
820    H-0.. see below), the lower 11 bits are stored in the other (identified 
821    by H-1). 
822
823    Combine together and shifted left by 1 (it's a half word address) and 
824    there you have it.
825
826      Op: 1111 = F,
827      H-0, upper address-0 = 000
828      Op: 1111 = F,
829      H-1, lower address-0 = 800
830
831    They can be ordered either way, but the arm tools I've seen always put 
832    the lower one first. It probably doesn't matter. [email protected]
833
834    XXX:  Actually the order does matter.  The second instruction (H-1)
835    moves the computed address into the PC, so it must be the second one
836    in the sequence.  The problem, however is that whilst little endian code
837    stores the instructions in HI then LOW order, big endian code does the
838    reverse.  [email protected]  */
839
840 #define LOW_HI_ORDER 0xF800F000
841 #define HI_LOW_ORDER 0xF000F800
842
843 static insn32
844 insert_thumb_branch (br_insn, rel_off)
845      insn32 br_insn;
846      int rel_off;
847 {
848   unsigned int low_bits;
849   unsigned int high_bits;
850
851
852   BFD_ASSERT((rel_off & 1) != 1);
853
854   rel_off >>= 1;                              /* half word aligned address */
855   low_bits = rel_off & 0x000007FF;            /* the bottom 11 bits */
856   high_bits = (rel_off >> 11) & 0x000007FF;   /* the top 11 bits */
857
858   if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
859     br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
860   else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
861     br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
862   else
863     abort(); /* error - not a valid branch instruction form */
864
865   /* FIXME: abort is probably not the right call. [email protected] */
866
867   return br_insn;
868 }
869
870 \f
871 static struct coff_link_hash_entry *
872 find_thumb_glue (info, name, input_bfd)
873      struct bfd_link_info * info;
874      CONST char *           name;
875      bfd *                  input_bfd;
876 {
877   char *                        tmp_name;
878   struct coff_link_hash_entry * myh;
879
880   tmp_name = ((char *)
881          bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1));
882
883   BFD_ASSERT (tmp_name);
884
885   sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
886   
887   myh = coff_link_hash_lookup
888     (coff_hash_table (info), tmp_name, false, false, true);
889   
890   if (myh == NULL)
891     /* xgettext:c-format */
892     _bfd_error_handler (_("%s: unable to find THUMB glue '%s' for `%s'"),
893                         bfd_get_filename (input_bfd), tmp_name, name);
894   
895   free (tmp_name);
896
897   return myh;
898 }
899
900 static struct coff_link_hash_entry *
901 find_arm_glue (info, name, input_bfd)
902      struct bfd_link_info * info;
903      CONST char *           name;
904      bfd *                  input_bfd;
905 {
906   char *                        tmp_name;
907   struct coff_link_hash_entry * myh;
908
909   tmp_name = ((char *)
910               bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));
911
912   BFD_ASSERT (tmp_name);
913
914   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
915   
916   myh = coff_link_hash_lookup
917     (coff_hash_table (info), tmp_name, false, false, true);
918
919   if (myh == NULL)
920     /* xgettext:c-format */
921     _bfd_error_handler (_("%s: unable to find ARM glue '%s' for `%s'"),
922                         bfd_get_filename (input_bfd), tmp_name, name);
923   
924   free (tmp_name);
925
926   return myh;
927 }
928
929 /*
930   ARM->Thumb glue:
931
932        .arm
933        __func_from_arm:
934              ldr r12, __func_addr
935              bx  r12
936        __func_addr:
937             .word func    @ behave as if you saw a ARM_32 reloc
938 */
939
940 #define ARM2THUMB_GLUE_SIZE 12
941 static const insn32 a2t1_ldr_insn       = 0xe59fc000;
942 static const insn32 a2t2_bx_r12_insn    = 0xe12fff1c;
943 static const insn32 a2t3_func_addr_insn = 0x00000001;
944
945 /*
946    Thumb->ARM:                          Thumb->(non-interworking aware) ARM
947
948    .thumb                               .thumb
949    .align 2                             .align 2
950       __func_from_thumb:                   __func_from_thumb:
951            bx pc                                push {r6, lr}
952            nop                                  ldr  r6, __func_addr
953    .arm                                         mov  lr, pc
954       __func_change_to_arm:                     bx   r6
955            b func                       .arm
956                                            __func_back_to_thumb:
957                                                 ldmia r13! {r6, lr}
958                                                 bx    lr
959                                            __func_addr:
960                                                 .word   func 
961 */
962
963 #define THUMB2ARM_GLUE_SIZE (globals->support_old_code ? 20 : 8)
964 static const insn16 t2a1_bx_pc_insn = 0x4778;
965 static const insn16 t2a2_noop_insn  = 0x46c0;
966 static const insn32 t2a3_b_insn     = 0xea000000;
967
968 static const insn16 t2a1_push_insn  = 0xb540;
969 static const insn16 t2a2_ldr_insn   = 0x4e03;
970 static const insn16 t2a3_mov_insn   = 0x46fe;
971 static const insn16 t2a4_bx_insn    = 0x4730;
972 static const insn32 t2a5_pop_insn   = 0xe8bd4040;
973 static const insn32 t2a6_bx_insn    = 0xe12fff1e;
974
975 /* TODO:
976      We should really create new local (static) symbols in destination
977      object for each stub we create.  We should also create local
978      (static) symbols within the stubs when switching between ARM and
979      Thumb code.  This will ensure that the debugger and disassembler
980      can present a better view of stubs.
981
982      We can treat stubs like literal sections, and for the THUMB9 ones
983      (short addressing range) we should be able to insert the stubs
984      between sections. i.e. the simplest approach (since relocations
985      are done on a section basis) is to dump the stubs at the end of
986      processing a section. That way we can always try and minimise the
987      offset to and from a stub. However, this does not map well onto
988      the way that the linker/BFD does its work: mapping all input
989      sections to output sections via the linker script before doing
990      all the processing.
991
992      Unfortunately it may be easier to just to disallow short range
993      Thumb->ARM stubs (i.e. no conditional inter-working branches,
994      only branch-and-link (BL) calls.  This will simplify the processing
995      since we can then put all of the stubs into their own section.
996
997   TODO:
998      On a different subject, rather than complaining when a
999      branch cannot fit in the number of bits available for the
1000      instruction we should generate a trampoline stub (needed to
1001      address the complete 32bit address space).  */
1002
1003 /* The standard COFF backend linker does not cope with the special 
1004    Thumb BRANCH23 relocation.  The alternative would be to split the
1005    BRANCH23 into seperate HI23 and LO23 relocations. However, it is a
1006    bit simpler simply providing our own relocation driver. */
1007
1008 /* The reloc processing routine for the ARM/Thumb COFF linker.  NOTE:
1009    This code is a very slightly modified copy of
1010    _bfd_coff_generic_relocate_section.  It would be a much more
1011    maintainable solution to have a MACRO that could be expanded within
1012    _bfd_coff_generic_relocate_section that would only be provided for
1013    ARM/Thumb builds.  It is only the code marked THUMBEXTENSION that
1014    is different from the original.  */
1015
1016 static boolean
1017 coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
1018                            contents, relocs, syms, sections)
1019      bfd *output_bfd;
1020      struct bfd_link_info *info;
1021      bfd *input_bfd;
1022      asection *input_section;
1023      bfd_byte *contents;
1024      struct internal_reloc *relocs;
1025      struct internal_syment *syms;
1026      asection **sections;
1027 {
1028   struct internal_reloc * rel;
1029   struct internal_reloc * relend;
1030
1031   rel = relocs;
1032   relend = rel + input_section->reloc_count;
1033
1034   for (; rel < relend; rel++)
1035     {
1036       int                            done = 0;
1037       long                           symndx;
1038       struct coff_link_hash_entry *  h;
1039       struct internal_syment *       sym;
1040       bfd_vma                        addend;
1041       bfd_vma                        val;
1042       reloc_howto_type *             howto;
1043       bfd_reloc_status_type          rstat;
1044       bfd_vma                        h_val;
1045
1046       symndx = rel->r_symndx;
1047
1048       if (symndx == -1)
1049         {
1050           h = NULL;
1051           sym = NULL;
1052         }
1053       else
1054         {    
1055           h = obj_coff_sym_hashes (input_bfd)[symndx];
1056           sym = syms + symndx;
1057         }
1058
1059       /* COFF treats common symbols in one of two ways.  Either the
1060          size of the symbol is included in the section contents, or it
1061          is not.  We assume that the size is not included, and force
1062          the rtype_to_howto function to adjust the addend as needed.  */
1063
1064       if (sym != NULL && sym->n_scnum != 0)
1065         addend = - sym->n_value;
1066       else
1067         addend = 0;
1068
1069
1070       howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
1071                                        sym, &addend);
1072       if (howto == NULL)
1073         return false;
1074
1075       /* If we are doing a relocateable link, then we can just ignore
1076          a PC relative reloc that is pcrel_offset.  It will already
1077          have the correct value.  If this is not a relocateable link,
1078          then we should ignore the symbol value.  */
1079       if (howto->pc_relative && howto->pcrel_offset)
1080         {
1081           if (info->relocateable)
1082             continue;
1083           if (sym != NULL && sym->n_scnum != 0)
1084             addend += sym->n_value;
1085         }
1086
1087       /* If we are doing a relocateable link, then we can just ignore
1088          a PC relative reloc that is pcrel_offset.  It will already
1089          have the correct value.  */
1090       if (info->relocateable
1091           && howto->pc_relative
1092           && howto->pcrel_offset)
1093         continue;
1094
1095       val = 0;
1096
1097       if (h == NULL)
1098         {
1099           asection *sec;
1100
1101           if (symndx == -1)
1102             {
1103               sec = bfd_abs_section_ptr;
1104               val = 0;
1105             }
1106           else
1107             {
1108               sec = sections[symndx];
1109               val = (sec->output_section->vma
1110                      + sec->output_offset
1111                      + sym->n_value
1112                      - sec->vma);
1113             }
1114         }
1115       else
1116         {
1117 #if 1 /* THUMBEXTENSION */
1118           /* We don't output the stubs if we are generating a
1119              relocatable output file, since we may as well leave the
1120              stub generation to the final linker pass. If we fail to
1121              verify that the name is defined, we'll try to build stubs
1122              for an undefined name... */
1123           if (! info->relocateable
1124               && (   h->root.type == bfd_link_hash_defined
1125                   || h->root.type == bfd_link_hash_defweak))
1126             {
1127               asection *   h_sec = h->root.u.def.section;
1128               const char * name  = h->root.root.string;
1129               
1130               /* h locates the symbol referenced in the reloc.  */
1131               h_val = (h->root.u.def.value
1132                        + h_sec->output_section->vma
1133                        + h_sec->output_offset);
1134
1135               if (howto->type == ARM_26)
1136                 {
1137                   if (   h->class == C_THUMBSTATFUNC
1138                       || h->class == C_THUMBEXTFUNC)
1139                     {
1140                       /* Arm code calling a Thumb function */
1141                       unsigned long int                 tmp;
1142                       long int                          my_offset;
1143                       asection *                        s;
1144                       long int                          ret_offset;
1145                       struct coff_link_hash_entry *     myh; 
1146                       struct coff_arm_link_hash_table * globals;
1147                       
1148                       myh = find_arm_glue (info, name, input_bfd);
1149                       if (myh == NULL)
1150                         return false;
1151
1152                       globals = coff_arm_hash_table (info);
1153
1154                       BFD_ASSERT (globals != NULL);
1155                       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1156                         
1157                       my_offset = myh->root.u.def.value;
1158                       
1159                       s = bfd_get_section_by_name (globals->bfd_of_glue_owner, 
1160                                                   ARM2THUMB_GLUE_SECTION_NAME);
1161                       BFD_ASSERT (s != NULL);
1162                       BFD_ASSERT (s->contents != NULL);
1163                       BFD_ASSERT (s->output_section != NULL);
1164
1165                       if ((my_offset & 0x01) == 0x01)
1166                         {
1167                           if (h_sec->owner != NULL
1168                               && INTERWORK_SET (h_sec->owner)
1169                               && ! INTERWORK_FLAG (h_sec->owner))
1170                             {
1171                               _bfd_error_handler
1172                                 /* xgettext:c-format */
1173                                 (_("%s(%s): warning: interworking not enabled."),
1174                                  bfd_get_filename (h_sec->owner), name);
1175                               _bfd_error_handler
1176                                 /* xgettext:c-format */
1177                                 (_("  first occurrence: %s: arm call to thumb"),
1178                                  bfd_get_filename (input_bfd));
1179                             }
1180
1181                           --my_offset;
1182                           myh->root.u.def.value = my_offset;
1183
1184                           bfd_put_32 (output_bfd, a2t1_ldr_insn,
1185                                       s->contents + my_offset);
1186                           
1187                           bfd_put_32 (output_bfd, a2t2_bx_r12_insn,
1188                                       s->contents + my_offset + 4);
1189                           
1190                           /* It's a thumb address.  Add the low order bit.  */
1191                           bfd_put_32 (output_bfd, h_val | a2t3_func_addr_insn,
1192                                       s->contents + my_offset + 8);
1193                         }
1194
1195                       BFD_ASSERT (my_offset <= globals->arm_glue_size);
1196
1197                       tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
1198                                         - input_section->vma);
1199                       
1200                       tmp = tmp & 0xFF000000;
1201
1202                       /* Somehow these are both 4 too far, so subtract 8. */
1203                       ret_offset =
1204                         s->output_offset
1205                         + my_offset 
1206                         + s->output_section->vma
1207                         - (input_section->output_offset
1208                            + input_section->output_section->vma 
1209                            + rel->r_vaddr)
1210                         - 8;
1211
1212                       tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
1213                       
1214                       bfd_put_32 (output_bfd, tmp, contents + rel->r_vaddr
1215                                   - input_section->vma);
1216                       
1217                       done = 1;
1218                     }
1219                 }
1220               
1221               /* Note: We used to check for ARM_THUMB9 and ARM_THUMB12 */
1222               else if (howto->type == ARM_THUMB23)
1223                 {
1224                   if (   h->class == C_EXT 
1225                       || h->class == C_STAT
1226                       || h->class == C_LABEL)
1227                     {
1228                       /* Thumb code calling an ARM function */
1229                       asection *                         s = 0;
1230                       long int                           my_offset;
1231                       unsigned long int                  tmp;
1232                       long int                           ret_offset;
1233                       struct coff_link_hash_entry *      myh;
1234                       struct coff_arm_link_hash_table *  globals;
1235
1236                       myh = find_thumb_glue (info, name, input_bfd);
1237                       if (myh == NULL)
1238                         return false;
1239
1240                       globals = coff_arm_hash_table (info);
1241                       
1242                       BFD_ASSERT (globals != NULL);
1243                       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1244                       
1245                       my_offset = myh->root.u.def.value;
1246                       
1247                       s = bfd_get_section_by_name (globals->bfd_of_glue_owner, 
1248                                                    THUMB2ARM_GLUE_SECTION_NAME);
1249                       
1250                       BFD_ASSERT (s != NULL);
1251                       BFD_ASSERT (s->contents != NULL);
1252                       BFD_ASSERT (s->output_section != NULL);
1253                       
1254                       if ((my_offset & 0x01) == 0x01)
1255                         {
1256                           if (h_sec->owner != NULL
1257                               && INTERWORK_SET (h_sec->owner)
1258                               && ! INTERWORK_FLAG (h_sec->owner)
1259                               && ! globals->support_old_code)
1260                             {
1261                               _bfd_error_handler
1262                                 /* xgettext:c-format */
1263                                 (_("%s(%s): warning: interworking not enabled."),
1264                                  bfd_get_filename (h_sec->owner), name);
1265                               _bfd_error_handler
1266                                 /* xgettext:c-format */
1267                                 (_("  first occurrence: %s: thumb call to arm"),
1268                                  bfd_get_filename (input_bfd));
1269                               _bfd_error_handler
1270                                 (_("  consider relinking with --support-old-code enabled"));
1271                             }
1272                           
1273                           -- my_offset;
1274                           myh->root.u.def.value = my_offset;
1275
1276                           if (globals->support_old_code)
1277                             {
1278                               bfd_put_16 (output_bfd, t2a1_push_insn,
1279                                           s->contents + my_offset);
1280                               
1281                               bfd_put_16 (output_bfd, t2a2_ldr_insn,
1282                                           s->contents + my_offset + 2);
1283
1284                               bfd_put_16 (output_bfd, t2a3_mov_insn,
1285                                           s->contents + my_offset + 4);
1286
1287                               bfd_put_16 (output_bfd, t2a4_bx_insn,
1288                                           s->contents + my_offset + 6);
1289                               
1290                               bfd_put_32 (output_bfd, t2a5_pop_insn,
1291                                           s->contents + my_offset + 8);
1292                               
1293                               bfd_put_32 (output_bfd, t2a6_bx_insn,
1294                                           s->contents + my_offset + 12);
1295                               
1296                               /* Store the address of the function in the last word of the stub.  */
1297                               bfd_put_32 (output_bfd, h_val,
1298                                           s->contents + my_offset + 16);
1299                             }
1300                           else
1301                             {
1302                               bfd_put_16 (output_bfd, t2a1_bx_pc_insn,
1303                                           s->contents + my_offset);
1304                       
1305                               bfd_put_16 (output_bfd, t2a2_noop_insn,
1306                                           s->contents + my_offset + 2);
1307                       
1308                               ret_offset =
1309                                 ((bfd_signed_vma) h_val)        /* Address of destination of the stub */
1310                                 - ((bfd_signed_vma)
1311                                    (s->output_offset            /* Offset from the start of the current section to the start of the stubs.  */
1312                                     + my_offset                 /* Offset of the start of this stub from the start of the stubs.  */
1313                                     + s->output_section->vma)   /* Address of the start of the current section.  */
1314                                    + 4                          /* The branch instruction is 4 bytes into the stub.  */
1315                                    + 8);                        /* ARM branches work from the pc of the instruction + 8.  */
1316                               
1317                               bfd_put_32 (output_bfd,
1318                                           t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
1319                                           s->contents + my_offset + 4);
1320                             }
1321                         }
1322
1323                       BFD_ASSERT (my_offset <= globals->thumb_glue_size);
1324
1325                       /* Now go back and fix up the original BL insn to point
1326                          to here.  */
1327                       ret_offset =
1328                         s->output_offset
1329                         + my_offset
1330                         - (input_section->output_offset
1331                            + rel->r_vaddr)
1332                         -4;
1333                       
1334                       tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
1335                                         - input_section->vma);
1336
1337                       bfd_put_32 (output_bfd,
1338                                   insert_thumb_branch (tmp, ret_offset),
1339                                   contents + rel->r_vaddr
1340                                   - input_section->vma);
1341                       
1342                       done = 1;
1343                     }
1344                 }
1345             }
1346           
1347           /* If the relocation type and destination symbol does not
1348              fall into one of the above categories, then we can just
1349              perform a direct link. */
1350
1351           if (done)
1352             rstat = bfd_reloc_ok;
1353           else 
1354 #endif /* THUMBEXTENSION */
1355             if (   h->root.type == bfd_link_hash_defined
1356                 || h->root.type == bfd_link_hash_defweak)
1357             {
1358               asection *sec;
1359
1360               sec = h->root.u.def.section;
1361               val = (h->root.u.def.value
1362                      + sec->output_section->vma
1363                      + sec->output_offset);
1364               }
1365
1366           else if (! info->relocateable)
1367             {
1368               if (! ((*info->callbacks->undefined_symbol)
1369                      (info, h->root.root.string, input_bfd, input_section,
1370                       rel->r_vaddr - input_section->vma)))
1371                 return false;
1372             }
1373         }
1374
1375       if (info->base_file)
1376         {
1377           /* Emit a reloc if the backend thinks it needs it. */
1378           if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
1379             {
1380               /* relocation to a symbol in a section which
1381                  isn't absolute - we output the address here 
1382                  to a file */
1383               bfd_vma addr = rel->r_vaddr 
1384                 - input_section->vma 
1385                 + input_section->output_offset 
1386                   + input_section->output_section->vma;
1387               if (coff_data(output_bfd)->pe)
1388                 addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
1389               /* FIXME: Shouldn't 4 be sizeof (addr)?  */
1390               fwrite (&addr, 1,4, (FILE *) info->base_file);
1391             }
1392         }
1393   
1394 #if 1 /* THUMBEXTENSION */
1395       if (done)
1396         rstat = bfd_reloc_ok;
1397       /* Only perform this fix during the final link, not a relocatable link.  [email protected]  */
1398       else if (! info->relocateable
1399                && howto->type == ARM_THUMB23)
1400         {
1401           /* This is pretty much a copy of what the default
1402              _bfd_final_link_relocate and _bfd_relocate_contents
1403              routines do to perform a relocation, with special
1404              processing for the split addressing of the Thumb BL
1405              instruction.  Again, it would probably be simpler adding a
1406              ThumbBRANCH23 specific macro expansion into the default
1407              code.  */
1408           
1409           bfd_vma address = rel->r_vaddr - input_section->vma;
1410           
1411           if (address > input_section->_raw_size)
1412             rstat = bfd_reloc_outofrange;
1413           else
1414             {
1415               bfd_vma         relocation       = val + addend;
1416               int             size             = bfd_get_reloc_size (howto);
1417               boolean         overflow         = false;
1418               bfd_byte *      location         = contents + address;
1419               bfd_vma         x                = bfd_get_32 (input_bfd, location);
1420               bfd_vma         src_mask         = 0x007FFFFE;
1421               bfd_signed_vma  reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
1422               bfd_signed_vma  reloc_signed_min = ~reloc_signed_max;
1423               bfd_vma         check;
1424               bfd_signed_vma  signed_check;
1425               bfd_vma         add;
1426               bfd_signed_vma  signed_add;
1427
1428               BFD_ASSERT (size == 4);
1429               
1430               /* howto->pc_relative should be TRUE for type 14 BRANCH23 */
1431               relocation -= (input_section->output_section->vma
1432                              + input_section->output_offset);
1433               
1434               /* howto->pcrel_offset should be TRUE for type 14 BRANCH23 */
1435               relocation -= address;
1436               
1437               /* No need to negate the relocation with BRANCH23. */
1438               /* howto->complain_on_overflow == complain_overflow_signed for BRANCH23.  */
1439               /* howto->rightshift == 1 */
1440               /* Drop unwanted bits from the value we are relocating to.  */
1441               
1442               check = relocation >> howto->rightshift;
1443                 
1444               /* If this is a signed value, the rightshift just dropped
1445                  leading 1 bits (assuming twos complement).  */
1446               if ((bfd_signed_vma) relocation >= 0)
1447                 signed_check = check;
1448               else
1449                 signed_check = (check
1450                                 | ((bfd_vma) - 1
1451                                    & ~((bfd_vma) - 1 >> howto->rightshift)));
1452               
1453               /* Get the value from the object file.  */
1454               if (bfd_big_endian (input_bfd))
1455                 {
1456                   add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
1457                 }
1458               else
1459                 {
1460                   add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
1461                 }
1462
1463               /* Get the value from the object file with an appropriate sign.
1464                  The expression involving howto->src_mask isolates the upper
1465                  bit of src_mask.  If that bit is set in the value we are
1466                  adding, it is negative, and we subtract out that number times
1467                  two.  If src_mask includes the highest possible bit, then we
1468                  can not get the upper bit, but that does not matter since
1469                  signed_add needs no adjustment to become negative in that
1470                  case.  */
1471               
1472               signed_add = add;
1473               
1474               if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)
1475                 signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;
1476               
1477               /* Add the value from the object file, shifted so that it is a
1478                  straight number.  */
1479               /* howto->bitpos == 0 */
1480               
1481               signed_check += signed_add;
1482               relocation += signed_add;
1483
1484               BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);
1485
1486               /* Assumes two's complement.  */
1487               if (   signed_check > reloc_signed_max
1488                   || signed_check < reloc_signed_min)
1489                 overflow = true;
1490               
1491               /* Put RELOCATION into the correct bits:  */
1492               
1493               if (bfd_big_endian (input_bfd))
1494                 {
1495                   relocation = (((relocation & 0xffe) >> 1)  | ((relocation << 4) & 0x07ff0000));
1496                 }
1497               else
1498                 {
1499                   relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
1500                 }
1501               
1502               /* Add RELOCATION to the correct bits of X:  */
1503               x = ((x & ~howto->dst_mask) | relocation);
1504
1505               /* Put the relocated value back in the object file:  */
1506               bfd_put_32 (input_bfd, x, location);
1507
1508               rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;
1509             }
1510         }
1511       else
1512 #endif /* THUMBEXTENSION */
1513         rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
1514                                           contents,
1515                                           rel->r_vaddr - input_section->vma,
1516                                           val, addend);
1517 #if 1 /* THUMBEXTENSION */
1518       /* FIXME: 
1519          Is this the best way to fix up thumb addresses? [email protected]
1520          Probably not, but it works, and if it works it don't need fixing!  [email protected] */
1521       /* Only perform this fix during the final link, not a relocatable link.  [email protected]  */
1522       if (! info->relocateable
1523           && rel->r_type == ARM_32)
1524         {
1525           /* Determine if we need to set the bottom bit of a relocated address
1526              because the address is the address of a Thumb code symbol.  */
1527              
1528           int patchit = false;
1529           
1530           if (h != NULL
1531               && (   h->class == C_THUMBSTATFUNC
1532                   || h->class == C_THUMBEXTFUNC))
1533             {
1534               patchit = true;
1535             }
1536           else if (sym != NULL
1537                    && sym->n_scnum > N_UNDEF)
1538             {
1539               /* No hash entry - use the symbol instead.  */
1540
1541               if (   sym->n_sclass == C_THUMBSTATFUNC
1542                   || sym->n_sclass == C_THUMBEXTFUNC)
1543                 patchit = true;
1544             }
1545
1546           if (patchit)
1547             {
1548               bfd_byte * location = contents + rel->r_vaddr - input_section->vma;
1549               bfd_vma    x        = bfd_get_32 (input_bfd, location);
1550
1551               bfd_put_32 (input_bfd, x | 1, location);
1552             }
1553         }
1554 #endif /* THUMBEXTENSION */      
1555       
1556       switch (rstat)
1557         {
1558         default:
1559           abort ();
1560         case bfd_reloc_ok:
1561           break;
1562         case bfd_reloc_outofrange:
1563           (*_bfd_error_handler)
1564             (_("%s: bad reloc address 0x%lx in section `%s'"),
1565              bfd_get_filename (input_bfd),
1566              (unsigned long) rel->r_vaddr,
1567              bfd_get_section_name (input_bfd, input_section));
1568           return false;
1569         case bfd_reloc_overflow:
1570           {
1571             const char *name;
1572             char buf[SYMNMLEN + 1];
1573
1574             if (symndx == -1)
1575               name = "*ABS*";
1576             else if (h != NULL)
1577               name = h->root.root.string;
1578             else
1579               {
1580                 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
1581                 if (name == NULL)
1582                   return false;
1583               }
1584
1585             if (! ((*info->callbacks->reloc_overflow)
1586                    (info, name, howto->name, (bfd_vma) 0, input_bfd,
1587                     input_section, rel->r_vaddr - input_section->vma)))
1588               return false;
1589           }
1590         }
1591     }
1592
1593   return true;
1594 }
1595
1596 #ifndef COFF_WITH_PE
1597 boolean
1598 bfd_arm_allocate_interworking_sections (info) 
1599      struct bfd_link_info * info;
1600 {
1601   asection *                        s;
1602   bfd_byte *                        foo;
1603   struct coff_arm_link_hash_table * globals;
1604 #if 0
1605   static char                       test_char = '1';
1606 #endif
1607
1608   globals = coff_arm_hash_table (info);
1609   
1610   BFD_ASSERT (globals != NULL);
1611
1612   if (globals->arm_glue_size != 0)
1613     {
1614       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1615       
1616       s = bfd_get_section_by_name
1617         (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
1618
1619       BFD_ASSERT (s != NULL);
1620       
1621       foo = (bfd_byte *) bfd_alloc
1622         (globals->bfd_of_glue_owner, globals->arm_glue_size);
1623 #if 0
1624       memset (foo, test_char, globals->arm_glue_size);
1625 #endif
1626       
1627       s->_raw_size = s->_cooked_size = globals->arm_glue_size;
1628       s->contents = foo;
1629     }
1630
1631   if (globals->thumb_glue_size != 0)
1632     {
1633       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1634       
1635       s = bfd_get_section_by_name
1636         (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
1637
1638       BFD_ASSERT (s != NULL);
1639       
1640       foo = (bfd_byte *) bfd_alloc
1641         (globals->bfd_of_glue_owner, globals->thumb_glue_size);
1642 #if 0
1643       memset (foo, test_char, globals->thumb_glue_size);
1644 #endif
1645       
1646       s->_raw_size = s->_cooked_size = globals->thumb_glue_size;
1647       s->contents = foo;
1648     }
1649
1650   return true;
1651 }
1652
1653 static void
1654 record_arm_to_thumb_glue (info, h)
1655      struct bfd_link_info *        info;
1656      struct coff_link_hash_entry * h;
1657 {
1658   const char *                      name = h->root.root.string;
1659   register asection *               s;
1660   char *                            tmp_name;
1661   struct coff_link_hash_entry *     myh;
1662   struct coff_arm_link_hash_table * globals;
1663
1664   globals = coff_arm_hash_table (info);
1665
1666   BFD_ASSERT (globals != NULL);
1667   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1668
1669   s = bfd_get_section_by_name
1670     (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
1671
1672   BFD_ASSERT (s != NULL);
1673
1674   tmp_name = ((char *)
1675               bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));
1676
1677   BFD_ASSERT (tmp_name);
1678
1679   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
1680   
1681   myh = coff_link_hash_lookup
1682     (coff_hash_table (info), tmp_name, false, false, true);
1683   
1684   if (myh != NULL)
1685     {
1686       free (tmp_name);
1687       return; /* we've already seen this guy */
1688     }
1689
1690   /* The only trick here is using globals->arm_glue_size as the value. Even
1691      though the section isn't allocated yet, this is where we will be putting
1692      it.  */
1693
1694   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1695                                 BSF_GLOBAL, 
1696                                 s, globals->arm_glue_size + 1,
1697                                 NULL, true, false, 
1698                                 (struct bfd_link_hash_entry **) & myh);
1699   
1700   free (tmp_name);
1701   
1702   globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
1703
1704   return;
1705 }
1706
1707 static void
1708 record_thumb_to_arm_glue (info, h)
1709      struct bfd_link_info *        info;
1710      struct coff_link_hash_entry * h;
1711 {
1712   const char *                       name = h->root.root.string;
1713   register asection *                s;
1714   char *                             tmp_name;
1715   struct coff_link_hash_entry *      myh;
1716   struct coff_arm_link_hash_table *  globals;
1717
1718   
1719   globals = coff_arm_hash_table (info);
1720   
1721   BFD_ASSERT (globals != NULL);
1722   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1723
1724   s = bfd_get_section_by_name
1725     (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
1726
1727   BFD_ASSERT (s != NULL);
1728
1729   tmp_name = (char *) bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
1730
1731   BFD_ASSERT (tmp_name);
1732
1733   sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
1734
1735   myh = coff_link_hash_lookup
1736     (coff_hash_table (info), tmp_name, false, false, true);
1737   
1738   if (myh != NULL)
1739     {
1740       free (tmp_name);
1741       return; /* we've already seen this guy */
1742     }
1743
1744   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1745                                 BSF_GLOBAL, s, globals->thumb_glue_size + 1,
1746                                 NULL, true, false, 
1747                                 (struct bfd_link_hash_entry **) & myh);
1748   
1749   /* If we mark it 'thumb', the disassembler will do a better job.  */
1750   myh->class = C_THUMBEXTFUNC;
1751
1752   free (tmp_name);
1753
1754   /* Allocate another symbol to mark where we switch to arm mode.  */
1755       
1756 #define CHANGE_TO_ARM "__%s_change_to_arm"
1757 #define BACK_FROM_ARM "__%s_back_from_arm"
1758   
1759   tmp_name = (char *) bfd_malloc (strlen (name) + strlen (CHANGE_TO_ARM) + 1);
1760   
1761   BFD_ASSERT (tmp_name);
1762   
1763   sprintf (tmp_name, globals->support_old_code ? BACK_FROM_ARM : CHANGE_TO_ARM, name);
1764
1765   myh = NULL;
1766   
1767   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1768                                 BSF_LOCAL, s, globals->thumb_glue_size
1769                                 + (globals->support_old_code ? 8 : 4),
1770                                 NULL, true, false, 
1771                                 (struct bfd_link_hash_entry **) & myh);
1772
1773   free (tmp_name);  
1774   
1775   globals->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
1776
1777   return;
1778 }
1779
1780 /* Select a BFD to be used to hold the sections used by the glue code.
1781    This function is called from the linker scripts in ld/emultempl/
1782    {armcoff/pe}.em  */
1783 boolean
1784 bfd_arm_get_bfd_for_interworking (abfd, info)
1785      bfd *                  abfd;
1786      struct bfd_link_info * info;
1787 {
1788   struct coff_arm_link_hash_table * globals;
1789   flagword                          flags;
1790   asection *                        sec;
1791     
1792   /* If we are only performing a partial link do not bother
1793      getting a bfd to hold the glue.  */
1794   if (info->relocateable)
1795     return true;
1796   
1797   globals = coff_arm_hash_table (info);
1798   
1799   BFD_ASSERT (globals != NULL);
1800
1801   if (globals->bfd_of_glue_owner != NULL)
1802     return true;
1803   
1804   sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
1805   
1806   if (sec == NULL) 
1807     {
1808       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
1809       
1810       sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
1811       
1812       if (sec == NULL
1813           || ! bfd_set_section_flags (abfd, sec, flags)
1814           || ! bfd_set_section_alignment (abfd, sec, 2))
1815         return false;
1816     }
1817
1818   sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
1819
1820   if (sec == NULL) 
1821     {
1822       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
1823       
1824       sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
1825       
1826       if (sec == NULL
1827           || ! bfd_set_section_flags (abfd, sec, flags)
1828           || ! bfd_set_section_alignment (abfd, sec, 2))
1829         return false;
1830     }
1831   
1832   /* Save the bfd for later use.  */
1833   globals->bfd_of_glue_owner = abfd;
1834   
1835   return true;
1836 }
1837
1838 boolean
1839 bfd_arm_process_before_allocation (abfd, info, support_old_code)
1840      bfd *                   abfd;
1841      struct bfd_link_info *  info;
1842      int                     support_old_code;
1843 {
1844   asection * sec;
1845   struct coff_arm_link_hash_table * globals;
1846
1847   /* If we are only performing a partial link do not bother
1848      to construct any glue.  */
1849   if (info->relocateable)
1850     return true;
1851   
1852   /* Here we have a bfd that is to be included on the link.  We have a hook
1853      to do reloc rummaging, before section sizes are nailed down.  */
1854
1855   _bfd_coff_get_external_symbols (abfd);
1856
1857   globals = coff_arm_hash_table (info);
1858   
1859   BFD_ASSERT (globals != NULL);
1860   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1861
1862   globals->support_old_code = support_old_code;
1863   
1864   /* Rummage around all the relocs and map the glue vectors.  */
1865   sec = abfd->sections;
1866
1867   if (sec == NULL)
1868     return true;
1869
1870   for (; sec != NULL; sec = sec->next)
1871     {
1872       struct internal_reloc * i;
1873       struct internal_reloc * rel;
1874
1875       if (sec->reloc_count == 0) 
1876         continue;
1877
1878       /* Load the relocs.  */
1879       /* FIXME: there may be a storage leak here. */
1880       
1881       i = _bfd_coff_read_internal_relocs (abfd, sec, 1, 0, 0, 0);
1882     
1883       BFD_ASSERT (i != 0);
1884
1885       for (rel = i; rel < i + sec->reloc_count; ++rel) 
1886         {
1887           unsigned short                 r_type  = rel->r_type;
1888           long                           symndx;
1889           struct coff_link_hash_entry *  h;
1890
1891           symndx = rel->r_symndx;
1892
1893           /* If the relocation is not against a symbol it cannot concern us. */
1894           if (symndx == -1)
1895             continue;
1896
1897           h = obj_coff_sym_hashes (abfd)[symndx];
1898
1899           /* If the relocation is against a static symbol it must be within
1900              the current section and so cannot be a cross ARM/Thumb relocation.  */
1901           if (h == NULL)
1902             continue;
1903
1904           switch (r_type)
1905             {
1906             case ARM_26:
1907               /* This one is a call from arm code.  We need to look up
1908                  the target of the call. If it is a thumb target, we
1909                  insert glue.  */
1910               
1911               if (h->class == C_THUMBEXTFUNC)
1912                 record_arm_to_thumb_glue (info, h);
1913               break;
1914               
1915             case ARM_THUMB23:
1916               /* This one is a call from thumb code.  We used to look
1917                  for ARM_THUMB9 and ARM_THUMB12 as well.  We need to look
1918                  up the target of the call. If it is an arm target, we
1919                  insert glue.  If the symbol does not exist it will be
1920                  given a class of C_EXT and so we will generate a stub
1921                  for it.  This is not really a problem, since the link
1922                  is doomed anyway.  */
1923
1924               switch (h->class)
1925                 {
1926                 case C_EXT:
1927                 case C_STAT:
1928                 case C_LABEL:
1929                   record_thumb_to_arm_glue (info, h);
1930                   break;
1931                 default:
1932                   ;
1933                 }
1934               break;
1935               
1936             default:
1937               break;
1938             }
1939         }
1940     }
1941
1942   return true;
1943 }
1944
1945 #endif /* ! COFF_WITH_PE */
1946
1947 #define coff_bfd_reloc_type_lookup              coff_arm_reloc_type_lookup
1948 #define coff_relocate_section                   coff_arm_relocate_section
1949 #define coff_bfd_is_local_label_name            coff_arm_is_local_label_name
1950 #define coff_adjust_symndx                      coff_arm_adjust_symndx
1951 #define coff_link_output_has_begun              coff_arm_link_output_has_begun
1952 #define coff_final_link_postscript              coff_arm_final_link_postscript
1953 #define coff_bfd_merge_private_bfd_data         coff_arm_merge_private_bfd_data
1954 #define coff_bfd_print_private_bfd_data         coff_arm_print_private_bfd_data
1955 #define coff_bfd_set_private_flags              _bfd_coff_arm_set_private_flags
1956 #define coff_bfd_copy_private_bfd_data          coff_arm_copy_private_bfd_data
1957 #define coff_bfd_link_hash_table_create         coff_arm_link_hash_table_create
1958
1959
1960 /* When doing a relocateable link, we want to convert ARM26 relocs
1961    into ARM26D relocs.  */
1962
1963 static boolean
1964 coff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
1965      bfd *obfd;
1966      struct bfd_link_info *info;
1967      bfd *ibfd;
1968      asection *sec;
1969      struct internal_reloc *irel;
1970      boolean *adjustedp;
1971 {
1972   if (irel->r_type == 3)
1973     {
1974       struct coff_link_hash_entry *h;
1975
1976       h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
1977       if (h != NULL
1978           && (h->root.type == bfd_link_hash_defined
1979               || h->root.type == bfd_link_hash_defweak)
1980           && h->root.u.def.section->output_section == sec->output_section)
1981         irel->r_type = 7;
1982     }
1983   *adjustedp = false;
1984   return true;
1985 }
1986
1987 /* Called when merging the private data areas of two BFDs.
1988    This is important as it allows us to detect if we are
1989    attempting to merge binaries compiled for different ARM
1990    targets, eg different CPUs or differents APCS's.     */
1991
1992 static boolean
1993 coff_arm_merge_private_bfd_data (ibfd, obfd)
1994      bfd *   ibfd;
1995      bfd *   obfd;
1996 {
1997   BFD_ASSERT (ibfd != NULL && obfd != NULL);
1998
1999   if (ibfd == obfd)
2000     return true;
2001
2002   /* If the two formats are different we cannot merge anything.
2003      This is not an error, since it is permissable to change the
2004      input and output formats.  */
2005   if (   ibfd->xvec->flavour != bfd_target_coff_flavour
2006       || obfd->xvec->flavour != bfd_target_coff_flavour)
2007     return true;
2008
2009   /* Verify that the APCS is the same for the two BFDs */
2010   if (APCS_SET (ibfd))
2011     {
2012       if (APCS_SET (obfd))
2013         {
2014           /* If the src and dest have different APCS flag bits set, fail.  */
2015           if (APCS_26_FLAG (obfd) != APCS_26_FLAG (ibfd))
2016             {
2017               _bfd_error_handler
2018                 /* xgettext: c-format */
2019                 (_("%s: ERROR: compiled for APCS-%d whereas target %s uses APCS-%d"),
2020                  bfd_get_filename (ibfd), APCS_26_FLAG (ibfd) ? 26 : 32,
2021                  bfd_get_filename (obfd), APCS_26_FLAG (obfd) ? 26 : 32
2022                  );
2023
2024               bfd_set_error (bfd_error_wrong_format);
2025               return false;
2026             }
2027           
2028           if (APCS_FLOAT_FLAG (obfd) != APCS_FLOAT_FLAG (ibfd))
2029             {
2030               const char *msg;
2031
2032               if (APCS_FLOAT_FLAG (ibfd))
2033                 /* xgettext: c-format */
2034                 msg = _("%s: ERROR: passes floats in float registers whereas target %s uses integer registers");
2035               else
2036                 /* xgettext: c-format */
2037                 msg = _("%s: ERROR: passes floats in integer registers whereas target %s uses float registers");
2038               
2039               _bfd_error_handler (msg, bfd_get_filename (ibfd),
2040                                   bfd_get_filename (obfd));
2041
2042               bfd_set_error (bfd_error_wrong_format);
2043               return false;
2044             }
2045           
2046           if (PIC_FLAG (obfd) != PIC_FLAG (ibfd))
2047             {
2048               const char * msg;
2049
2050               if (PIC_FLAG (ibfd))
2051                 /* xgettext: c-format */
2052                 msg = _("%s: ERROR: compiled as position independent code, whereas target %s is absolute position");
2053               else
2054                 /* xgettext: c-format */
2055                 msg = _("%s: ERROR: compiled as absolute position code, whereas target %s is position independent");
2056               _bfd_error_handler (msg, bfd_get_filename (ibfd),
2057                                   bfd_get_filename (obfd));
2058
2059               bfd_set_error (bfd_error_wrong_format);
2060               return false;
2061             }
2062         }
2063       else
2064         {
2065           SET_APCS_FLAGS (obfd, APCS_26_FLAG (ibfd) | APCS_FLOAT_FLAG (ibfd) | PIC_FLAG (ibfd));
2066           
2067           /* Set up the arch and fields as well as these are probably wrong.  */
2068           bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
2069         }
2070     }
2071
2072   /* Check the interworking support.  */
2073   if (INTERWORK_SET (ibfd))
2074     {
2075       if (INTERWORK_SET (obfd))
2076         {
2077           /* If the src and dest differ in their interworking issue a warning.  */
2078           if (INTERWORK_FLAG (obfd) != INTERWORK_FLAG (ibfd))
2079             {
2080               const char * msg;
2081
2082               if (INTERWORK_FLAG (ibfd))
2083                 /* xgettext: c-format */
2084                 msg = _("Warning: input file %s supports interworking, whereas %s does not.");
2085               else
2086                 /* xgettext: c-format */
2087                 msg = _("Warning: input file %s does not support interworking, whereas %s does.");
2088               
2089               _bfd_error_handler (msg, bfd_get_filename (ibfd),
2090                                   bfd_get_filename (obfd));
2091             }
2092         }
2093       else
2094         {
2095           SET_INTERWORK_FLAG (obfd, INTERWORK_FLAG (ibfd));
2096         }
2097     }
2098
2099   return true;
2100 }
2101
2102
2103 /* Display the flags field.  */
2104
2105 static boolean
2106 coff_arm_print_private_bfd_data (abfd, ptr)
2107      bfd *   abfd;
2108      PTR     ptr;
2109 {
2110   FILE * file = (FILE *) ptr;
2111   
2112   BFD_ASSERT (abfd != NULL && ptr != NULL);
2113   
2114   /* xgettext:c-format */
2115   fprintf (file, _("private flags = %x:"), coff_data (abfd)->flags);
2116   
2117   if (APCS_SET (abfd))
2118     {
2119       /* xgettext: APCS is ARM Prodecure Call Standard, it should not be translated.  */
2120       fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32);
2121
2122       if (APCS_FLOAT_FLAG (abfd))
2123         fprintf (file, _(" [floats passed in float registers]"));
2124       else
2125         fprintf (file, _(" [floats passed in integer registers]"));
2126
2127       if (PIC_FLAG (abfd))
2128         fprintf (file, _(" [position independent]"));
2129       else
2130         fprintf (file, _(" [absolute position]"));
2131     }
2132   
2133   if (! INTERWORK_SET (abfd))
2134     fprintf (file, _(" [interworking flag not initialised]"));
2135   else if (INTERWORK_FLAG (abfd))
2136     fprintf (file, _(" [interworking supported]"));
2137   else
2138     fprintf (file, _(" [interworking not supported]"));
2139   
2140   fputc ('\n', file);
2141   
2142   return true;
2143 }
2144
2145
2146 /* Copies the given flags into the coff_tdata.flags field.
2147    Typically these flags come from the f_flags[] field of
2148    the COFF filehdr structure, which contains important,
2149    target specific information.
2150    Note: Although this function is static, it is explicitly
2151    called from both coffcode.h and peicode.h.  */
2152
2153 static boolean
2154 _bfd_coff_arm_set_private_flags (abfd, flags)
2155         bfd *      abfd;
2156         flagword   flags;
2157 {
2158   flagword flag;
2159
2160   BFD_ASSERT (abfd != NULL);
2161
2162   flag = (flags & F_APCS26) ? F_APCS_26 : 0;
2163   
2164   /* Make sure that the APCS field has not been initialised to the opposite
2165      value.  */
2166   if (APCS_SET (abfd)
2167       && (   (APCS_26_FLAG    (abfd) != flag)
2168           || (APCS_FLOAT_FLAG (abfd) != (flags & F_APCS_FLOAT))
2169           || (PIC_FLAG        (abfd) != (flags & F_PIC))
2170           ))
2171     return false;
2172
2173   flag |= (flags & (F_APCS_FLOAT | F_PIC));
2174   
2175   SET_APCS_FLAGS (abfd, flag);
2176
2177   flag = (flags & F_INTERWORK);
2178   
2179   /* If the BFD has already had its interworking flag set, but it
2180      is different from the value that we have been asked to set,
2181      then assume that that merged code will not support interworking
2182      and set the flag accordingly.  */
2183   if (INTERWORK_SET (abfd) && (INTERWORK_FLAG (abfd) != flag))
2184     {
2185       if (flag)
2186         /* xgettext: c-format */
2187         _bfd_error_handler (_("Warning: Not setting interworking flag of %s, since it has already been specified as non-interworking"),
2188                             bfd_get_filename (abfd));
2189       else
2190         /* xgettext: c-format */
2191         _bfd_error_handler (_("Warning: Clearing the interworking flag of %s due to outside request"),
2192                             bfd_get_filename (abfd));
2193       flag = 0;
2194     }
2195
2196   SET_INTERWORK_FLAG (abfd, flag);
2197
2198   return true;
2199 }
2200
2201
2202 /* Copy the important parts of the target specific data
2203    from one instance of a BFD to another.  */
2204
2205 static boolean
2206 coff_arm_copy_private_bfd_data (src, dest)
2207      bfd *  src;
2208      bfd *  dest;
2209 {
2210   BFD_ASSERT (src != NULL && dest != NULL);
2211  
2212   if (src == dest)
2213     return true;
2214
2215   /* If the destination is not in the same format as the source, do not do
2216      the copy.  */
2217   if (src->xvec != dest->xvec)
2218     return true;
2219
2220   /* copy the flags field */
2221   if (APCS_SET (src))
2222     {
2223       if (APCS_SET (dest))
2224         {
2225           /* If the src and dest have different APCS flag bits set, fail.  */
2226           if (APCS_26_FLAG (dest) != APCS_26_FLAG (src))
2227             return false;
2228           
2229           if (APCS_FLOAT_FLAG (dest) != APCS_FLOAT_FLAG (src))
2230             return false;
2231           
2232           if (PIC_FLAG (dest) != PIC_FLAG (src))
2233             return false;
2234         }
2235       else
2236         SET_APCS_FLAGS (dest, APCS_26_FLAG (src) | APCS_FLOAT_FLAG (src)
2237                         | PIC_FLAG (src));
2238     }
2239
2240   if (INTERWORK_SET (src))
2241     {
2242       if (INTERWORK_SET (dest))
2243         {
2244           /* If the src and dest have different interworking flags then turn
2245              off the interworking bit.  */
2246           if (INTERWORK_FLAG (dest) != INTERWORK_FLAG (src))
2247             {
2248               if (INTERWORK_FLAG (dest))
2249                 {
2250                   /* xgettext:c-format */
2251                   _bfd_error_handler (("Warning: Clearing the interworking bit of %s, because the non-interworking code in %s has been copied into it"),
2252                                       bfd_get_filename (dest),
2253                                       bfd_get_filename (src));
2254                 }
2255               
2256               SET_INTERWORK_FLAG (dest, 0);
2257             }
2258         }
2259       else
2260         {
2261           SET_INTERWORK_FLAG (dest, INTERWORK_FLAG (src));
2262         }
2263     }
2264
2265   return true;
2266 }
2267
2268 /* Note:  the definitions here of LOCAL_LABEL_PREFIX and USER_LABEL_PREIFX
2269  *must* match the definitions on gcc/config/arm/semi.h.  */
2270 #define LOCAL_LABEL_PREFIX "."
2271 #define USER_LABEL_PREFIX "_"
2272
2273 static boolean
2274 coff_arm_is_local_label_name (abfd, name)
2275      bfd *        abfd;
2276      const char * name;
2277 {
2278 #ifdef LOCAL_LABEL_PREFIX
2279   /* If there is a prefix for local labels then look for this.
2280      If the prefix exists, but it is empty, then ignore the test. */
2281   
2282   if (LOCAL_LABEL_PREFIX[0] != 0)
2283     {
2284       if (strncmp (name, LOCAL_LABEL_PREFIX, strlen (LOCAL_LABEL_PREFIX)) == 0)
2285         return true;
2286     }
2287 #endif
2288 #ifdef USER_LABEL_PREFIX
2289   if (USER_LABEL_PREFIX[0] != 0)
2290     {
2291       if (strncmp (name, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)) == 0)
2292         return false;
2293     }
2294 #endif
2295   
2296   /* devo/gcc/config/dbxcoff.h defines ASM_OUTPUT_SOURCE_LINE to generate
2297      local line numbers as .LM<number>, so treat these as local.  */
2298   
2299   switch (name[0])
2300     {
2301     case 'L': return true;
2302     case '.': return (name[1] == 'L' && name[2] == 'M') ? true : false;
2303     default:  return false;     /* Cannot make our minds up - default to
2304                                    false so that it will not be stripped
2305                                    by accident.  */ 
2306     }
2307 }
2308
2309 /* This piece of machinery exists only to guarantee that the bfd that holds
2310    the glue section is written last. 
2311
2312    This does depend on bfd_make_section attaching a new section to the
2313    end of the section list for the bfd. 
2314
2315    [email protected]  */
2316
2317 static boolean
2318 coff_arm_link_output_has_begun (sub, info)
2319      bfd * sub;
2320      struct coff_final_link_info * info;
2321 {
2322   return (sub->output_has_begun
2323           || sub == coff_arm_hash_table (info->info)->bfd_of_glue_owner);
2324 }
2325
2326 static boolean
2327 coff_arm_final_link_postscript (abfd, pfinfo)
2328      bfd * abfd;
2329      struct coff_final_link_info * pfinfo;
2330 {
2331   struct coff_arm_link_hash_table * globals;
2332
2333   globals = coff_arm_hash_table (pfinfo->info);
2334   
2335   BFD_ASSERT (globals != NULL);
2336   
2337   if (globals->bfd_of_glue_owner != NULL)
2338     {
2339       if (! _bfd_coff_link_input_bfd (pfinfo, globals->bfd_of_glue_owner))
2340         return false;
2341       
2342       globals->bfd_of_glue_owner->output_has_begun = true;
2343     }
2344   
2345   return true;
2346 }
2347
2348 #if 0
2349 #define coff_SWAP_sym_in  arm_bfd_coff_swap_sym_in
2350
2351 static void coff_swap_sym_in PARAMS ((bfd *, PTR, PTR));
2352
2353 /* Sepcial version of symbol swapper, used to grab a bfd
2354    onto which the glue sections can be attached.  */
2355 static void
2356 arm_bfd_coff_swap_sym_in (abfd, ext1, in1)
2357      bfd * abfd;
2358      PTR   ext1;
2359      PTR   in1;
2360 {
2361   flagword flags;
2362   register asection * s;
2363
2364   /* Do the normal swap in.  */
2365   coff_swap_sym_in (abfd, ext1, in1);
2366
2367   if (bfd_of_glue_owner != NULL) /* we already have a toc, so go home */
2368     return;
2369
2370   /* Save the bfd for later allocation.  */
2371   bfd_of_glue_owner = abfd;
2372
2373   s = bfd_get_section_by_name (bfd_of_glue_owner , 
2374                                ARM2THUMB_GLUE_SECTION_NAME);
2375
2376   if (s == NULL) 
2377     {
2378       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
2379       
2380       s = bfd_make_section (bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
2381
2382       if (s == NULL
2383           || !bfd_set_section_flags (bfd_of_glue_owner, s, flags)
2384           || !bfd_set_section_alignment (bfd_of_glue_owner, s, 2))
2385         {
2386           /* FIXME: set appropriate bfd error */
2387           abort();
2388         }
2389     }
2390
2391   s = bfd_get_section_by_name (bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
2392
2393   if (s == NULL) 
2394     {
2395       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
2396       
2397       s = bfd_make_section (bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
2398       
2399       if (s == NULL
2400           || !bfd_set_section_flags (bfd_of_glue_owner, s, flags)
2401           || !bfd_set_section_alignment (bfd_of_glue_owner, s, 2))
2402         {
2403           /* FIXME: set appropriate bfd error [email protected] */
2404           abort();
2405         }
2406     }
2407   
2408   return;
2409 }
2410 #endif
2411
2412 #include "coffcode.h"
2413
2414 const bfd_target
2415 #ifdef TARGET_LITTLE_SYM
2416 TARGET_LITTLE_SYM =
2417 #else
2418 armcoff_little_vec =
2419 #endif
2420 {
2421 #ifdef TARGET_LITTLE_NAME
2422   TARGET_LITTLE_NAME,
2423 #else
2424   "coff-arm-little",
2425 #endif
2426   bfd_target_coff_flavour,
2427   BFD_ENDIAN_LITTLE,            /* data byte order is little */
2428   BFD_ENDIAN_LITTLE,            /* header byte order is little */
2429
2430   (HAS_RELOC | EXEC_P |         /* object flags */
2431    HAS_LINENO | HAS_DEBUG |
2432    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2433
2434 #ifndef COFF_WITH_PE
2435   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2436 #else
2437   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
2438    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
2439 #endif
2440
2441 #ifdef TARGET_UNDERSCORE
2442   TARGET_UNDERSCORE,            /* leading underscore */
2443 #else
2444   0,                            /* leading underscore */
2445 #endif
2446   '/',                          /* ar_pad_char */
2447   15,                           /* ar_max_namelen */
2448
2449   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2450      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2451      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
2452   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2453      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2454      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
2455
2456 /* Note that we allow an object file to be treated as a core file as well. */
2457     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2458        bfd_generic_archive_p, coff_object_p},
2459     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
2460        bfd_false},
2461     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
2462        _bfd_write_archive_contents, bfd_false},
2463
2464      BFD_JUMP_TABLE_GENERIC (coff),
2465      BFD_JUMP_TABLE_COPY (coff),
2466      BFD_JUMP_TABLE_CORE (_bfd_nocore),
2467      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
2468      BFD_JUMP_TABLE_SYMBOLS (coff),
2469      BFD_JUMP_TABLE_RELOCS (coff),
2470      BFD_JUMP_TABLE_WRITE (coff),
2471      BFD_JUMP_TABLE_LINK (coff),
2472      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2473
2474   (PTR) & bfd_coff_std_swap_table,
2475 };
2476
2477 const bfd_target
2478 #ifdef TARGET_BIG_SYM
2479 TARGET_BIG_SYM =
2480 #else
2481 armcoff_big_vec =
2482 #endif
2483 {
2484 #ifdef TARGET_BIG_NAME
2485   TARGET_BIG_NAME,
2486 #else
2487   "coff-arm-big",
2488 #endif
2489   bfd_target_coff_flavour,
2490   BFD_ENDIAN_BIG,               /* data byte order is big */
2491   BFD_ENDIAN_BIG,               /* header byte order is big */
2492
2493   (HAS_RELOC | EXEC_P |         /* object flags */
2494    HAS_LINENO | HAS_DEBUG |
2495    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2496
2497 #ifndef COFF_WITH_PE
2498   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2499 #else
2500   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
2501    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
2502 #endif
2503
2504 #ifdef TARGET_UNDERSCORE
2505   TARGET_UNDERSCORE,            /* leading underscore */
2506 #else
2507   0,                            /* leading underscore */
2508 #endif
2509   '/',                          /* ar_pad_char */
2510   15,                           /* ar_max_namelen */
2511
2512   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2513      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2514      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
2515   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2516      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2517      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
2518
2519 /* Note that we allow an object file to be treated as a core file as well. */
2520     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2521        bfd_generic_archive_p, coff_object_p},
2522     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
2523        bfd_false},
2524     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
2525        _bfd_write_archive_contents, bfd_false},
2526
2527      BFD_JUMP_TABLE_GENERIC (coff),
2528      BFD_JUMP_TABLE_COPY (coff),
2529      BFD_JUMP_TABLE_CORE (_bfd_nocore),
2530      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
2531      BFD_JUMP_TABLE_SYMBOLS (coff),
2532      BFD_JUMP_TABLE_RELOCS (coff),
2533      BFD_JUMP_TABLE_WRITE (coff),
2534      BFD_JUMP_TABLE_LINK (coff),
2535      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2536
2537   (PTR) & bfd_coff_std_swap_table,
2538 };
This page took 0.205444 seconds and 4 git commands to generate.