]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elf32-arm.c
* Makefile.am: Add elf32-arm.c.
[thirdparty/binutils-gdb.git] / bfd / elf32-arm.c
1 /* 32-bit ELF support for ARM
2 Copyright 1993, 1995, 1998 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "elf-bfd.h"
24
25 #include "elf/arm.h"
26
27 typedef unsigned long int insn32;
28 typedef unsigned short int insn16;
29
30 static reloc_howto_type *elf32_arm_reloc_type_lookup
31 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
32 static void elf32_arm_info_to_howto
33 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
34 static boolean elf32_arm_set_private_flags
35 PARAMS ((bfd *, flagword));
36 static boolean elf32_arm_copy_private_bfd_data
37 PARAMS ((bfd *, bfd *));
38 static boolean elf32_arm_merge_private_bfd_data
39 PARAMS ((bfd *, bfd *));
40 static boolean elf32_arm_print_private_bfd_data
41 PARAMS ((bfd *, PTR));
42 static int elf32_arm_get_symbol_type
43 PARAMS (( Elf_Internal_Sym *));
44 static struct bfd_link_hash_table *elf32_arm_link_hash_table_create
45 PARAMS ((bfd *));
46
47
48 static insn32 insert_thumb_branch
49 PARAMS ((insn32, int));
50 static struct elf_link_hash_entry *find_thumb_glue
51 PARAMS ((struct bfd_link_info *, CONST char *, bfd *));
52 static struct elf_link_hash_entry *find_arm_glue
53 PARAMS ((struct bfd_link_info *, CONST char *, bfd *));
54 static void record_arm_to_thumb_glue
55 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
56 static void record_thumb_to_arm_glue
57 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
58
59 /* The linker script knows the section names for placement.
60 The entry_names are used to do simple name mangling on the stubs.
61 Given a function name, and its type, the stub can be found. The
62 name can be changed. The only requirement is the %s be present.
63 */
64
65 #define INTERWORK_FLAG( abfd ) (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
66
67 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
68 #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
69
70 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
71 #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
72
73 /* Get the ARM elf linker hash table from a link_info structure. */
74 #define elf32_arm_hash_table(info) \
75 ((struct elf32_arm_link_hash_table *) ((info)->hash))
76
77 /* ARM ELF linker hash table */
78 struct elf32_arm_link_hash_table
79 {
80 /* The main hash table. */
81 struct elf_link_hash_table root;
82
83 /* The size in bytes of the section containg the Thumb-to-ARM glue. */
84 long int thumb_glue_size;
85
86 /* The size in bytes of the section containg the ARM-to-Thumb glue. */
87 long int arm_glue_size;
88
89 /* An arbitary input BFD chosen to hold the glue sections. */
90 bfd *bfd_of_glue_owner;
91
92 };
93
94
95
96 /* Create an ARM elf linker hash table */
97
98 static struct bfd_link_hash_table *
99 elf32_arm_link_hash_table_create (abfd)
100 bfd *abfd;
101 {
102 struct elf32_arm_link_hash_table *ret;
103
104 ret = ((struct elf32_arm_link_hash_table *)
105 bfd_alloc (abfd, sizeof (struct elf32_arm_link_hash_table)));
106 if (ret == (struct elf32_arm_link_hash_table *) NULL)
107 return NULL;
108
109 if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
110 _bfd_elf_link_hash_newfunc))
111 {
112 bfd_release (abfd, ret);
113 return NULL;
114 }
115
116 ret->thumb_glue_size = 0;
117 ret->arm_glue_size = 0;
118 ret->bfd_of_glue_owner = NULL;
119
120 return &ret->root.root;
121 }
122
123 static struct elf_link_hash_entry *
124 find_thumb_glue (link_info, name, input_bfd)
125 struct bfd_link_info *link_info;
126 CONST char *name;
127 bfd *input_bfd;
128 {
129 char *tmp_name;
130 struct elf_link_hash_entry *hash;
131 struct elf32_arm_link_hash_table *hash_table;
132
133 /* We need a pointer to the armelf specific hash table. */
134 hash_table = elf32_arm_hash_table (link_info);
135
136
137 tmp_name = ((char *)
138 bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1));
139
140 BFD_ASSERT (tmp_name);
141
142 sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
143
144 hash = elf_link_hash_lookup
145 (&(hash_table)->root, tmp_name, false, false, true);
146
147 if (hash == NULL)
148 /* xgettext:c-format */
149 _bfd_error_handler (_ ("%s: unable to find THUMB glue '%s' for `%s'"),
150 bfd_get_filename (input_bfd), tmp_name, name);
151
152 free (tmp_name);
153
154 return hash;
155 }
156
157 static struct elf_link_hash_entry *
158 find_arm_glue (link_info, name, input_bfd)
159 struct bfd_link_info *link_info;
160 CONST char *name;
161 bfd *input_bfd;
162 {
163 char *tmp_name;
164 struct elf_link_hash_entry *myh;
165 struct elf32_arm_link_hash_table *hash_table;
166
167 /* We need a pointer to the elfarm specific hash table. */
168 hash_table = elf32_arm_hash_table (link_info);
169
170 tmp_name = ((char *)
171 bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));
172
173 BFD_ASSERT (tmp_name);
174
175 sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
176
177 myh = elf_link_hash_lookup
178 (&(hash_table)->root, tmp_name, false, false, true);
179
180 if (myh == NULL)
181 /* xgettext:c-format */
182 _bfd_error_handler (_ ("%s: unable to find ARM glue '%s' for `%s'"),
183 bfd_get_filename (input_bfd), tmp_name, name);
184
185 free (tmp_name);
186
187 return myh;
188 }
189
190 /*
191 ARM->Thumb glue:
192
193 .arm
194 __func_from_arm:
195 ldr r12, __func_addr
196 bx r12
197 __func_addr:
198 .word func @ behave as if you saw a ARM_32 reloc
199 */
200
201 #define ARM2THUMB_GLUE_SIZE 12
202 static const insn32 a2t1_ldr_insn = 0xe59fc000;
203 static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
204 static const insn32 a2t3_func_addr_insn = 0x00000001;
205
206 /*
207 Thumb->ARM: Thumb->(non-interworking aware) ARM
208
209 .thumb .thumb
210 .align 2 .align 2
211 __func_from_thumb: __func_from_thumb:
212 bx pc push {r6, lr}
213 nop ldr r6, __func_addr
214 .arm mov lr, pc
215 __func_change_to_arm: bx r6
216 b func .arm
217 __func_back_to_thumb:
218 ldmia r13! {r6, lr}
219 bx lr
220 __func_addr:
221 .word func
222 */
223
224 #define THUMB2ARM_GLUE_SIZE 8
225 static const insn16 t2a1_bx_pc_insn = 0x4778;
226 static const insn16 t2a2_noop_insn = 0x46c0;
227 static const insn32 t2a3_b_insn = 0xea000000;
228
229 static const insn16 t2a1_push_insn = 0xb540;
230 static const insn16 t2a2_ldr_insn = 0x4e03;
231 static const insn16 t2a3_mov_insn = 0x46fe;
232 static const insn16 t2a4_bx_insn = 0x4730;
233 static const insn32 t2a5_pop_insn = 0xe8bd4040;
234 static const insn32 t2a6_bx_insn = 0xe12fff1e;
235
236 boolean
237 bfd_elf32_arm_allocate_interworking_sections (info)
238 struct bfd_link_info *info;
239 {
240 asection *s;
241 bfd_byte *foo;
242 struct elf32_arm_link_hash_table *globals;
243
244 globals = elf32_arm_hash_table (info);
245
246 BFD_ASSERT (globals != NULL);
247
248 if (globals->arm_glue_size != 0)
249 {
250 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
251
252 s = bfd_get_section_by_name
253 (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
254
255 BFD_ASSERT (s != NULL);
256
257 foo = (bfd_byte *) bfd_alloc
258 (globals->bfd_of_glue_owner, globals->arm_glue_size);
259
260 s->_raw_size = s->_cooked_size = globals->arm_glue_size;
261 s->contents = foo;
262 }
263
264 if (globals->thumb_glue_size != 0)
265 {
266 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
267
268 s = bfd_get_section_by_name
269 (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
270
271 BFD_ASSERT (s != NULL);
272
273 foo = (bfd_byte *) bfd_alloc
274 (globals->bfd_of_glue_owner, globals->thumb_glue_size);
275
276 s->_raw_size = s->_cooked_size = globals->thumb_glue_size;
277 s->contents = foo;
278 }
279
280 return true;
281 }
282
283 static void
284 record_arm_to_thumb_glue (link_info, h)
285 struct bfd_link_info *link_info;
286 struct elf_link_hash_entry *h;
287 {
288 const char *name = h->root.root.string;
289 register asection *s;
290 char *tmp_name;
291 struct elf_link_hash_entry *myh;
292 struct elf32_arm_link_hash_table *globals;
293
294 globals = elf32_arm_hash_table (link_info);
295
296 BFD_ASSERT (globals != NULL);
297 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
298
299 s = bfd_get_section_by_name
300 (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
301
302
303 BFD_ASSERT (s != NULL);
304
305 tmp_name = ((char *)
306 bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));
307
308 BFD_ASSERT (tmp_name);
309
310 sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
311
312 myh = elf_link_hash_lookup
313 (&(globals)->root, tmp_name, false, false, true);
314
315 if (myh != NULL)
316 {
317 free (tmp_name);
318 return; /* we've already seen this guy */
319 }
320
321 /* The only trick here is using hash_table->arm_glue_size as the value. Even
322 though the section isn't allocated yet, this is where we will be putting
323 it. */
324
325 _bfd_generic_link_add_one_symbol (link_info, globals->bfd_of_glue_owner, tmp_name,
326 BSF_GLOBAL,
327 s, globals->arm_glue_size + 1,
328 NULL, true, false,
329 (struct bfd_link_hash_entry **) &myh);
330
331 free (tmp_name);
332
333 globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
334
335 return;
336 }
337
338 static void
339 record_thumb_to_arm_glue (link_info, h)
340 struct bfd_link_info *link_info;
341 struct elf_link_hash_entry *h;
342 {
343 const char *name = h->root.root.string;
344 register asection *s;
345 char *tmp_name;
346 struct elf_link_hash_entry *myh;
347 struct elf32_arm_link_hash_table *hash_table;
348 char bind;
349
350 hash_table = elf32_arm_hash_table (link_info);
351
352 BFD_ASSERT (hash_table != NULL);
353 BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL);
354
355 s = bfd_get_section_by_name
356 (hash_table->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
357
358 BFD_ASSERT (s != NULL);
359
360 tmp_name = (char *) bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
361
362 BFD_ASSERT (tmp_name);
363
364 sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
365
366 myh = elf_link_hash_lookup
367 (&(hash_table)->root, tmp_name, false, false, true);
368
369 if (myh != NULL)
370 {
371 free (tmp_name);
372 return; /* we've already seen this guy */
373 }
374
375 _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, tmp_name,
376 BSF_GLOBAL, s, hash_table->thumb_glue_size + 1,
377 NULL, true, false,
378 (struct bfd_link_hash_entry **) &myh);
379
380 /* If we mark it 'thumb', the disassembler will do a better job. */
381 bind = ELF_ST_BIND (myh->type);
382 myh->type = ELF_ST_INFO (bind, STT_ARM_TFUNC);
383
384 free (tmp_name);
385
386 /* Allocate another symbol to mark where we switch to arm mode. */
387
388 #define CHANGE_TO_ARM "__%s_change_to_arm"
389 #define BACK_FROM_ARM "__%s_back_from_arm"
390
391 tmp_name = (char *) bfd_malloc (strlen (name) + strlen (CHANGE_TO_ARM) + 1);
392
393 BFD_ASSERT (tmp_name);
394
395 sprintf (tmp_name, CHANGE_TO_ARM, name);
396
397 myh = NULL;
398
399 _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, tmp_name,
400 BSF_LOCAL, s, hash_table->thumb_glue_size + 4,
401 NULL, true, false,
402 (struct bfd_link_hash_entry **) &myh);
403
404 free (tmp_name);
405
406 hash_table->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
407
408 return;
409 }
410
411 /* Select a BFD to be used to hold the sections used by the glue code.
412 This function is called from the linker scripts in ld/emultempl/
413 {armelf/pe}.em */
414 boolean
415 bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
416 bfd *abfd;
417 struct bfd_link_info *info;
418 {
419 struct elf32_arm_link_hash_table *globals;
420 flagword flags;
421 asection *sec;
422
423 /* If we are only performing a partial link do not bother
424 getting a bfd to hold the glue. */
425 if (info->relocateable)
426 return true;
427
428 globals = elf32_arm_hash_table (info);
429
430 BFD_ASSERT (globals != NULL);
431
432 if (globals->bfd_of_glue_owner != NULL)
433 return true;
434
435 sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
436
437 if (sec == NULL)
438 {
439 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
440
441 sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
442
443 if (sec == NULL
444 || !bfd_set_section_flags (abfd, sec, flags)
445 || !bfd_set_section_alignment (abfd, sec, 2))
446 return false;
447 }
448
449 sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
450
451 if (sec == NULL)
452 {
453 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
454
455 sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
456
457 if (sec == NULL
458 || !bfd_set_section_flags (abfd, sec, flags)
459 || !bfd_set_section_alignment (abfd, sec, 2))
460 return false;
461 }
462
463 /* Save the bfd for later use. */
464 globals->bfd_of_glue_owner = abfd;
465
466 return true;
467 }
468
469 boolean
470 bfd_elf32_arm_process_before_allocation (abfd, link_info)
471 bfd *abfd;
472 struct bfd_link_info *link_info;
473 {
474 Elf_Internal_Shdr *symtab_hdr;
475 Elf_Internal_Rela *free_relocs = NULL;
476 Elf_Internal_Rela *irel, *irelend;
477 bfd_byte *contents = NULL;
478 bfd_byte *free_contents = NULL;
479 Elf32_External_Sym *extsyms = NULL;
480 Elf32_External_Sym *free_extsyms = NULL;
481
482 asection *sec;
483 struct elf32_arm_link_hash_table *globals;
484
485 /* If we are only performing a partial link do not bother
486 to construct any glue. */
487 if (link_info->relocateable)
488 return true;
489
490 /* Here we have a bfd that is to be included on the link. We have a hook
491 to do reloc rummaging, before section sizes are nailed down. */
492
493 globals = elf32_arm_hash_table (link_info);
494
495 BFD_ASSERT (globals != NULL);
496 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
497
498 /* Rummage around all the relocs and map the glue vectors. */
499 sec = abfd->sections;
500
501 if (sec == NULL)
502 return true;
503
504 for (; sec != NULL; sec = sec->next)
505 {
506
507 if (sec->reloc_count == 0)
508 continue;
509
510 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
511 /* Load the relocs. */
512
513 irel = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL,
514 (Elf_Internal_Rela *) NULL, false));
515
516 BFD_ASSERT (irel != 0);
517
518 irelend = irel + sec->reloc_count;
519 for (; irel < irelend; irel++)
520 {
521 long r_type;
522 unsigned long r_index;
523 unsigned char code;
524
525 struct elf_link_hash_entry *h;
526
527 r_type = ELF32_R_TYPE (irel->r_info);
528 r_index = ELF32_R_SYM (irel->r_info);
529
530 /* These are the only relocation types we care about */
531 if (r_type != R_ARM_PC24
532 && r_type != R_ARM_THM_PC22)
533 continue;
534
535 /* Get the section contents if we haven't done so already. */
536 if (contents == NULL)
537 {
538 /* Get cached copy if it exists. */
539 if (elf_section_data (sec)->this_hdr.contents != NULL)
540 contents = elf_section_data (sec)->this_hdr.contents;
541 else
542 {
543 /* Go get them off disk. */
544 contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
545 if (contents == NULL)
546 goto error_return;
547 free_contents = contents;
548
549 if (!bfd_get_section_contents (abfd, sec, contents,
550 (file_ptr) 0, sec->_raw_size))
551 goto error_return;
552 }
553 }
554
555 /* Read this BFD's symbols if we haven't done so already. */
556 if (extsyms == NULL)
557 {
558 /* Get cached copy if it exists. */
559 if (symtab_hdr->contents != NULL)
560 extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
561 else
562 {
563 /* Go get them off disk. */
564 extsyms = ((Elf32_External_Sym *)
565 bfd_malloc (symtab_hdr->sh_size));
566 if (extsyms == NULL)
567 goto error_return;
568 free_extsyms = extsyms;
569 if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
570 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)
571 != symtab_hdr->sh_size))
572 goto error_return;
573 }
574 }
575
576 /* If the relocation is not against a symbol it cannot concern us. */
577
578 h = NULL;
579
580 /* We don't care about local symbols */
581 if (r_index < symtab_hdr->sh_info)
582 continue;
583
584 /* This is an external symbol */
585 r_index -= symtab_hdr->sh_info;
586 h = (struct elf_link_hash_entry *)
587 elf_sym_hashes (abfd)[r_index];
588
589 /* If the relocation is against a static symbol it must be within
590 the current section and so cannot be a cross ARM/Thumb relocation. */
591 if (h == NULL)
592 continue;
593
594 switch (r_type)
595 {
596 case R_ARM_PC24:
597 /* This one is a call from arm code. We need to look up
598 the target of the call. If it is a thumb target, we
599 insert glue. */
600
601 if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC)
602 record_arm_to_thumb_glue (link_info, h);
603 break;
604
605 case R_ARM_THM_PC22:
606
607 /* This one is a call from thumb code. We look
608 up the target of the call. If it is not a thumb
609 target, we insert glue. */
610
611 if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC)
612 record_thumb_to_arm_glue (link_info, h);
613 break;
614
615 default:
616 break;
617 }
618 }
619 }
620
621 return true;
622 error_return:
623 if (free_relocs != NULL)
624 free (free_relocs);
625 if (free_contents != NULL)
626 free (free_contents);
627 if (free_extsyms != NULL)
628 free (free_extsyms);
629 return false;
630
631 }
632
633 #define USE_RELA
634 #define TARGET_UNDERSCORE '_'
635
636 static reloc_howto_type elf32_arm_howto_table[] =
637 {
638 /* No relocation */
639 HOWTO (R_ARM_NONE, /* type */
640 0, /* rightshift */
641 0, /* size (0 = byte, 1 = short, 2 = long) */
642 0, /* bitsize */
643 false, /* pc_relative */
644 0, /* bitpos */
645 complain_overflow_dont, /* complain_on_overflow */
646 bfd_elf_generic_reloc, /* special_function */
647 "R_ARM_NONE", /* name */
648 false, /* partial_inplace */
649 0, /* src_mask */
650 0, /* dst_mask */
651 false), /* pcrel_offset */
652
653 HOWTO (R_ARM_PC24, /* type */
654 2, /* rightshift */
655 2, /* size (0 = byte, 1 = short, 2 = long) */
656 24, /* bitsize */
657 true, /* pc_relative */
658 0, /* bitpos */
659 complain_overflow_signed, /* complain_on_overflow */
660 bfd_elf_generic_reloc, /* special_function */
661 "R_ARM_PC24", /* name */
662 false, /* partial_inplace */
663 0x00ffffff, /* src_mask */
664 0x00ffffff, /* dst_mask */
665 true), /* pcrel_offset */
666
667 /* 32 bit absolute */
668 HOWTO (R_ARM_ABS32, /* type */
669 0, /* rightshift */
670 2, /* size (0 = byte, 1 = short, 2 = long) */
671 32, /* bitsize */
672 false, /* pc_relative */
673 0, /* bitpos */
674 complain_overflow_bitfield, /* complain_on_overflow */
675 bfd_elf_generic_reloc, /* special_function */
676 "R_ARM_ABS32", /* name */
677 false, /* partial_inplace */
678 0xffffffff, /* src_mask */
679 0xffffffff, /* dst_mask */
680 false), /* pcrel_offset */
681
682 /* standard 32bit pc-relative reloc */
683 HOWTO (R_ARM_REL32, /* type */
684 0, /* rightshift */
685 2, /* size (0 = byte, 1 = short, 2 = long) */
686 32, /* bitsize */
687 true, /* pc_relative */
688 0, /* bitpos */
689 complain_overflow_bitfield, /* complain_on_overflow */
690 bfd_elf_generic_reloc, /* special_function */
691 "R_ARM_REL32", /* name */
692 false, /* partial_inplace */
693 0xffffffff, /* src_mask */
694 0xffffffff, /* dst_mask */
695 true), /* pcrel_offset */
696
697 /* 8 bit absolute */
698 HOWTO (R_ARM_ABS8, /* type */
699 0, /* rightshift */
700 0, /* size (0 = byte, 1 = short, 2 = long) */
701 8, /* bitsize */
702 false, /* pc_relative */
703 0, /* bitpos */
704 complain_overflow_bitfield, /* complain_on_overflow */
705 bfd_elf_generic_reloc, /* special_function */
706 "R_ARM_ABS8", /* name */
707 false, /* partial_inplace */
708 0x000000ff, /* src_mask */
709 0x000000ff, /* dst_mask */
710 false), /* pcrel_offset */
711
712 /* 16 bit absolute */
713 HOWTO (R_ARM_ABS16, /* type */
714 0, /* rightshift */
715 1, /* size (0 = byte, 1 = short, 2 = long) */
716 16, /* bitsize */
717 false, /* pc_relative */
718 0, /* bitpos */
719 complain_overflow_bitfield, /* complain_on_overflow */
720 bfd_elf_generic_reloc, /* special_function */
721 "R_ARM_ABS16", /* name */
722 false, /* partial_inplace */
723 0, /* src_mask */
724 0, /* dst_mask */
725 false), /* pcrel_offset */
726
727 /* 12 bit absolute */
728 HOWTO (R_ARM_ABS12, /* type */
729 0, /* rightshift */
730 2, /* size (0 = byte, 1 = short, 2 = long) */
731 12, /* bitsize */
732 false, /* pc_relative */
733 0, /* bitpos */
734 complain_overflow_bitfield, /* complain_on_overflow */
735 bfd_elf_generic_reloc, /* special_function */
736 "R_ARM_ABS12", /* name */
737 false, /* partial_inplace */
738 0x000008ff, /* src_mask */
739 0x000008ff, /* dst_mask */
740 false), /* pcrel_offset */
741
742 HOWTO (R_ARM_THM_ABS5, /* type */
743 0, /* rightshift */
744 2, /* size (0 = byte, 1 = short, 2 = long) */
745 5, /* bitsize */
746 false, /* pc_relative */
747 0, /* bitpos */
748 complain_overflow_bitfield, /* complain_on_overflow */
749 bfd_elf_generic_reloc, /* special_function */
750 "R_ARM_THM_ABS5", /* name */
751 false, /* partial_inplace */
752 0x000007e0, /* src_mask */
753 0x000007e0, /* dst_mask */
754 false), /* pcrel_offset */
755
756 HOWTO (R_ARM_THM_PC22, /* type */
757 1, /* rightshift */
758 2, /* size (0 = byte, 1 = short, 2 = long) */
759 22, /* bitsize */
760 true, /* pc_relative */
761 0, /* bitpos */
762 complain_overflow_signed, /* complain_on_overflow */
763 bfd_elf_generic_reloc, /* special_function */
764 "R_ARM_THM_PC22", /* name */
765 false, /* partial_inplace */
766 0x07ff07ff, /* src_mask */
767 0x07ff07ff, /* dst_mask */
768 true), /* pcrel_offset */
769
770 HOWTO (R_ARM_SBREL32, /* type */
771 0, /* rightshift */
772 0, /* size (0 = byte, 1 = short, 2 = long) */
773 0, /* bitsize */
774 false, /* pc_relative */
775 0, /* bitpos */
776 complain_overflow_dont, /* complain_on_overflow */
777 bfd_elf_generic_reloc, /* special_function */
778 "R_ARM_SBREL32", /* name */
779 false, /* partial_inplace */
780 0, /* src_mask */
781 0, /* dst_mask */
782 false), /* pcrel_offset */
783
784 HOWTO (R_ARM_AMP_VCALL9, /* type */
785 1, /* rightshift */
786 1, /* size (0 = byte, 1 = short, 2 = long) */
787 8, /* bitsize */
788 true, /* pc_relative */
789 0, /* bitpos */
790 complain_overflow_signed, /* complain_on_overflow */
791 bfd_elf_generic_reloc, /* special_function */
792 "R_ARM_AMP_VCALL9", /* name */
793 false, /* partial_inplace */
794 0x000000ff, /* src_mask */
795 0x000000ff, /* dst_mask */
796 true), /* pcrel_offset */
797
798 /* 12 bit pc relative */
799 HOWTO (R_ARM_THM_PC11, /* type */
800 1, /* rightshift */
801 1, /* size (0 = byte, 1 = short, 2 = long) */
802 11, /* bitsize */
803 true, /* pc_relative */
804 0, /* bitpos */
805 complain_overflow_signed, /* complain_on_overflow */
806 bfd_elf_generic_reloc, /* special_function */
807 "R_ARM_THM_PC11", /* name */
808 false, /* partial_inplace */
809 0x000007ff, /* src_mask */
810 0x000007ff, /* dst_mask */
811 true), /* pcrel_offset */
812
813 /* 12 bit pc relative */
814 HOWTO (R_ARM_THM_PC9, /* type */
815 1, /* rightshift */
816 1, /* size (0 = byte, 1 = short, 2 = long) */
817 8, /* bitsize */
818 true, /* pc_relative */
819 0, /* bitpos */
820 complain_overflow_signed, /* complain_on_overflow */
821 bfd_elf_generic_reloc, /* special_function */
822 "R_ARM_THM_PC9", /* name */
823 false, /* partial_inplace */
824 0x000000ff, /* src_mask */
825 0x000000ff, /* dst_mask */
826 true), /* pcrel_offset */
827
828 /* FILL ME IN (#13-249) */
829
830
831 HOWTO (R_ARM_RREL32, /* type */
832 0, /* rightshift */
833 0, /* size (0 = byte, 1 = short, 2 = long) */
834 0, /* bitsize */
835 false, /* pc_relative */
836 0, /* bitpos */
837 complain_overflow_dont, /* complain_on_overflow */
838 bfd_elf_generic_reloc, /* special_function */
839 "R_ARM_RREL32", /* name */
840 false, /* partial_inplace */
841 0, /* src_mask */
842 0, /* dst_mask */
843 false), /* pcrel_offset */
844
845 HOWTO (R_ARM_RABS32, /* type */
846 0, /* rightshift */
847 0, /* size (0 = byte, 1 = short, 2 = long) */
848 0, /* bitsize */
849 false, /* pc_relative */
850 0, /* bitpos */
851 complain_overflow_dont, /* complain_on_overflow */
852 bfd_elf_generic_reloc, /* special_function */
853 "R_ARM_RABS32", /* name */
854 false, /* partial_inplace */
855 0, /* src_mask */
856 0, /* dst_mask */
857 false), /* pcrel_offset */
858
859 HOWTO (R_ARM_RPC24, /* type */
860 0, /* rightshift */
861 0, /* size (0 = byte, 1 = short, 2 = long) */
862 0, /* bitsize */
863 false, /* pc_relative */
864 0, /* bitpos */
865 complain_overflow_dont, /* complain_on_overflow */
866 bfd_elf_generic_reloc, /* special_function */
867 "R_ARM_RPC24", /* name */
868 false, /* partial_inplace */
869 0, /* src_mask */
870 0, /* dst_mask */
871 false), /* pcrel_offset */
872
873 HOWTO (R_ARM_RBASE, /* type */
874 0, /* rightshift */
875 0, /* size (0 = byte, 1 = short, 2 = long) */
876 0, /* bitsize */
877 false, /* pc_relative */
878 0, /* bitpos */
879 complain_overflow_dont, /* complain_on_overflow */
880 bfd_elf_generic_reloc, /* special_function */
881 "R_ARM_RBASE", /* name */
882 false, /* partial_inplace */
883 0, /* src_mask */
884 0, /* dst_mask */
885 false), /* pcrel_offset */
886
887 };
888 struct elf32_arm_reloc_map
889 {
890 unsigned char bfd_reloc_val;
891 unsigned char elf_reloc_val;
892 };
893
894 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
895 {
896 {BFD_RELOC_NONE, R_ARM_NONE,},
897 {BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24,},
898 {BFD_RELOC_32, R_ARM_ABS32,},
899 {BFD_RELOC_32_PCREL, R_ARM_REL32,},
900 {BFD_RELOC_8, R_ARM_ABS8,},
901 {BFD_RELOC_16, R_ARM_ABS16,},
902 {BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12,},
903 {BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5,},
904 {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22,},
905 {BFD_RELOC_NONE, R_ARM_SBREL32,},
906 {BFD_RELOC_NONE, R_ARM_AMP_VCALL9,},
907 {BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_PC11,},
908 {BFD_RELOC_THUMB_PCREL_BRANCH9, R_ARM_THM_PC9,}
909 };
910
911 static reloc_howto_type *
912 elf32_arm_reloc_type_lookup (abfd, code)
913 bfd *abfd;
914 bfd_reloc_code_real_type code;
915 {
916 unsigned int i;
917
918 for (i = 0;
919 i < sizeof (elf32_arm_reloc_map) / sizeof (struct elf32_arm_reloc_map);
920 i++)
921 {
922 if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
923 return &elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val];
924 }
925
926 return NULL;
927 }
928
929 static void
930 elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc)
931 bfd *abfd;
932 arelent *bfd_reloc;
933 Elf32_Internal_Rela *elf_reloc;
934 {
935 unsigned int r_type;
936
937 r_type = ELF32_R_TYPE (elf_reloc->r_info);
938 /* fixme: need range test */
939 /* BFD_ASSERT (r_type < (unsigned int) R_ELF32_ARM_MAX); */
940 bfd_reloc->howto = &elf32_arm_howto_table[r_type];
941 }
942
943 /* The thumb form of a long branch is a bit finicky, because the offset
944 encoding is split over two fields, each in it's own instruction. They
945 can occur in any order. So given a thumb form of long branch, and an
946 offset, insert the offset into the thumb branch and return finished
947 instruction.
948
949 It takes two thumb instructions to encode the target address. Each has
950 11 bits to invest. The upper 11 bits are stored in one (identifed by
951 H-0.. see below), the lower 11 bits are stored in the other (identified
952 by H-1).
953
954 Combine together and shifted left by 1 (it's a half word address) and
955 there you have it.
956
957 Op: 1111 = F,
958 H-0, upper address-0 = 000
959 Op: 1111 = F,
960 H-1, lower address-0 = 800
961
962 They can be ordered either way, but the arm tools I've seen always put
963 the lower one first. It probably doesn't matter. krk@cygnus.com
964
965 XXX: Actually the order does matter. The second instruction (H-1)
966 moves the computed address into the PC, so it must be the second one
967 in the sequence. The problem, however is that whilst little endian code
968 stores the instructions in HI then LOW order, big endian code does the
969 reverse. nickc@cygnus.com */
970
971 #define LOW_HI_ORDER 0xF800F000
972 #define HI_LOW_ORDER 0xF000F800
973
974 static insn32
975 insert_thumb_branch (br_insn, rel_off)
976 insn32 br_insn;
977 int rel_off;
978 {
979 unsigned int low_bits;
980 unsigned int high_bits;
981
982
983 BFD_ASSERT ((rel_off & 1) != 1);
984
985 rel_off >>= 1; /* half word aligned address */
986 low_bits = rel_off & 0x000007FF; /* the bottom 11 bits */
987 high_bits = (rel_off >> 11) & 0x000007FF; /* the top 11 bits */
988
989 if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
990 br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
991 else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
992 br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
993 else
994 abort (); /* error - not a valid branch instruction form */
995
996 /* FIXME: abort is probably not the right call. krk@cygnus.com */
997
998 return br_insn;
999 }
1000
1001 /* Thumb code calling an ARM function */
1002 int
1003 elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,
1004 hit_data, sym_sec, offset, addend, val)
1005 struct bfd_link_info *info;
1006 char *name;
1007 bfd *input_bfd;
1008 bfd *output_bfd;
1009 asection *input_section;
1010 bfd_byte *hit_data;
1011 asection *sym_sec;
1012 int offset;
1013 int addend;
1014 bfd_vma val;
1015 {
1016 asection *s = 0;
1017 long int my_offset;
1018 unsigned long int tmp;
1019 long int ret_offset;
1020 struct elf_link_hash_entry *myh;
1021 struct elf32_arm_link_hash_table *globals;
1022
1023 myh = find_thumb_glue (info, name, input_bfd);
1024 if (myh == NULL)
1025 return false;
1026
1027 globals = elf32_arm_hash_table (info);
1028
1029 BFD_ASSERT (globals != NULL);
1030 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1031
1032 my_offset = myh->root.u.def.value;
1033
1034 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
1035 THUMB2ARM_GLUE_SECTION_NAME);
1036
1037 BFD_ASSERT (s != NULL);
1038 BFD_ASSERT (s->contents != NULL);
1039 BFD_ASSERT (s->output_section != NULL);
1040
1041 if ((my_offset & 0x01) == 0x01)
1042 {
1043 if (sym_sec != NULL
1044 && sym_sec->owner != NULL
1045 && !INTERWORK_FLAG (sym_sec->owner))
1046 {
1047 _bfd_error_handler
1048 (_ ("%s(%s): warning: interworking not enabled."),
1049 bfd_get_filename (sym_sec->owner), name);
1050 _bfd_error_handler
1051 (_ (" first occurrence: %s: thumb call to arm"),
1052 bfd_get_filename (input_bfd));
1053 }
1054
1055 --my_offset;
1056 myh->root.u.def.value = my_offset;
1057
1058 bfd_put_16 (output_bfd, t2a1_bx_pc_insn,
1059 s->contents + my_offset);
1060
1061 bfd_put_16 (output_bfd, t2a2_noop_insn,
1062 s->contents + my_offset + 2);
1063
1064 ret_offset =
1065 ((bfd_signed_vma) val) /* Address of destination of the stub */
1066 - ((bfd_signed_vma)
1067 (s->output_offset /* Offset from the start of the current section to the start of the stubs. */
1068 + my_offset /* Offset of the start of this stub from the start of the stubs. */
1069 + s->output_section->vma) /* Address of the start of the current section. */
1070 + 4 /* The branch instruction is 4 bytes into the stub. */
1071 + 8); /* ARM branches work from the pc of the instruction + 8. */
1072
1073 bfd_put_32 (output_bfd,
1074 t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
1075 s->contents + my_offset + 4);
1076 }
1077
1078 BFD_ASSERT (my_offset <= globals->thumb_glue_size);
1079
1080 /* Now go back and fix up the original BL insn to point
1081 to here. */
1082 ret_offset =
1083 s->output_offset
1084 + my_offset
1085 - (input_section->output_offset
1086 + offset + addend)
1087 - 4;
1088
1089 tmp = bfd_get_32 (input_bfd, hit_data
1090 - input_section->vma);
1091
1092 bfd_put_32 (output_bfd,
1093 insert_thumb_branch (tmp, ret_offset),
1094 hit_data - input_section->vma);
1095 }
1096
1097 /* Arm code calling a Thumb function */
1098 int
1099 elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section,
1100 hit_data, sym_sec, offset, addend, val)
1101
1102 struct bfd_link_info *info;
1103 char *name;
1104 bfd *input_bfd;
1105 bfd *output_bfd;
1106 asection *input_section;
1107 bfd_byte *hit_data;
1108 asection *sym_sec;
1109 int offset;
1110 int addend;
1111 bfd_vma val;
1112 {
1113 unsigned long int tmp;
1114 long int my_offset;
1115 asection *s;
1116 long int ret_offset;
1117 struct elf_link_hash_entry *myh;
1118 struct elf32_arm_link_hash_table *globals;
1119
1120 myh = find_arm_glue (info, name, input_bfd);
1121 if (myh == NULL)
1122 return false;
1123
1124 globals = elf32_arm_hash_table (info);
1125
1126 BFD_ASSERT (globals != NULL);
1127 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1128
1129 my_offset = myh->root.u.def.value;
1130 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
1131 ARM2THUMB_GLUE_SECTION_NAME);
1132 BFD_ASSERT (s != NULL);
1133 BFD_ASSERT (s->contents != NULL);
1134 BFD_ASSERT (s->output_section != NULL);
1135
1136 if ((my_offset & 0x01) == 0x01)
1137 {
1138 if (sym_sec != NULL
1139 && sym_sec->owner != NULL
1140 && !INTERWORK_FLAG (sym_sec->owner))
1141 {
1142 _bfd_error_handler
1143 (_ ("%s(%s): warning: interworking not enabled."),
1144 bfd_get_filename (sym_sec->owner), name);
1145 _bfd_error_handler
1146 (_ (" first occurrence: %s: arm call to thumb"),
1147 bfd_get_filename (input_bfd));
1148 }
1149 --my_offset;
1150 myh->root.u.def.value = my_offset;
1151
1152 bfd_put_32 (output_bfd, a2t1_ldr_insn,
1153 s->contents + my_offset);
1154
1155 bfd_put_32 (output_bfd, a2t2_bx_r12_insn,
1156 s->contents + my_offset + 4);
1157
1158 /* It's a thumb address. Add the low order bit. */
1159 bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
1160 s->contents + my_offset + 8);
1161 }
1162
1163 BFD_ASSERT (my_offset <= globals->arm_glue_size);
1164
1165 tmp = bfd_get_32 (input_bfd, hit_data);
1166 tmp = tmp & 0xFF000000;
1167
1168 /* Somehow these are both 4 too far, so subtract 8. */
1169 ret_offset = s->output_offset
1170 + my_offset
1171 + s->output_section->vma
1172 - (input_section->output_offset
1173 + input_section->output_section->vma
1174 + offset + addend)
1175 - 8;
1176
1177 tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
1178
1179 bfd_put_32 (output_bfd, tmp, hit_data
1180 - input_section->vma);
1181
1182 }
1183
1184 /* Perform a relocation as part of a final link. */
1185 static bfd_reloc_status_type
1186 elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
1187 input_section, contents, offset, value,
1188 addend, info, sym_sec, sym_name, sym_flags)
1189 reloc_howto_type *howto;
1190 bfd *input_bfd;
1191 bfd *output_bfd;
1192 asection *input_section;
1193 bfd_byte *contents;
1194 bfd_vma offset;
1195 bfd_vma value;
1196 bfd_vma addend;
1197 struct bfd_link_info *info;
1198 asection *sym_sec;
1199 const char *sym_name;
1200 unsigned char sym_flags;
1201 {
1202 unsigned long r_type = howto->type;
1203 bfd_byte *hit_data = contents + offset;
1204
1205 switch (r_type)
1206 {
1207
1208 case R_ARM_NONE:
1209 return bfd_reloc_ok;
1210
1211 case R_ARM_PC24:
1212 /* Arm B/BL instruction */
1213
1214 /* check for arm calling thumb function */
1215 if (sym_flags == STT_ARM_TFUNC)
1216 {
1217 elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
1218 input_section, hit_data, sym_sec, offset, addend, value);
1219 return bfd_reloc_ok;
1220 }
1221
1222 value = value + addend;
1223 value -= (input_section->output_section->vma
1224 + input_section->output_offset + 8);
1225 value -= offset;
1226 value = value >> howto->rightshift;
1227
1228 value &= 0xffffff;
1229 value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
1230 bfd_put_32 (input_bfd, value, hit_data);
1231 return bfd_reloc_ok;
1232
1233 case R_ARM_ABS32:
1234 value += addend;
1235 if (sym_flags == STT_ARM_TFUNC)
1236 value |= 1;
1237 bfd_put_32 (input_bfd, value, hit_data);
1238 return bfd_reloc_ok;
1239
1240 case R_ARM_REL32:
1241 value -= (input_section->output_section->vma
1242 + input_section->output_offset);
1243 value += addend;
1244
1245 bfd_put_32 (input_bfd, value, hit_data);
1246 return bfd_reloc_ok;
1247
1248 case R_ARM_ABS8:
1249 value += addend;
1250
1251 if ((long) value > 0x7f || (long) value < -0x80)
1252 return bfd_reloc_overflow;
1253
1254 bfd_put_8 (input_bfd, value, hit_data);
1255 return bfd_reloc_ok;
1256
1257 case R_ARM_ABS16:
1258 value += addend;
1259
1260 if ((long) value > 0x7fff || (long) value < -0x8000)
1261 return bfd_reloc_overflow;
1262
1263 bfd_put_16 (input_bfd, value, hit_data);
1264 return bfd_reloc_ok;
1265
1266 case R_ARM_ABS12:
1267 /* Support ldr and str instruction for the arm */
1268 /* Also thumb b (unconditional branch) */
1269 value += addend;
1270
1271 if ((long) value > 0x7ff || (long) value < -0x800)
1272 return bfd_reloc_overflow;
1273
1274 value |= (bfd_get_32 (input_bfd, hit_data) & 0xfffff000);
1275 bfd_put_32 (input_bfd, value, hit_data);
1276 return bfd_reloc_ok;
1277
1278 case R_ARM_THM_ABS5:
1279 /* Support ldr and str instructions for the thumb. */
1280 value += addend;
1281
1282 if ((long) value > 0x1f || (long) value < -0x10)
1283 return bfd_reloc_overflow;
1284
1285 value |= bfd_get_16 (input_bfd, hit_data) & 0xf82f;
1286 bfd_put_16 (input_bfd, value, hit_data);
1287 return bfd_reloc_ok;
1288
1289
1290 case R_ARM_THM_PC22:
1291 /* thumb BL (branch long instruction). */
1292 {
1293 bfd_vma relocation;
1294 boolean overflow = false;
1295 bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
1296 bfd_vma src_mask = 0x007FFFFE;
1297 bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
1298 bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
1299 bfd_vma check;
1300 bfd_signed_vma signed_check;
1301 bfd_vma add;
1302 bfd_signed_vma signed_add;
1303
1304 /* If it's not a call to thumb, assume call to arm */
1305 if (sym_flags != STT_ARM_TFUNC)
1306 {
1307 elf32_thumb_to_arm_stub (info, sym_name, input_bfd, output_bfd, input_section,
1308 hit_data, sym_sec, offset, addend, value);
1309 return bfd_reloc_ok;
1310 }
1311
1312 relocation = value + addend;
1313 relocation -= (input_section->output_section->vma + input_section->output_offset);
1314 relocation -= offset;
1315
1316 check = relocation >> howto->rightshift;
1317
1318 /* If this is a signed value, the rightshift just dropped
1319 leading 1 bits (assuming twos complement). */
1320 if ((bfd_signed_vma) relocation >= 0)
1321 signed_check = check;
1322 else
1323 signed_check = (check | ((bfd_vma) - 1 & ~((bfd_vma) - 1 >> howto->rightshift)));
1324
1325 /* Get the value from the object file. */
1326 if (bfd_big_endian (input_bfd))
1327 add = (((insn) & 0x07ff0000) >> 4) | (((insn) & 0x7ff) << 1);
1328 else
1329 add = ((((insn) & 0x7ff) << 12) | (((insn) & 0x07ff0000) >> 15));
1330
1331 /* Get the value from the object file with an appropriate sign.
1332 The expression involving howto->src_mask isolates the upper
1333 bit of src_mask. If that bit is set in the value we are
1334 adding, it is negative, and we subtract out that number times
1335 two. If src_mask includes the highest possible bit, then we
1336 can not get the upper bit, but that does not matter since
1337 signed_add needs no adjustment to become negative in that case. */
1338
1339 signed_add = add;
1340
1341 if ((add & (((~src_mask) >> 1) & src_mask)) != 0)
1342 signed_add -= (((~src_mask) >> 1) & src_mask) << 1;
1343
1344 /* Add the value from the object file, shifted so that it is a
1345 straight number. */
1346 /* howto->bitpos == 0 */
1347
1348 signed_check += signed_add;
1349 relocation += signed_add;
1350
1351 /* Assumes two's complement. */
1352 if (signed_check > reloc_signed_max
1353 || signed_check < reloc_signed_min)
1354 overflow = true;
1355
1356 /* Put RELOCATION into the correct bits: */
1357
1358 if (bfd_big_endian (input_bfd))
1359 relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
1360 else
1361 relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
1362
1363 /* Add RELOCATION to the correct bits of X: */
1364 insn = ((insn & ~howto->dst_mask) | relocation);
1365
1366 /* Put the relocated value back in the object file: */
1367 bfd_put_32 (input_bfd, insn, hit_data);
1368
1369 return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
1370 }
1371 break;
1372
1373 case R_ARM_SBREL32:
1374 return bfd_reloc_notsupported;
1375
1376 case R_ARM_AMP_VCALL9:
1377 return bfd_reloc_notsupported;
1378
1379 case R_ARM_RSBREL32:
1380 return bfd_reloc_notsupported;
1381
1382 case R_ARM_THM_RPC22:
1383 return bfd_reloc_notsupported;
1384
1385 case R_ARM_RREL32:
1386 return bfd_reloc_notsupported;
1387
1388 case R_ARM_RABS32:
1389 return bfd_reloc_notsupported;
1390
1391 case R_ARM_RPC24:
1392 return bfd_reloc_notsupported;
1393
1394 case R_ARM_RBASE:
1395 return bfd_reloc_notsupported;
1396
1397 default:
1398 return bfd_reloc_notsupported;
1399 }
1400 }
1401
1402
1403 /* Relocate an ARM ELF section. */
1404 static boolean
1405 elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
1406 contents, relocs, local_syms, local_sections)
1407 bfd *output_bfd;
1408 struct bfd_link_info *info;
1409 bfd *input_bfd;
1410 asection *input_section;
1411 bfd_byte *contents;
1412 Elf_Internal_Rela *relocs;
1413 Elf_Internal_Sym *local_syms;
1414 asection **local_sections;
1415 {
1416 Elf_Internal_Shdr *symtab_hdr;
1417 struct elf_link_hash_entry **sym_hashes;
1418 Elf_Internal_Rela *rel, *relend;
1419 const char *name;
1420
1421 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1422 sym_hashes = elf_sym_hashes (input_bfd);
1423
1424 rel = relocs;
1425 relend = relocs + input_section->reloc_count;
1426 for (; rel < relend; rel++)
1427 {
1428 int r_type;
1429 reloc_howto_type *howto;
1430 unsigned long r_symndx;
1431 Elf_Internal_Sym *sym;
1432 asection *sec;
1433 struct elf_link_hash_entry *h;
1434 bfd_vma relocation;
1435 bfd_reloc_status_type r;
1436
1437 r_symndx = ELF32_R_SYM (rel->r_info);
1438 r_type = ELF32_R_TYPE (rel->r_info);
1439 howto = elf32_arm_howto_table + r_type;
1440
1441 if (info->relocateable)
1442 {
1443 /* This is a relocateable link. We don't have to change
1444 anything, unless the reloc is against a section symbol,
1445 in which case we have to adjust according to where the
1446 section symbol winds up in the output section. */
1447 if (r_symndx < symtab_hdr->sh_info)
1448 {
1449 sym = local_syms + r_symndx;
1450 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1451 {
1452 sec = local_sections[r_symndx];
1453 rel->r_addend += sec->output_offset + sym->st_value;
1454 }
1455 }
1456
1457 continue;
1458 }
1459
1460 /* This is a final link. */
1461 h = NULL;
1462 sym = NULL;
1463 sec = NULL;
1464 if (r_symndx < symtab_hdr->sh_info)
1465 {
1466 sym = local_syms + r_symndx;
1467 sec = local_sections[r_symndx];
1468 relocation = (sec->output_section->vma
1469 + sec->output_offset
1470 + sym->st_value);
1471 }
1472 else
1473 {
1474 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1475 while (h->root.type == bfd_link_hash_indirect
1476 || h->root.type == bfd_link_hash_warning)
1477 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1478 if (h->root.type == bfd_link_hash_defined
1479 || h->root.type == bfd_link_hash_defweak)
1480 {
1481 sec = h->root.u.def.section;
1482 relocation = (h->root.u.def.value
1483 + sec->output_section->vma
1484 + sec->output_offset);
1485 }
1486 else if (h->root.type == bfd_link_hash_undefweak)
1487 relocation = 0;
1488 else
1489 {
1490 if (!((*info->callbacks->undefined_symbol)
1491 (info, h->root.root.string, input_bfd,
1492 input_section, rel->r_offset)))
1493 return false;
1494 relocation = 0;
1495 }
1496 }
1497
1498 if (h != NULL)
1499 name = h->root.root.string;
1500 else
1501 {
1502 name = (bfd_elf_string_from_elf_section
1503 (input_bfd, symtab_hdr->sh_link, sym->st_name));
1504 if (name == NULL || *name == '\0')
1505 name = bfd_section_name (input_bfd, sec);
1506 }
1507
1508 r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
1509 input_section,
1510 contents, rel->r_offset,
1511 relocation, rel->r_addend,
1512 info, sec, name,
1513 (h ? ELF_ST_TYPE (h->type) : ELF_ST_TYPE (sym->st_info)));
1514
1515
1516 if (r != bfd_reloc_ok)
1517 {
1518 const char *msg = (const char *) 0;
1519
1520 switch (r)
1521 {
1522 case bfd_reloc_overflow:
1523 if (!((*info->callbacks->reloc_overflow)
1524 (info, name, howto->name, (bfd_vma) 0,
1525 input_bfd, input_section, rel->r_offset)))
1526 return false;
1527 break;
1528
1529 case bfd_reloc_undefined:
1530 if (!((*info->callbacks->undefined_symbol)
1531 (info, name, input_bfd, input_section,
1532 rel->r_offset)))
1533 return false;
1534 break;
1535
1536 case bfd_reloc_outofrange:
1537 msg = _ ("internal error: out of range error");
1538 goto common_error;
1539
1540 case bfd_reloc_notsupported:
1541 msg = _ ("internal error: unsupported relocation error");
1542 goto common_error;
1543
1544 case bfd_reloc_dangerous:
1545 msg = _ ("internal error: dangerous error");
1546 goto common_error;
1547
1548 default:
1549 msg = _ ("internal error: unknown error");
1550 /* fall through */
1551
1552 common_error:
1553 if (!((*info->callbacks->warning)
1554 (info, msg, name, input_bfd, input_section,
1555 rel->r_offset)))
1556 return false;
1557 break;
1558 }
1559 }
1560 }
1561
1562 return true;
1563 }
1564
1565 /* Function to keep ARM specific flags in the ELF header. */
1566 static boolean
1567 elf32_arm_set_private_flags (abfd, flags)
1568 bfd *abfd;
1569 flagword flags;
1570 {
1571 if (elf_flags_init (abfd)
1572 && elf_elfheader (abfd)->e_flags != flags)
1573 {
1574 if (flags & EF_INTERWORK)
1575 _bfd_error_handler (_ ("\
1576 Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
1577 bfd_get_filename (abfd));
1578 else
1579 _bfd_error_handler (_ ("\
1580 Warning: Clearing the interwork flag of %s due to outside request"),
1581 bfd_get_filename (abfd));
1582 }
1583 else
1584 {
1585 elf_elfheader (abfd)->e_flags = flags;
1586 elf_flags_init (abfd) = true;
1587 }
1588
1589 return true;
1590 }
1591
1592 /* Copy backend specific data from one object module to another */
1593 static boolean
1594 elf32_arm_copy_private_bfd_data (ibfd, obfd)
1595 bfd *ibfd;
1596 bfd *obfd;
1597 {
1598 flagword in_flags;
1599 flagword out_flags;
1600
1601 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1602 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1603 return true;
1604
1605 in_flags = elf_elfheader (ibfd)->e_flags;
1606 out_flags = elf_elfheader (obfd)->e_flags;
1607
1608 if (elf_flags_init (obfd) && in_flags != out_flags)
1609 {
1610 /* Cannot mix PIC and non-PIC code. */
1611 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
1612 return false;
1613
1614 /* Cannot mix APCS26 and APCS32 code. */
1615 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
1616 return false;
1617
1618 /* Cannot mix float APCS and non-float APCS code. */
1619 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
1620 return false;
1621
1622 /* If the src and dest have different interworking flags
1623 then turn off the interworking bit. */
1624 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
1625 {
1626 if (out_flags & EF_INTERWORK)
1627 _bfd_error_handler (_ ("\
1628 Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
1629 bfd_get_filename (obfd), bfd_get_filename (ibfd));
1630
1631 in_flags &= ~EF_INTERWORK;
1632 }
1633 }
1634
1635 elf_elfheader (obfd)->e_flags = in_flags;
1636 elf_flags_init (obfd) = true;
1637
1638 return true;
1639 }
1640
1641 /* Merge backend specific data from an object file to the output
1642 object file when linking. */
1643 static boolean
1644 elf32_arm_merge_private_bfd_data (ibfd, obfd)
1645 bfd *ibfd;
1646 bfd *obfd;
1647 {
1648 flagword out_flags;
1649 flagword in_flags;
1650
1651 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1652 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1653 return true;
1654
1655 /* The input BFD must have had its flags initialised. */
1656 /* The following seems bogus to me -- The flags are initialized in
1657 the assembler but I don't think an elf_flags_init field is
1658 written into the object */
1659 /* BFD_ASSERT (elf_flags_init (ibfd)); */
1660
1661 in_flags = elf_elfheader (ibfd)->e_flags;
1662 out_flags = elf_elfheader (obfd)->e_flags;
1663
1664 if (!elf_flags_init (obfd))
1665 {
1666 /* If the input is the default architecture then do not
1667 bother setting the flags for the output architecture,
1668 instead allow future merges to do this. If no future
1669 merges ever set these flags then they will retain their
1670 unitialised values, which surprise surprise, correspond
1671 to the default values. */
1672 if (bfd_get_arch_info (ibfd)->the_default)
1673 return true;
1674
1675 elf_flags_init (obfd) = true;
1676 elf_elfheader (obfd)->e_flags = in_flags;
1677
1678 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1679 && bfd_get_arch_info (obfd)->the_default)
1680 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1681
1682 return true;
1683 }
1684
1685 /* Check flag compatibility. */
1686 if (in_flags == out_flags)
1687 return true;
1688
1689 /* Complain about various flag mismatches. */
1690
1691 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
1692 _bfd_error_handler (_ ("\
1693 Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
1694 bfd_get_filename (ibfd),
1695 in_flags & EF_APCS_26 ? 26 : 32,
1696 bfd_get_filename (obfd),
1697 out_flags & EF_APCS_26 ? 26 : 32);
1698
1699 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
1700 _bfd_error_handler (_ ("\
1701 Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
1702 bfd_get_filename (ibfd),
1703 in_flags & EF_APCS_FLOAT ? _ ("float") : _ ("integer"),
1704 bfd_get_filename (obfd),
1705 out_flags & EF_APCS_26 ? _ ("float") : _ ("integer"));
1706
1707 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
1708 _bfd_error_handler (_ ("\
1709 Error: %s is compiled as position %s code, whereas %s is not"),
1710 bfd_get_filename (ibfd),
1711 in_flags & EF_PIC ? _ ("independent") : _ ("dependent"),
1712 bfd_get_filename (obfd));
1713
1714 /* Interworking mismatch is only a warning. */
1715 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
1716 {
1717 _bfd_error_handler (_ ("\
1718 Warning: %s %s interworking, whereas %s %s"),
1719 bfd_get_filename (ibfd),
1720 in_flags & EF_INTERWORK ? _ ("supports") : _ ("does not support"),
1721 bfd_get_filename (obfd),
1722 out_flags & EF_INTERWORK ? _ ("does not") : _ ("does"));
1723 return true;
1724 }
1725
1726 return false;
1727 }
1728
1729 /* Display the flags field */
1730 static boolean
1731 elf32_arm_print_private_bfd_data (abfd, ptr)
1732 bfd *abfd;
1733 PTR ptr;
1734 {
1735 FILE *file = (FILE *) ptr;
1736
1737 BFD_ASSERT (abfd != NULL && ptr != NULL);
1738
1739 /* Print normal ELF private data. */
1740 _bfd_elf_print_private_bfd_data (abfd, ptr);
1741
1742 /* Ignore init flag - it may not be set, despite the flags field containing valid data. */
1743
1744 /* xgettext:c-format */
1745 fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
1746
1747 if (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
1748 fprintf (file, _ (" [interworking enabled]"));
1749 else
1750 fprintf (file, _ (" [interworking not enabled]"));
1751
1752 if (elf_elfheader (abfd)->e_flags & EF_APCS_26)
1753 fprintf (file, _ (" [APCS-26]"));
1754 else
1755 fprintf (file, _ (" [APCS-32]"));
1756
1757 if (elf_elfheader (abfd)->e_flags & EF_APCS_FLOAT)
1758 fprintf (file, _ (" [floats passed in float registers]"));
1759 else
1760 fprintf (file, _ (" [floats passed in integer registers]"));
1761
1762 if (elf_elfheader (abfd)->e_flags & EF_PIC)
1763 fprintf (file, _ (" [position independent]"));
1764 else
1765 fprintf (file, _ (" [absolute position]"));
1766
1767 fputc ('\n', file);
1768
1769 return true;
1770 }
1771
1772 static int
1773 elf32_arm_get_symbol_type (elf_sym)
1774 Elf_Internal_Sym *elf_sym;
1775 {
1776 return ELF_ST_TYPE(elf_sym->st_info);
1777 }
1778
1779
1780 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
1781 #define TARGET_LITTLE_NAME "elf32-littlearm"
1782 #define TARGET_BIG_SYM bfd_elf32_bigarm_vec
1783 #define TARGET_BIG_NAME "elf32-bigarm"
1784 #define ELF_ARCH bfd_arch_arm
1785 #define ELF_MACHINE_CODE EM_ARM
1786
1787 #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
1788 #define elf_info_to_howto elf32_arm_info_to_howto
1789 #define elf_info_to_howto_rel 0
1790 #define elf_backend_relocate_section elf32_arm_relocate_section
1791 #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data
1792 #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data
1793 #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags
1794 #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data
1795 #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
1796 #define elf_backend_get_symbol_type elf32_arm_get_symbol_type
1797 #define elf_symbol_leading_char '_'
1798
1799 #include "elf32-target.h"