]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elf32-arm.c
Add ARM ELF private flags
[thirdparty/binutils-gdb.git] / bfd / elf32-arm.c
1 /* start-sanitize-armelf */
2 /* 32-bit ELF support for ARM
3 Copyright 1993, 1995, 1998 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25
26 #include "elf/arm.h"
27
28 static reloc_howto_type *elf32_arm_reloc_type_lookup
29 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
30 static void elf32_arm_info_to_howto
31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
32 static boolean elf32_arm_set_private_flags
33 PARAMS ((bfd *, flagword));
34 static boolean elf32_arm_copy_private_bfd_data
35 PARAMS ((bfd *, bfd *));
36 static boolean elf32_arm_merge_private_bfd_data
37 PARAMS ((bfd *, bfd *));
38 static boolean elf32_arm_print_private_bfd_data
39 PARAMS ((bfd *, PTR));
40
41 #define USE_RELA
42 #define TARGET_UNDERSCORE '_'
43
44 static reloc_howto_type elf32_arm_howto_table[] =
45 {
46 /* No relocation */
47 HOWTO (R_ARM_NONE, /* type */
48 0, /* rightshift */
49 0, /* size (0 = byte, 1 = short, 2 = long) */
50 0, /* bitsize */
51 false, /* pc_relative */
52 0, /* bitpos */
53 complain_overflow_dont, /* complain_on_overflow */
54 bfd_elf_generic_reloc, /* special_function */
55 "R_ARM_NONE", /* name */
56 false, /* partial_inplace */
57 0, /* src_mask */
58 0, /* dst_mask */
59 false), /* pcrel_offset */
60
61 HOWTO (R_ARM_PC24, /* type */
62 2, /* rightshift */
63 2, /* size (0 = byte, 1 = short, 2 = long) */
64 24, /* bitsize */
65 true, /* pc_relative */
66 0, /* bitpos */
67 complain_overflow_signed, /* complain_on_overflow */
68 bfd_elf_generic_reloc, /* special_function */
69 "R_ARM_PC24", /* name */
70 false, /* partial_inplace */
71 0x00ffffff, /* src_mask */
72 0x00ffffff, /* dst_mask */
73 true), /* pcrel_offset */
74
75 /* 32 bit absolute */
76 HOWTO (R_ARM_ABS32, /* type */
77 0, /* rightshift */
78 2, /* size (0 = byte, 1 = short, 2 = long) */
79 32, /* bitsize */
80 false, /* pc_relative */
81 0, /* bitpos */
82 complain_overflow_bitfield, /* complain_on_overflow */
83 bfd_elf_generic_reloc, /* special_function */
84 "R_ARM_ABS32", /* name */
85 false, /* partial_inplace */
86 0xffffffff, /* src_mask */
87 0xffffffff, /* dst_mask */
88 false), /* pcrel_offset */
89
90 /* standard 32bit pc-relative reloc */
91 HOWTO (R_ARM_REL32, /* type */
92 0, /* rightshift */
93 2, /* size (0 = byte, 1 = short, 2 = long) */
94 32, /* bitsize */
95 true, /* pc_relative */
96 0, /* bitpos */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 bfd_elf_generic_reloc, /* special_function */
99 "R_ARM_REL32", /* name */
100 false, /* partial_inplace */
101 0xffffffff, /* src_mask */
102 0xffffffff, /* dst_mask */
103 true), /* pcrel_offset */
104
105 /* 8 bit absolute */
106 HOWTO (R_ARM_ABS8, /* type */
107 0, /* rightshift */
108 0, /* size (0 = byte, 1 = short, 2 = long) */
109 8, /* bitsize */
110 false, /* pc_relative */
111 0, /* bitpos */
112 complain_overflow_bitfield, /* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_ARM_ABS8", /* name */
115 false, /* partial_inplace */
116 0x000000ff, /* src_mask */
117 0x000000ff, /* dst_mask */
118 false), /* pcrel_offset */
119
120 /* 16 bit absolute */
121 HOWTO (R_ARM_ABS16, /* type */
122 0, /* rightshift */
123 1, /* size (0 = byte, 1 = short, 2 = long) */
124 16, /* bitsize */
125 false, /* pc_relative */
126 0, /* bitpos */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_ARM_ABS16", /* name */
130 false, /* partial_inplace */
131 0, /* src_mask */
132 0, /* dst_mask */
133 false), /* pcrel_offset */
134
135 /* 12 bit absolute */
136 HOWTO (R_ARM_ABS12, /* type */
137 0, /* rightshift */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
139 12, /* bitsize */
140 false, /* pc_relative */
141 0, /* bitpos */
142 complain_overflow_bitfield, /* complain_on_overflow */
143 bfd_elf_generic_reloc, /* special_function */
144 "R_ARM_ABS12", /* name */
145 false, /* partial_inplace */
146 0x000008ff, /* src_mask */
147 0x000008ff, /* dst_mask */
148 false), /* pcrel_offset */
149
150 HOWTO (R_ARM_THM_ABS5, /* type */
151 0, /* rightshift */
152 2, /* size (0 = byte, 1 = short, 2 = long) */
153 5, /* bitsize */
154 false, /* pc_relative */
155 0, /* bitpos */
156 complain_overflow_bitfield, /* complain_on_overflow */
157 bfd_elf_generic_reloc, /* special_function */
158 "R_ARM_THM_ABS5", /* name */
159 false, /* partial_inplace */
160 0x000007e0, /* src_mask */
161 0x000007e0, /* dst_mask */
162 false), /* pcrel_offset */
163
164 HOWTO (R_ARM_THM_PC22, /* type */
165 1, /* rightshift */
166 2, /* size (0 = byte, 1 = short, 2 = long) */
167 22, /* bitsize */
168 true, /* pc_relative */
169 0, /* bitpos */
170 complain_overflow_signed, /* complain_on_overflow */
171 bfd_elf_generic_reloc, /* special_function */
172 "R_ARM_THM_PC22", /* name */
173 false, /* partial_inplace */
174 0x07ff07ff, /* src_mask */
175 0x07ff07ff, /* dst_mask */
176 true), /* pcrel_offset */
177
178 HOWTO (R_ARM_SBREL32, /* type */
179 0, /* rightshift */
180 0, /* size (0 = byte, 1 = short, 2 = long) */
181 0, /* bitsize */
182 false, /* pc_relative */
183 0, /* bitpos */
184 complain_overflow_dont, /* complain_on_overflow */
185 bfd_elf_generic_reloc, /* special_function */
186 "R_ARM_SBREL32", /* name */
187 false, /* partial_inplace */
188 0, /* src_mask */
189 0, /* dst_mask */
190 false), /* pcrel_offset */
191
192 HOWTO (R_ARM_AMP_VCALL9, /* type */
193 1, /* rightshift */
194 1, /* size (0 = byte, 1 = short, 2 = long) */
195 8, /* bitsize */
196 true, /* pc_relative */
197 0, /* bitpos */
198 complain_overflow_signed, /* complain_on_overflow */
199 bfd_elf_generic_reloc, /* special_function */
200 "R_ARM_AMP_VCALL9", /* name */
201 false, /* partial_inplace */
202 0x000000ff, /* src_mask */
203 0x000000ff, /* dst_mask */
204 true), /* pcrel_offset */
205
206 /* 12 bit pc relative */
207 HOWTO (R_ARM_THM_PC11, /* type */
208 1, /* rightshift */
209 1, /* size (0 = byte, 1 = short, 2 = long) */
210 11, /* bitsize */
211 true, /* pc_relative */
212 0, /* bitpos */
213 complain_overflow_signed, /* complain_on_overflow */
214 bfd_elf_generic_reloc, /* special_function */
215 "R_ARM_THM_PC11", /* name */
216 false, /* partial_inplace */
217 0x000007ff, /* src_mask */
218 0x000007ff, /* dst_mask */
219 true), /* pcrel_offset */
220
221 /* 12 bit pc relative */
222 HOWTO (R_ARM_THM_PC9, /* type */
223 1, /* rightshift */
224 1, /* size (0 = byte, 1 = short, 2 = long) */
225 8, /* bitsize */
226 true, /* pc_relative */
227 0, /* bitpos */
228 complain_overflow_signed, /* complain_on_overflow */
229 bfd_elf_generic_reloc, /* special_function */
230 "R_ARM_THM_PC9", /* name */
231 false, /* partial_inplace */
232 0x000000ff, /* src_mask */
233 0x000000ff, /* dst_mask */
234 true), /* pcrel_offset */
235
236 /* FILL ME IN (#13-249) */
237
238
239 HOWTO (R_ARM_RREL32, /* type */
240 0, /* rightshift */
241 0, /* size (0 = byte, 1 = short, 2 = long) */
242 0, /* bitsize */
243 false, /* pc_relative */
244 0, /* bitpos */
245 complain_overflow_dont, /* complain_on_overflow */
246 bfd_elf_generic_reloc, /* special_function */
247 "R_ARM_RREL32", /* name */
248 false, /* partial_inplace */
249 0, /* src_mask */
250 0, /* dst_mask */
251 false), /* pcrel_offset */
252
253 HOWTO (R_ARM_RABS32, /* type */
254 0, /* rightshift */
255 0, /* size (0 = byte, 1 = short, 2 = long) */
256 0, /* bitsize */
257 false, /* pc_relative */
258 0, /* bitpos */
259 complain_overflow_dont, /* complain_on_overflow */
260 bfd_elf_generic_reloc, /* special_function */
261 "R_ARM_RABS32", /* name */
262 false, /* partial_inplace */
263 0, /* src_mask */
264 0, /* dst_mask */
265 false), /* pcrel_offset */
266
267 HOWTO (R_ARM_RPC24, /* type */
268 0, /* rightshift */
269 0, /* size (0 = byte, 1 = short, 2 = long) */
270 0, /* bitsize */
271 false, /* pc_relative */
272 0, /* bitpos */
273 complain_overflow_dont, /* complain_on_overflow */
274 bfd_elf_generic_reloc, /* special_function */
275 "R_ARM_RPC24", /* name */
276 false, /* partial_inplace */
277 0, /* src_mask */
278 0, /* dst_mask */
279 false), /* pcrel_offset */
280
281 HOWTO (R_ARM_RBASE, /* type */
282 0, /* rightshift */
283 0, /* size (0 = byte, 1 = short, 2 = long) */
284 0, /* bitsize */
285 false, /* pc_relative */
286 0, /* bitpos */
287 complain_overflow_dont, /* complain_on_overflow */
288 bfd_elf_generic_reloc, /* special_function */
289 "R_ARM_RBASE", /* name */
290 false, /* partial_inplace */
291 0, /* src_mask */
292 0, /* dst_mask */
293 false), /* pcrel_offset */
294
295 };
296 struct elf32_arm_reloc_map
297 {
298 unsigned char bfd_reloc_val;
299 unsigned char elf_reloc_val;
300 };
301
302 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
303 {
304 { BFD_RELOC_NONE, R_ARM_NONE, },
305 { BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24, },
306 { BFD_RELOC_32, R_ARM_ABS32, },
307 { BFD_RELOC_32_PCREL, R_ARM_REL32, },
308 { BFD_RELOC_8, R_ARM_ABS8, },
309 { BFD_RELOC_16, R_ARM_ABS16, },
310 { BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12, },
311 { BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5, },
312 { BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22, },
313 { BFD_RELOC_NONE, R_ARM_SBREL32 , },
314 { BFD_RELOC_NONE, R_ARM_AMP_VCALL9, },
315 { BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_PC11, },
316 { BFD_RELOC_THUMB_PCREL_BRANCH9, R_ARM_THM_PC9, }
317 };
318
319 static reloc_howto_type *
320 elf32_arm_reloc_type_lookup (abfd, code)
321 bfd *abfd;
322 bfd_reloc_code_real_type code;
323 {
324 unsigned int i;
325
326 for (i = 0;
327 i < sizeof (elf32_arm_reloc_map) / sizeof (struct elf32_arm_reloc_map);
328 i++)
329 {
330 if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
331 return &elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val];
332 }
333
334 return NULL;
335 }
336
337 static void
338 elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc)
339 bfd *abfd;
340 arelent *bfd_reloc;
341 Elf32_Internal_Rela *elf_reloc;
342 {
343 unsigned int r_type;
344
345 r_type = ELF32_R_TYPE (elf_reloc->r_info);
346 /* fixme: need range test */
347 /* BFD_ASSERT (r_type < (unsigned int) R_ELF32_ARM_MAX); */
348 bfd_reloc->howto = &elf32_arm_howto_table[r_type];
349 }
350
351 /* Perform a relocation as part of a final link. */
352 static bfd_reloc_status_type
353 elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
354 input_section, contents, offset, value,
355 addend, info, sym_sec, is_local)
356 reloc_howto_type *howto;
357 bfd *input_bfd;
358 bfd *output_bfd;
359 asection *input_section;
360 bfd_byte *contents;
361 bfd_vma offset;
362 bfd_vma value;
363 bfd_vma addend;
364 struct bfd_link_info *info;
365 asection *sym_sec;
366 int is_local;
367 {
368 unsigned long r_type = howto->type;
369 bfd_byte *hit_data = contents + offset;
370
371 switch (r_type)
372 {
373
374 case R_ARM_NONE:
375 return bfd_reloc_ok;
376
377 case R_ARM_PC24:
378 value -= (input_section->output_offset + offset + 8);
379 value += addend;
380 value = value >> 2;
381
382 /* if ((long) value > 0xffffff || (long) value < -0x1000000)
383 return bfd_reloc_overflow; */
384
385 value &= 0xffffff;
386 value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
387 bfd_put_32 (input_bfd, value, hit_data);
388 return bfd_reloc_ok;
389
390 case R_ARM_ABS32:
391 value += addend;
392 bfd_put_32 (input_bfd, value, hit_data);
393 return bfd_reloc_ok;
394
395 case R_ARM_REL32:
396 value -= (input_section->output_section->vma
397 + input_section->output_offset);
398 value += addend;
399
400 bfd_put_32 (input_bfd, value, hit_data);
401 return bfd_reloc_ok;
402
403 case R_ARM_ABS8:
404 value += addend;
405
406 if ((long) value > 0x7f || (long) value < -0x80)
407 return bfd_reloc_overflow;
408
409 bfd_put_8 (input_bfd, value, hit_data);
410 return bfd_reloc_ok;
411
412 case R_ARM_ABS16:
413 value += addend;
414
415 if ((long) value > 0x7fff || (long) value < -0x8000)
416 return bfd_reloc_overflow;
417
418 bfd_put_16 (input_bfd, value, hit_data);
419 return bfd_reloc_ok;
420
421 case R_ARM_ABS12:
422 /* Support ldr and str instruction for the arm */
423 /* Also thumb b (unconditional branch) */
424 value += addend;
425
426 if ((long) value > 0x7ff || (long) value < -0x800)
427 return bfd_reloc_overflow;
428
429 value |= (bfd_get_32 (input_bfd, hit_data) & 0xfffff000);
430 bfd_put_32 (input_bfd, value, hit_data);
431 return bfd_reloc_ok;
432
433 case R_ARM_THM_ABS5:
434 /* Support ldr and str instructions for the thumb. */
435 value += addend;
436
437 if ((long) value > 0x1f || (long) value < -0x10)
438 return bfd_reloc_overflow;
439
440 value |= bfd_get_16 (input_bfd, hit_data) & 0xf82f;
441 bfd_put_16 (input_bfd, value, hit_data);
442 return bfd_reloc_ok;
443 break;
444
445 #define LOW_HI_ORDER 0xF800F000
446 #define HI_LOW_ORDER 0xF000F800
447
448 /* thumb BL (branch long instruction). */
449 case R_ARM_THM_PC22:
450 {
451 unsigned int low_bits;
452 unsigned int high_bits;
453 bfd_vma insn;
454
455 value -= (input_section->output_offset + offset + 8);
456 value += addend;
457 value = value >> 1;
458
459 low_bits = value & 0x000007ff;
460 high_bits = (value >> 11) & 0x000007ff;
461 insn = bfd_get_32 (input_bfd, hit_data);
462
463 if ((insn & LOW_HI_ORDER) == LOW_HI_ORDER)
464 insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
465 else if ((insn & HI_LOW_ORDER) == HI_LOW_ORDER)
466 insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
467 else
468 abort(); /* error - not a valid branch instruction form */
469
470 bfd_put_32 (input_bfd, insn, hit_data);
471 return bfd_reloc_ok;
472 }
473 break;
474
475 case R_ARM_SBREL32:
476 break;
477
478 case R_ARM_AMP_VCALL9:
479 return bfd_reloc_notsupported;
480
481 case R_ARM_RSBREL32:
482 return bfd_reloc_notsupported;
483
484 case R_ARM_THM_RPC22:
485 return bfd_reloc_notsupported;
486
487 case R_ARM_RREL32:
488 return bfd_reloc_notsupported;
489
490 case R_ARM_RABS32:
491 return bfd_reloc_notsupported;
492
493 case R_ARM_RPC24:
494 return bfd_reloc_notsupported;
495
496 case R_ARM_RBASE:
497 return bfd_reloc_notsupported;
498
499 default:
500 return bfd_reloc_notsupported;
501 }
502 }
503 /* Relocate an ARM ELF section. */
504 static boolean
505 elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
506 contents, relocs, local_syms, local_sections)
507 bfd *output_bfd;
508 struct bfd_link_info *info;
509 bfd *input_bfd;
510 asection *input_section;
511 bfd_byte *contents;
512 Elf_Internal_Rela *relocs;
513 Elf_Internal_Sym *local_syms;
514 asection **local_sections;
515 {
516 Elf_Internal_Shdr *symtab_hdr;
517 struct elf_link_hash_entry **sym_hashes;
518 Elf_Internal_Rela *rel, *relend;
519
520 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
521 sym_hashes = elf_sym_hashes (input_bfd);
522
523 rel = relocs;
524 relend = relocs + input_section->reloc_count;
525 for (; rel < relend; rel++)
526 {
527 int r_type;
528 reloc_howto_type *howto;
529 unsigned long r_symndx;
530 Elf_Internal_Sym *sym;
531 asection *sec;
532 struct elf_link_hash_entry *h;
533 bfd_vma relocation;
534 bfd_reloc_status_type r;
535
536 r_symndx = ELF32_R_SYM (rel->r_info);
537 r_type = ELF32_R_TYPE (rel->r_info);
538 howto = elf32_arm_howto_table + r_type;
539
540 if (info->relocateable)
541 {
542 /* This is a relocateable link. We don't have to change
543 anything, unless the reloc is against a section symbol,
544 in which case we have to adjust according to where the
545 section symbol winds up in the output section. */
546 if (r_symndx < symtab_hdr->sh_info)
547 {
548 sym = local_syms + r_symndx;
549 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
550 {
551 sec = local_sections[r_symndx];
552 rel->r_addend += sec->output_offset + sym->st_value;
553 }
554 }
555
556 continue;
557 }
558
559 /* This is a final link. */
560 h = NULL;
561 sym = NULL;
562 sec = NULL;
563 if (r_symndx < symtab_hdr->sh_info)
564 {
565 sym = local_syms + r_symndx;
566 sec = local_sections[r_symndx];
567 relocation = (sec->output_section->vma
568 + sec->output_offset
569 + sym->st_value);
570 }
571 else
572 {
573 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
574 while (h->root.type == bfd_link_hash_indirect
575 || h->root.type == bfd_link_hash_warning)
576 h = (struct elf_link_hash_entry *) h->root.u.i.link;
577 if (h->root.type == bfd_link_hash_defined
578 || h->root.type == bfd_link_hash_defweak)
579 {
580 sec = h->root.u.def.section;
581 relocation = (h->root.u.def.value
582 + sec->output_section->vma
583 + sec->output_offset);
584 }
585 else if (h->root.type == bfd_link_hash_undefweak)
586 relocation = 0;
587 else
588 {
589 if (! ((*info->callbacks->undefined_symbol)
590 (info, h->root.root.string, input_bfd,
591 input_section, rel->r_offset)))
592 return false;
593 relocation = 0;
594 }
595 }
596
597 r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
598 input_section,
599 contents, rel->r_offset,
600 relocation, rel->r_addend,
601 info, sec, h == NULL);
602
603
604 if (r != bfd_reloc_ok)
605 {
606 const char *name;
607 const char *msg = (const char *)0;
608
609 if (h != NULL)
610 name = h->root.root.string;
611 else
612 {
613 name = (bfd_elf_string_from_elf_section
614 (input_bfd, symtab_hdr->sh_link, sym->st_name));
615 if (name == NULL || *name == '\0')
616 name = bfd_section_name (input_bfd, sec);
617 }
618
619 switch (r)
620 {
621 case bfd_reloc_overflow:
622 if (! ((*info->callbacks->reloc_overflow)
623 (info, name, howto->name, (bfd_vma) 0,
624 input_bfd, input_section, rel->r_offset)))
625 return false;
626 break;
627
628 case bfd_reloc_undefined:
629 if (! ((*info->callbacks->undefined_symbol)
630 (info, name, input_bfd, input_section,
631 rel->r_offset)))
632 return false;
633 break;
634
635 case bfd_reloc_outofrange:
636 msg = _("internal error: out of range error");
637 goto common_error;
638
639 case bfd_reloc_notsupported:
640 msg = _("internal error: unsupported relocation error");
641 goto common_error;
642
643 case bfd_reloc_dangerous:
644 msg = _("internal error: dangerous error");
645 goto common_error;
646
647 default:
648 msg = _("internal error: unknown error");
649 /* fall through */
650
651 common_error:
652 if (!((*info->callbacks->warning)
653 (info, msg, name, input_bfd, input_section,
654 rel->r_offset)))
655 return false;
656 break;
657 }
658 }
659 }
660
661 return true;
662 }
663
664 /* Function to keep ARM specific flags in the ELF header. */
665 static boolean
666 elf32_arm_set_private_flags (abfd, flags)
667 bfd * abfd;
668 flagword flags;
669 {
670 if (elf_flags_init (abfd)
671 && elf_elfheader (abfd)->e_flags != flags)
672 {
673 if (flags & EF_INTERWORK)
674 _bfd_error_handler (_("\
675 Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
676 bfd_get_filename (abfd));
677 else
678 _bfd_error_handler (_("\
679 Warning: Clearing the interwork flag of %s due to outside request"),
680 bfd_get_filename (abfd));
681 }
682 else
683 {
684 elf_elfheader (abfd)->e_flags = flags;
685 elf_flags_init (abfd) = true;
686 }
687
688 return true;
689 }
690
691 /* Copy backend specific data from one object module to another */
692 static boolean
693 elf32_arm_copy_private_bfd_data (ibfd, obfd)
694 bfd * ibfd;
695 bfd * obfd;
696 {
697 flagword in_flags;
698 flagword out_flags;
699
700 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
701 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
702 return true;
703
704 in_flags = elf_elfheader (ibfd)->e_flags;
705 out_flags = elf_elfheader (obfd)->e_flags;
706
707 if (elf_flags_init (obfd) && in_flags != out_flags)
708 {
709 /* Cannot mix PIC and non-PIC code. */
710 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
711 return false;
712
713 /* Cannot mix APCS26 and APCS32 code. */
714 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
715 return false;
716
717 /* Cannot mix float APCS and non-float APCS code. */
718 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
719 return false;
720
721 /* If the src and dest have different interworking flags
722 then turn off the interworking bit. */
723 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
724 {
725 if (out_flags & EF_INTERWORK)
726 _bfd_error_handler (_("\
727 Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
728 bfd_get_filename (obfd), bfd_get_filename (ibfd));
729
730 in_flags &= ~ EF_INTERWORK;
731 }
732 }
733
734 elf_elfheader (obfd)->e_flags = in_flags;
735 elf_flags_init (obfd) = true;
736
737 return true;
738 }
739
740 /* Merge backend specific data from an object file to the output
741 object file when linking. */
742 static boolean
743 elf32_arm_merge_private_bfd_data (ibfd, obfd)
744 bfd * ibfd;
745 bfd * obfd;
746 {
747 flagword out_flags;
748 flagword in_flags;
749
750 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
751 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
752 return true;
753
754 /* The input BFD must have had its flags initialised. */
755 BFD_ASSERT (elf_flags_init (ibfd));
756
757 in_flags = elf_elfheader (ibfd)->e_flags;
758 out_flags = elf_elfheader (obfd)->e_flags;
759
760 if (! elf_flags_init (obfd))
761 {
762 /* If the input is the default architecture then do not
763 bother setting the flags for the output architecture,
764 instead allow future merges to do this. If no future
765 merges ever set these flags then they will retain their
766 unitialised values, which surprise surprise, correspond
767 to the default values. */
768 if (bfd_get_arch_info (ibfd)->the_default)
769 return true;
770
771 elf_flags_init (obfd) = true;
772 elf_elfheader (obfd)->e_flags = in_flags;
773
774 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
775 && bfd_get_arch_info (obfd)->the_default)
776 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
777
778 return true;
779 }
780
781 /* Check flag compatibility. */
782 if (in_flags == out_flags)
783 return true;
784
785 /* Complain about various flag mismatches. */
786
787 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
788 _bfd_error_handler (_("\
789 Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
790 bfd_get_filename (ibfd),
791 in_flags & EF_APCS_26 ? 26 : 32,
792 bfd_get_filename (obfd),
793 out_flags & EF_APCS_26 ? 26 : 32);
794
795 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
796 _bfd_error_handler (_("\
797 Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
798 bfd_get_filename (ibfd),
799 in_flags & EF_APCS_FLOAT ? _("float") : _("integer"),
800 bfd_get_filename (obfd),
801 out_flags & EF_APCS_26 ? _("float") : _("integer"));
802
803 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
804 _bfd_error_handler (_("\
805 Error: %s is compiled as position %s code, whereas %s is not"),
806 bfd_get_filename (ibfd),
807 in_flags & EF_PIC ? _("independent") : _("dependent"),
808 bfd_get_filename (obfd));
809
810 /* Interworking mismatch is only a warning. */
811 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
812 {
813 _bfd_error_handler (_("\
814 Warning: %s %s interworking, whereas %s %s"),
815 bfd_get_filename (ibfd),
816 in_flags & EF_INTERWORK ? _("supports") : _("does not support"),
817 bfd_get_filename (obfd),
818 out_flags & EF_INTERWORK ? _("does not") : _("does"));
819 return true;
820 }
821
822 return false;
823 }
824
825 /* Display the flags field */
826 static boolean
827 elf32_arm_print_private_bfd_data (abfd, ptr)
828 bfd * abfd;
829 PTR ptr;
830 {
831 FILE * file = (FILE *) ptr;
832
833 BFD_ASSERT (abfd != NULL && ptr != NULL);
834
835 /* Print normal ELF private data. */
836 _bfd_elf_print_private_bfd_data (abfd, ptr);
837
838 /* Ignore init flag - it may not be set, despite the flags field containing valid data. */
839
840 /* xgettext:c-format */
841 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
842
843 if (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
844 fprintf (file, _(" [interworking enabled]"));
845 else
846 fprintf (file, _(" [interworking not enabled]"));
847
848 if (elf_elfheader (abfd)->e_flags & EF_APCS_26)
849 fprintf (file, _(" [APCS-26]"));
850 else
851 fprintf (file, _(" [APCS-32]"));
852
853 if (elf_elfheader (abfd)->e_flags & EF_APCS_FLOAT)
854 fprintf (file, _(" [floats passed in float registers]"));
855 else
856 fprintf (file, _(" [floats passed in intgere registers]"));
857
858 if (elf_elfheader (abfd)->e_flags & EF_PIC)
859 fprintf (file, _(" [position independent]"));
860 else
861 fprintf (file, _(" [absolute position]"));
862
863 fputc ('\n', file);
864
865 return true;
866 }
867
868
869 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
870 #define TARGET_LITTLE_NAME "elf32-littlearm"
871 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
872 #define TARGET_BIG_NAME "elf32-bigarm"
873 #define ELF_ARCH bfd_arch_arm
874 #define ELF_MACHINE_CODE EM_ARM
875
876 #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
877 #define elf_info_to_howto elf32_arm_info_to_howto
878 #define elf_info_to_howto_rel 0
879 #define elf_backend_relocate_section elf32_arm_relocate_section
880 #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data
881 #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data
882 #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags
883 #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data
884
885 #define elf_symbol_leading_char '_'
886
887 #include "elf32-target.h"
888 /* end-sanitize-armelf */