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