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