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