* bfd-in.h (bfd_arm_allocate_interworking_sections): Static
[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 || rel->r_type == ARM_RVA32))
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 #ifdef COFF_IMAGE_WITH_PE
1614 static
1615 #endif
1616 boolean
1617 bfd_arm_allocate_interworking_sections (info) 
1618      struct bfd_link_info * info;
1619 {
1620   asection *                        s;
1621   bfd_byte *                        foo;
1622   struct coff_arm_link_hash_table * globals;
1623 #if 0
1624   static char                       test_char = '1';
1625 #endif
1626
1627   globals = coff_arm_hash_table (info);
1628   
1629   BFD_ASSERT (globals != NULL);
1630
1631   if (globals->arm_glue_size != 0)
1632     {
1633       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1634       
1635       s = bfd_get_section_by_name
1636         (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
1637
1638       BFD_ASSERT (s != NULL);
1639       
1640       foo = (bfd_byte *) bfd_alloc
1641         (globals->bfd_of_glue_owner, globals->arm_glue_size);
1642 #if 0
1643       memset (foo, test_char, globals->arm_glue_size);
1644 #endif
1645       
1646       s->_raw_size = s->_cooked_size = globals->arm_glue_size;
1647       s->contents = foo;
1648     }
1649
1650   if (globals->thumb_glue_size != 0)
1651     {
1652       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1653       
1654       s = bfd_get_section_by_name
1655         (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
1656
1657       BFD_ASSERT (s != NULL);
1658       
1659       foo = (bfd_byte *) bfd_alloc
1660         (globals->bfd_of_glue_owner, globals->thumb_glue_size);
1661 #if 0
1662       memset (foo, test_char, globals->thumb_glue_size);
1663 #endif
1664       
1665       s->_raw_size = s->_cooked_size = globals->thumb_glue_size;
1666       s->contents = foo;
1667     }
1668
1669   return true;
1670 }
1671
1672 static void
1673 record_arm_to_thumb_glue (info, h)
1674      struct bfd_link_info *        info;
1675      struct coff_link_hash_entry * h;
1676 {
1677   const char *                      name = h->root.root.string;
1678   register asection *               s;
1679   char *                            tmp_name;
1680   struct coff_link_hash_entry *     myh;
1681   struct coff_arm_link_hash_table * globals;
1682
1683   globals = coff_arm_hash_table (info);
1684
1685   BFD_ASSERT (globals != NULL);
1686   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1687
1688   s = bfd_get_section_by_name
1689     (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
1690
1691   BFD_ASSERT (s != NULL);
1692
1693   tmp_name = ((char *)
1694               bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));
1695
1696   BFD_ASSERT (tmp_name);
1697
1698   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
1699   
1700   myh = coff_link_hash_lookup
1701     (coff_hash_table (info), tmp_name, false, false, true);
1702   
1703   if (myh != NULL)
1704     {
1705       free (tmp_name);
1706       return; /* we've already seen this guy */
1707     }
1708
1709   /* The only trick here is using globals->arm_glue_size as the value. Even
1710      though the section isn't allocated yet, this is where we will be putting
1711      it.  */
1712
1713   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1714                                 BSF_GLOBAL, 
1715                                 s, globals->arm_glue_size + 1,
1716                                 NULL, true, false, 
1717                                 (struct bfd_link_hash_entry **) & myh);
1718   
1719   free (tmp_name);
1720   
1721   globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
1722
1723   return;
1724 }
1725
1726 static void
1727 record_thumb_to_arm_glue (info, h)
1728      struct bfd_link_info *        info;
1729      struct coff_link_hash_entry * h;
1730 {
1731   const char *                       name = h->root.root.string;
1732   register asection *                s;
1733   char *                             tmp_name;
1734   struct coff_link_hash_entry *      myh;
1735   struct coff_arm_link_hash_table *  globals;
1736
1737   
1738   globals = coff_arm_hash_table (info);
1739   
1740   BFD_ASSERT (globals != NULL);
1741   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1742
1743   s = bfd_get_section_by_name
1744     (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
1745
1746   BFD_ASSERT (s != NULL);
1747
1748   tmp_name = (char *) bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
1749
1750   BFD_ASSERT (tmp_name);
1751
1752   sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
1753
1754   myh = coff_link_hash_lookup
1755     (coff_hash_table (info), tmp_name, false, false, true);
1756   
1757   if (myh != NULL)
1758     {
1759       free (tmp_name);
1760       return; /* we've already seen this guy */
1761     }
1762
1763   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1764                                 BSF_GLOBAL, s, globals->thumb_glue_size + 1,
1765                                 NULL, true, false, 
1766                                 (struct bfd_link_hash_entry **) & myh);
1767   
1768   /* If we mark it 'thumb', the disassembler will do a better job.  */
1769   myh->class = C_THUMBEXTFUNC;
1770
1771   free (tmp_name);
1772
1773   /* Allocate another symbol to mark where we switch to arm mode.  */
1774       
1775 #define CHANGE_TO_ARM "__%s_change_to_arm"
1776 #define BACK_FROM_ARM "__%s_back_from_arm"
1777   
1778   tmp_name = (char *) bfd_malloc (strlen (name) + strlen (CHANGE_TO_ARM) + 1);
1779   
1780   BFD_ASSERT (tmp_name);
1781   
1782   sprintf (tmp_name, globals->support_old_code ? BACK_FROM_ARM : CHANGE_TO_ARM, name);
1783
1784   myh = NULL;
1785   
1786   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1787                                 BSF_LOCAL, s, globals->thumb_glue_size
1788                                 + (globals->support_old_code ? 8 : 4),
1789                                 NULL, true, false, 
1790                                 (struct bfd_link_hash_entry **) & myh);
1791
1792   free (tmp_name);  
1793   
1794   globals->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
1795
1796   return;
1797 }
1798
1799 /* Select a BFD to be used to hold the sections used by the glue code.
1800    This function is called from the linker scripts in ld/emultempl/
1801    {armcoff/pe}.em  */
1802 #ifdef COFF_IMAGE_WITH_PE
1803 static
1804 #endif
1805 boolean
1806 bfd_arm_get_bfd_for_interworking (abfd, info)
1807      bfd *                  abfd;
1808      struct bfd_link_info * info;
1809 {
1810   struct coff_arm_link_hash_table * globals;
1811   flagword                          flags;
1812   asection *                        sec;
1813     
1814   /* If we are only performing a partial link do not bother
1815      getting a bfd to hold the glue.  */
1816   if (info->relocateable)
1817     return true;
1818   
1819   globals = coff_arm_hash_table (info);
1820   
1821   BFD_ASSERT (globals != NULL);
1822
1823   if (globals->bfd_of_glue_owner != NULL)
1824     return true;
1825   
1826   sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
1827   
1828   if (sec == NULL) 
1829     {
1830       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
1831       
1832       sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
1833       
1834       if (sec == NULL
1835           || ! bfd_set_section_flags (abfd, sec, flags)
1836           || ! bfd_set_section_alignment (abfd, sec, 2))
1837         return false;
1838     }
1839
1840   sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
1841
1842   if (sec == NULL) 
1843     {
1844       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
1845       
1846       sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
1847       
1848       if (sec == NULL
1849           || ! bfd_set_section_flags (abfd, sec, flags)
1850           || ! bfd_set_section_alignment (abfd, sec, 2))
1851         return false;
1852     }
1853   
1854   /* Save the bfd for later use.  */
1855   globals->bfd_of_glue_owner = abfd;
1856   
1857   return true;
1858 }
1859
1860 #ifdef COFF_IMAGE_WITH_PE
1861 static
1862 #endif
1863 boolean
1864 bfd_arm_process_before_allocation (abfd, info, support_old_code)
1865      bfd *                   abfd;
1866      struct bfd_link_info *  info;
1867      int                     support_old_code;
1868 {
1869   asection * sec;
1870   struct coff_arm_link_hash_table * globals;
1871
1872   /* If we are only performing a partial link do not bother
1873      to construct any glue.  */
1874   if (info->relocateable)
1875     return true;
1876   
1877   /* Here we have a bfd that is to be included on the link.  We have a hook
1878      to do reloc rummaging, before section sizes are nailed down.  */
1879
1880   _bfd_coff_get_external_symbols (abfd);
1881
1882   globals = coff_arm_hash_table (info);
1883   
1884   BFD_ASSERT (globals != NULL);
1885   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1886
1887   globals->support_old_code = support_old_code;
1888   
1889   /* Rummage around all the relocs and map the glue vectors.  */
1890   sec = abfd->sections;
1891
1892   if (sec == NULL)
1893     return true;
1894
1895   for (; sec != NULL; sec = sec->next)
1896     {
1897       struct internal_reloc * i;
1898       struct internal_reloc * rel;
1899
1900       if (sec->reloc_count == 0) 
1901         continue;
1902
1903       /* Load the relocs.  */
1904       /* FIXME: there may be a storage leak here. */
1905       
1906       i = _bfd_coff_read_internal_relocs (abfd, sec, 1, 0, 0, 0);
1907     
1908       BFD_ASSERT (i != 0);
1909
1910       for (rel = i; rel < i + sec->reloc_count; ++rel) 
1911         {
1912           unsigned short                 r_type  = rel->r_type;
1913           long                           symndx;
1914           struct coff_link_hash_entry *  h;
1915
1916           symndx = rel->r_symndx;
1917
1918           /* If the relocation is not against a symbol it cannot concern us. */
1919           if (symndx == -1)
1920             continue;
1921
1922           h = obj_coff_sym_hashes (abfd)[symndx];
1923
1924           /* If the relocation is against a static symbol it must be within
1925              the current section and so cannot be a cross ARM/Thumb relocation.  */
1926           if (h == NULL)
1927             continue;
1928
1929           switch (r_type)
1930             {
1931             case ARM_26:
1932               /* This one is a call from arm code.  We need to look up
1933                  the target of the call. If it is a thumb target, we
1934                  insert glue.  */
1935               
1936               if (h->class == C_THUMBEXTFUNC)
1937                 record_arm_to_thumb_glue (info, h);
1938               break;
1939               
1940             case ARM_THUMB23:
1941               /* This one is a call from thumb code.  We used to look
1942                  for ARM_THUMB9 and ARM_THUMB12 as well.  We need to look
1943                  up the target of the call. If it is an arm target, we
1944                  insert glue.  If the symbol does not exist it will be
1945                  given a class of C_EXT and so we will generate a stub
1946                  for it.  This is not really a problem, since the link
1947                  is doomed anyway.  */
1948
1949               switch (h->class)
1950                 {
1951                 case C_EXT:
1952                 case C_STAT:
1953                 case C_LABEL:
1954                   record_thumb_to_arm_glue (info, h);
1955                   break;
1956                 default:
1957                   ;
1958                 }
1959               break;
1960               
1961             default:
1962               break;
1963             }
1964         }
1965     }
1966
1967   return true;
1968 }
1969
1970 #define coff_bfd_reloc_type_lookup              coff_arm_reloc_type_lookup
1971 #define coff_relocate_section                   coff_arm_relocate_section
1972 #define coff_bfd_is_local_label_name            coff_arm_is_local_label_name
1973 #define coff_adjust_symndx                      coff_arm_adjust_symndx
1974 #define coff_link_output_has_begun              coff_arm_link_output_has_begun
1975 #define coff_final_link_postscript              coff_arm_final_link_postscript
1976 #define coff_bfd_merge_private_bfd_data         coff_arm_merge_private_bfd_data
1977 #define coff_bfd_print_private_bfd_data         coff_arm_print_private_bfd_data
1978 #define coff_bfd_set_private_flags              _bfd_coff_arm_set_private_flags
1979 #define coff_bfd_copy_private_bfd_data          coff_arm_copy_private_bfd_data
1980 #define coff_bfd_link_hash_table_create         coff_arm_link_hash_table_create
1981
1982
1983 /* When doing a relocateable link, we want to convert ARM26 relocs
1984    into ARM26D relocs.  */
1985
1986 static boolean
1987 coff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
1988      bfd *obfd;
1989      struct bfd_link_info *info;
1990      bfd *ibfd;
1991      asection *sec;
1992      struct internal_reloc *irel;
1993      boolean *adjustedp;
1994 {
1995   if (irel->r_type == 3)
1996     {
1997       struct coff_link_hash_entry *h;
1998
1999       h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
2000       if (h != NULL
2001           && (h->root.type == bfd_link_hash_defined
2002               || h->root.type == bfd_link_hash_defweak)
2003           && h->root.u.def.section->output_section == sec->output_section)
2004         irel->r_type = 7;
2005     }
2006   *adjustedp = false;
2007   return true;
2008 }
2009
2010 /* Called when merging the private data areas of two BFDs.
2011    This is important as it allows us to detect if we are
2012    attempting to merge binaries compiled for different ARM
2013    targets, eg different CPUs or differents APCS's.     */
2014
2015 static boolean
2016 coff_arm_merge_private_bfd_data (ibfd, obfd)
2017      bfd *   ibfd;
2018      bfd *   obfd;
2019 {
2020   BFD_ASSERT (ibfd != NULL && obfd != NULL);
2021
2022   if (ibfd == obfd)
2023     return true;
2024
2025   /* If the two formats are different we cannot merge anything.
2026      This is not an error, since it is permissable to change the
2027      input and output formats.  */
2028   if (   ibfd->xvec->flavour != bfd_target_coff_flavour
2029       || obfd->xvec->flavour != bfd_target_coff_flavour)
2030     return true;
2031
2032   /* Verify that the APCS is the same for the two BFDs */
2033   if (APCS_SET (ibfd))
2034     {
2035       if (APCS_SET (obfd))
2036         {
2037           /* If the src and dest have different APCS flag bits set, fail.  */
2038           if (APCS_26_FLAG (obfd) != APCS_26_FLAG (ibfd))
2039             {
2040               _bfd_error_handler
2041                 /* xgettext: c-format */
2042                 (_("%s: ERROR: compiled for APCS-%d whereas target %s uses APCS-%d"),
2043                  bfd_get_filename (ibfd), APCS_26_FLAG (ibfd) ? 26 : 32,
2044                  bfd_get_filename (obfd), APCS_26_FLAG (obfd) ? 26 : 32
2045                  );
2046
2047               bfd_set_error (bfd_error_wrong_format);
2048               return false;
2049             }
2050           
2051           if (APCS_FLOAT_FLAG (obfd) != APCS_FLOAT_FLAG (ibfd))
2052             {
2053               const char *msg;
2054
2055               if (APCS_FLOAT_FLAG (ibfd))
2056                 /* xgettext: c-format */
2057                 msg = _("%s: ERROR: passes floats in float registers whereas target %s uses integer registers");
2058               else
2059                 /* xgettext: c-format */
2060                 msg = _("%s: ERROR: passes floats in integer registers whereas target %s uses float registers");
2061               
2062               _bfd_error_handler (msg, bfd_get_filename (ibfd),
2063                                   bfd_get_filename (obfd));
2064
2065               bfd_set_error (bfd_error_wrong_format);
2066               return false;
2067             }
2068           
2069           if (PIC_FLAG (obfd) != PIC_FLAG (ibfd))
2070             {
2071               const char * msg;
2072
2073               if (PIC_FLAG (ibfd))
2074                 /* xgettext: c-format */
2075                 msg = _("%s: ERROR: compiled as position independent code, whereas target %s is absolute position");
2076               else
2077                 /* xgettext: c-format */
2078                 msg = _("%s: ERROR: compiled as absolute position code, whereas target %s is position independent");
2079               _bfd_error_handler (msg, bfd_get_filename (ibfd),
2080                                   bfd_get_filename (obfd));
2081
2082               bfd_set_error (bfd_error_wrong_format);
2083               return false;
2084             }
2085         }
2086       else
2087         {
2088           SET_APCS_FLAGS (obfd, APCS_26_FLAG (ibfd) | APCS_FLOAT_FLAG (ibfd) | PIC_FLAG (ibfd));
2089           
2090           /* Set up the arch and fields as well as these are probably wrong.  */
2091           bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
2092         }
2093     }
2094
2095   /* Check the interworking support.  */
2096   if (INTERWORK_SET (ibfd))
2097     {
2098       if (INTERWORK_SET (obfd))
2099         {
2100           /* If the src and dest differ in their interworking issue a warning.  */
2101           if (INTERWORK_FLAG (obfd) != INTERWORK_FLAG (ibfd))
2102             {
2103               const char * msg;
2104
2105               if (INTERWORK_FLAG (ibfd))
2106                 /* xgettext: c-format */
2107                 msg = _("Warning: input file %s supports interworking, whereas %s does not.");
2108               else
2109                 /* xgettext: c-format */
2110                 msg = _("Warning: input file %s does not support interworking, whereas %s does.");
2111               
2112               _bfd_error_handler (msg, bfd_get_filename (ibfd),
2113                                   bfd_get_filename (obfd));
2114             }
2115         }
2116       else
2117         {
2118           SET_INTERWORK_FLAG (obfd, INTERWORK_FLAG (ibfd));
2119         }
2120     }
2121
2122   return true;
2123 }
2124
2125
2126 /* Display the flags field.  */
2127
2128 static boolean
2129 coff_arm_print_private_bfd_data (abfd, ptr)
2130      bfd *   abfd;
2131      PTR     ptr;
2132 {
2133   FILE * file = (FILE *) ptr;
2134   
2135   BFD_ASSERT (abfd != NULL && ptr != NULL);
2136   
2137   /* xgettext:c-format */
2138   fprintf (file, _("private flags = %x:"), coff_data (abfd)->flags);
2139   
2140   if (APCS_SET (abfd))
2141     {
2142       /* xgettext: APCS is ARM Prodecure Call Standard, it should not be translated.  */
2143       fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32);
2144
2145       if (APCS_FLOAT_FLAG (abfd))
2146         fprintf (file, _(" [floats passed in float registers]"));
2147       else
2148         fprintf (file, _(" [floats passed in integer registers]"));
2149
2150       if (PIC_FLAG (abfd))
2151         fprintf (file, _(" [position independent]"));
2152       else
2153         fprintf (file, _(" [absolute position]"));
2154     }
2155   
2156   if (! INTERWORK_SET (abfd))
2157     fprintf (file, _(" [interworking flag not initialised]"));
2158   else if (INTERWORK_FLAG (abfd))
2159     fprintf (file, _(" [interworking supported]"));
2160   else
2161     fprintf (file, _(" [interworking not supported]"));
2162   
2163   fputc ('\n', file);
2164   
2165   return true;
2166 }
2167
2168
2169 /* Copies the given flags into the coff_tdata.flags field.
2170    Typically these flags come from the f_flags[] field of
2171    the COFF filehdr structure, which contains important,
2172    target specific information.
2173    Note: Although this function is static, it is explicitly
2174    called from both coffcode.h and peicode.h.  */
2175
2176 static boolean
2177 _bfd_coff_arm_set_private_flags (abfd, flags)
2178         bfd *      abfd;
2179         flagword   flags;
2180 {
2181   flagword flag;
2182
2183   BFD_ASSERT (abfd != NULL);
2184
2185   flag = (flags & F_APCS26) ? F_APCS_26 : 0;
2186   
2187   /* Make sure that the APCS field has not been initialised to the opposite
2188      value.  */
2189   if (APCS_SET (abfd)
2190       && (   (APCS_26_FLAG    (abfd) != flag)
2191           || (APCS_FLOAT_FLAG (abfd) != (flags & F_APCS_FLOAT))
2192           || (PIC_FLAG        (abfd) != (flags & F_PIC_INT ? F_PIC : 0))
2193           ))
2194     return false;
2195
2196   flag |= (flags & (F_APCS_FLOAT | F_PIC));
2197   
2198   SET_APCS_FLAGS (abfd, flag);
2199
2200   flag = (flags & F_INTERWORK);
2201   
2202   /* If the BFD has already had its interworking flag set, but it
2203      is different from the value that we have been asked to set,
2204      then assume that that merged code will not support interworking
2205      and set the flag accordingly.  */
2206   if (INTERWORK_SET (abfd) && (INTERWORK_FLAG (abfd) != flag))
2207     {
2208       if (flag)
2209         /* xgettext: c-format */
2210         _bfd_error_handler (_("Warning: Not setting interworking flag of %s, since it has already been specified as non-interworking"),
2211                             bfd_get_filename (abfd));
2212       else
2213         /* xgettext: c-format */
2214         _bfd_error_handler (_("Warning: Clearing the interworking flag of %s due to outside request"),
2215                             bfd_get_filename (abfd));
2216       flag = 0;
2217     }
2218
2219   SET_INTERWORK_FLAG (abfd, flag);
2220
2221   return true;
2222 }
2223
2224
2225 /* Copy the important parts of the target specific data
2226    from one instance of a BFD to another.  */
2227
2228 static boolean
2229 coff_arm_copy_private_bfd_data (src, dest)
2230      bfd *  src;
2231      bfd *  dest;
2232 {
2233   BFD_ASSERT (src != NULL && dest != NULL);
2234  
2235   if (src == dest)
2236     return true;
2237
2238   /* If the destination is not in the same format as the source, do not do
2239      the copy.  */
2240   if (src->xvec != dest->xvec)
2241     return true;
2242
2243   /* copy the flags field */
2244   if (APCS_SET (src))
2245     {
2246       if (APCS_SET (dest))
2247         {
2248           /* If the src and dest have different APCS flag bits set, fail.  */
2249           if (APCS_26_FLAG (dest) != APCS_26_FLAG (src))
2250             return false;
2251           
2252           if (APCS_FLOAT_FLAG (dest) != APCS_FLOAT_FLAG (src))
2253             return false;
2254           
2255           if (PIC_FLAG (dest) != PIC_FLAG (src))
2256             return false;
2257         }
2258       else
2259         SET_APCS_FLAGS (dest, APCS_26_FLAG (src) | APCS_FLOAT_FLAG (src)
2260                         | PIC_FLAG (src));
2261     }
2262
2263   if (INTERWORK_SET (src))
2264     {
2265       if (INTERWORK_SET (dest))
2266         {
2267           /* If the src and dest have different interworking flags then turn
2268              off the interworking bit.  */
2269           if (INTERWORK_FLAG (dest) != INTERWORK_FLAG (src))
2270             {
2271               if (INTERWORK_FLAG (dest))
2272                 {
2273                   /* xgettext:c-format */
2274                   _bfd_error_handler (("Warning: Clearing the interworking bit of %s, because the non-interworking code in %s has been copied into it"),
2275                                       bfd_get_filename (dest),
2276                                       bfd_get_filename (src));
2277                 }
2278               
2279               SET_INTERWORK_FLAG (dest, 0);
2280             }
2281         }
2282       else
2283         {
2284           SET_INTERWORK_FLAG (dest, INTERWORK_FLAG (src));
2285         }
2286     }
2287
2288   return true;
2289 }
2290
2291 /* Note:  the definitions here of LOCAL_LABEL_PREFIX and USER_LABEL_PREIFX
2292  *must* match the definitions in gcc/config/arm/coff.h and semi.h */
2293 #define LOCAL_LABEL_PREFIX "."
2294 #ifndef USER_LABEL_PREFIX
2295 #define USER_LABEL_PREFIX "_"
2296 #endif
2297
2298 static boolean
2299 coff_arm_is_local_label_name (abfd, name)
2300      bfd *        abfd;
2301      const char * name;
2302 {
2303 #ifdef LOCAL_LABEL_PREFIX
2304   /* If there is a prefix for local labels then look for this.
2305      If the prefix exists, but it is empty, then ignore the test. */
2306   
2307   if (LOCAL_LABEL_PREFIX[0] != 0)
2308     {
2309       if (strncmp (name, LOCAL_LABEL_PREFIX, strlen (LOCAL_LABEL_PREFIX)) == 0)
2310         return true;
2311     }
2312 #endif
2313 #ifdef USER_LABEL_PREFIX
2314   if (USER_LABEL_PREFIX[0] != 0)
2315     {
2316       if (strncmp (name, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)) == 0)
2317         return false;
2318     }
2319 #endif
2320   
2321   /* devo/gcc/config/dbxcoff.h defines ASM_OUTPUT_SOURCE_LINE to generate
2322      local line numbers as .LM<number>, so treat these as local.  */
2323   
2324   switch (name[0])
2325     {
2326     case 'L': return true;
2327     case '.': return (name[1] == 'L' && name[2] == 'M') ? true : false;
2328     default:  return false;     /* Cannot make our minds up - default to
2329                                    false so that it will not be stripped
2330                                    by accident.  */ 
2331     }
2332 }
2333
2334 /* This piece of machinery exists only to guarantee that the bfd that holds
2335    the glue section is written last. 
2336
2337    This does depend on bfd_make_section attaching a new section to the
2338    end of the section list for the bfd. 
2339
2340    krk@cygnus.com  */
2341
2342 static boolean
2343 coff_arm_link_output_has_begun (sub, info)
2344      bfd * sub;
2345      struct coff_final_link_info * info;
2346 {
2347   return (sub->output_has_begun
2348           || sub == coff_arm_hash_table (info->info)->bfd_of_glue_owner);
2349 }
2350
2351 static boolean
2352 coff_arm_final_link_postscript (abfd, pfinfo)
2353      bfd * abfd;
2354      struct coff_final_link_info * pfinfo;
2355 {
2356   struct coff_arm_link_hash_table * globals;
2357
2358   globals = coff_arm_hash_table (pfinfo->info);
2359   
2360   BFD_ASSERT (globals != NULL);
2361   
2362   if (globals->bfd_of_glue_owner != NULL)
2363     {
2364       if (! _bfd_coff_link_input_bfd (pfinfo, globals->bfd_of_glue_owner))
2365         return false;
2366       
2367       globals->bfd_of_glue_owner->output_has_begun = true;
2368     }
2369   
2370   return true;
2371 }
2372
2373 #if 0
2374 #define coff_SWAP_sym_in  arm_bfd_coff_swap_sym_in
2375
2376 static void coff_swap_sym_in PARAMS ((bfd *, PTR, PTR));
2377
2378 /* Sepcial version of symbol swapper, used to grab a bfd
2379    onto which the glue sections can be attached.  */
2380 static void
2381 arm_bfd_coff_swap_sym_in (abfd, ext1, in1)
2382      bfd * abfd;
2383      PTR   ext1;
2384      PTR   in1;
2385 {
2386   flagword flags;
2387   register asection * s;
2388
2389   /* Do the normal swap in.  */
2390   coff_swap_sym_in (abfd, ext1, in1);
2391
2392   if (bfd_of_glue_owner != NULL) /* we already have a toc, so go home */
2393     return;
2394
2395   /* Save the bfd for later allocation.  */
2396   bfd_of_glue_owner = abfd;
2397
2398   s = bfd_get_section_by_name (bfd_of_glue_owner , 
2399                                ARM2THUMB_GLUE_SECTION_NAME);
2400
2401   if (s == NULL) 
2402     {
2403       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
2404       
2405       s = bfd_make_section (bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
2406
2407       if (s == NULL
2408           || !bfd_set_section_flags (bfd_of_glue_owner, s, flags)
2409           || !bfd_set_section_alignment (bfd_of_glue_owner, s, 2))
2410         {
2411           /* FIXME: set appropriate bfd error */
2412           abort();
2413         }
2414     }
2415
2416   s = bfd_get_section_by_name (bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
2417
2418   if (s == NULL) 
2419     {
2420       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
2421       
2422       s = bfd_make_section (bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
2423       
2424       if (s == NULL
2425           || !bfd_set_section_flags (bfd_of_glue_owner, s, flags)
2426           || !bfd_set_section_alignment (bfd_of_glue_owner, s, 2))
2427         {
2428           /* FIXME: set appropriate bfd error krk@cygnus.com */
2429           abort();
2430         }
2431     }
2432   
2433   return;
2434 }
2435 #endif
2436
2437 #include "coffcode.h"
2438
2439 const bfd_target
2440 #ifdef TARGET_LITTLE_SYM
2441 TARGET_LITTLE_SYM =
2442 #else
2443 armcoff_little_vec =
2444 #endif
2445 {
2446 #ifdef TARGET_LITTLE_NAME
2447   TARGET_LITTLE_NAME,
2448 #else
2449   "coff-arm-little",
2450 #endif
2451   bfd_target_coff_flavour,
2452   BFD_ENDIAN_LITTLE,            /* data byte order is little */
2453   BFD_ENDIAN_LITTLE,            /* header byte order is little */
2454
2455   (HAS_RELOC | EXEC_P |         /* object flags */
2456    HAS_LINENO | HAS_DEBUG |
2457    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2458
2459 #ifndef COFF_WITH_PE
2460   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2461 #else
2462   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
2463    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
2464 #endif
2465
2466 #ifdef TARGET_UNDERSCORE
2467   TARGET_UNDERSCORE,            /* leading underscore */
2468 #else
2469   0,                            /* leading underscore */
2470 #endif
2471   '/',                          /* ar_pad_char */
2472   15,                           /* ar_max_namelen */
2473
2474   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2475      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2476      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
2477   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2478      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2479      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
2480
2481 /* Note that we allow an object file to be treated as a core file as well. */
2482     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2483        bfd_generic_archive_p, coff_object_p},
2484     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
2485        bfd_false},
2486     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
2487        _bfd_write_archive_contents, bfd_false},
2488
2489      BFD_JUMP_TABLE_GENERIC (coff),
2490      BFD_JUMP_TABLE_COPY (coff),
2491      BFD_JUMP_TABLE_CORE (_bfd_nocore),
2492      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
2493      BFD_JUMP_TABLE_SYMBOLS (coff),
2494      BFD_JUMP_TABLE_RELOCS (coff),
2495      BFD_JUMP_TABLE_WRITE (coff),
2496      BFD_JUMP_TABLE_LINK (coff),
2497      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2498
2499   (PTR) & bfd_coff_std_swap_table,
2500 };
2501
2502 const bfd_target
2503 #ifdef TARGET_BIG_SYM
2504 TARGET_BIG_SYM =
2505 #else
2506 armcoff_big_vec =
2507 #endif
2508 {
2509 #ifdef TARGET_BIG_NAME
2510   TARGET_BIG_NAME,
2511 #else
2512   "coff-arm-big",
2513 #endif
2514   bfd_target_coff_flavour,
2515   BFD_ENDIAN_BIG,               /* data byte order is big */
2516   BFD_ENDIAN_BIG,               /* header byte order is big */
2517
2518   (HAS_RELOC | EXEC_P |         /* object flags */
2519    HAS_LINENO | HAS_DEBUG |
2520    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
2521
2522 #ifndef COFF_WITH_PE
2523   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2524 #else
2525   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
2526    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
2527 #endif
2528
2529 #ifdef TARGET_UNDERSCORE
2530   TARGET_UNDERSCORE,            /* leading underscore */
2531 #else
2532   0,                            /* leading underscore */
2533 #endif
2534   '/',                          /* ar_pad_char */
2535   15,                           /* ar_max_namelen */
2536
2537   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2538      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2539      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
2540   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2541      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2542      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
2543
2544 /* Note that we allow an object file to be treated as a core file as well. */
2545     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
2546        bfd_generic_archive_p, coff_object_p},
2547     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
2548        bfd_false},
2549     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
2550        _bfd_write_archive_contents, bfd_false},
2551
2552      BFD_JUMP_TABLE_GENERIC (coff),
2553      BFD_JUMP_TABLE_COPY (coff),
2554      BFD_JUMP_TABLE_CORE (_bfd_nocore),
2555      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
2556      BFD_JUMP_TABLE_SYMBOLS (coff),
2557      BFD_JUMP_TABLE_RELOCS (coff),
2558      BFD_JUMP_TABLE_WRITE (coff),
2559      BFD_JUMP_TABLE_LINK (coff),
2560      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2561
2562   (PTR) & bfd_coff_std_swap_table,
2563 };