OSDN Git Service

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