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