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