* config/tc-i386.c (i386_operand): Fix typo in last patch.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
CommitLineData
efaa65c9
CM
1/* 32-bit ELF support for ARM
2 Copyright 1993, 1995, 1998 Free Software Foundation, Inc.
3
2c3c46ad 4 This file is part of BFD, the Binary File Descriptor library.
efaa65c9 5
2c3c46ad
CM
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.
efaa65c9 10
2c3c46ad
CM
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.
efaa65c9 15
2c3c46ad
CM
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. */
efaa65c9
CM
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
2c3c46ad
CM
27typedef unsigned long int insn32;
28typedef unsigned short int insn16;
29
efaa65c9 30static reloc_howto_type *elf32_arm_reloc_type_lookup
2c3c46ad 31 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
efaa65c9
CM
32static void elf32_arm_info_to_howto
33 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
0e7361bc
NC
34static boolean elf32_arm_set_private_flags
35 PARAMS ((bfd *, flagword));
36static boolean elf32_arm_copy_private_bfd_data
37 PARAMS ((bfd *, bfd *));
38static boolean elf32_arm_merge_private_bfd_data
39 PARAMS ((bfd *, bfd *));
40static boolean elf32_arm_print_private_bfd_data
41 PARAMS ((bfd *, PTR));
bb3b4377
CM
42static int elf32_arm_get_symbol_type
43 PARAMS (( Elf_Internal_Sym *));
2c3c46ad
CM
44static struct bfd_link_hash_table *elf32_arm_link_hash_table_create
45 PARAMS ((bfd *));
46
47
48static insn32 insert_thumb_branch
49 PARAMS ((insn32, int));
50static struct elf_link_hash_entry *find_thumb_glue
51 PARAMS ((struct bfd_link_info *, CONST char *, bfd *));
52static struct elf_link_hash_entry *find_arm_glue
53 PARAMS ((struct bfd_link_info *, CONST char *, bfd *));
54static void record_arm_to_thumb_glue
55 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
56static 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 */
78struct 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
98static struct bfd_link_hash_table *
99elf32_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
123static struct elf_link_hash_entry *
124find_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
157static struct elf_link_hash_entry *
158find_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
202static const insn32 a2t1_ldr_insn = 0xe59fc000;
203static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
204static 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
225static const insn16 t2a1_bx_pc_insn = 0x4778;
226static const insn16 t2a2_noop_insn = 0x46c0;
227static const insn32 t2a3_b_insn = 0xea000000;
228
229static const insn16 t2a1_push_insn = 0xb540;
230static const insn16 t2a2_ldr_insn = 0x4e03;
231static const insn16 t2a3_mov_insn = 0x46fe;
232static const insn16 t2a4_bx_insn = 0x4730;
233static const insn32 t2a5_pop_insn = 0xe8bd4040;
234static const insn32 t2a6_bx_insn = 0xe12fff1e;
235
236boolean
237bfd_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
283static void
284record_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
338static void
339record_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;
bb3b4377 348 char bind;
2c3c46ad
CM
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. */
bb3b4377
CM
381 bind = ELF_ST_BIND (myh->type);
382 myh->type = ELF_ST_INFO (bind, STT_ARM_TFUNC);
2c3c46ad
CM
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 */
414boolean
415bfd_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
469boolean
470bfd_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
2c3c46ad
CM
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 {
2c3c46ad
CM
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
bb3b4377 516 BFD_ASSERT (irel != 0);
2c3c46ad
CM
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
bb3b4377 601 if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC)
2c3c46ad
CM
602 record_arm_to_thumb_glue (link_info, h);
603 break;
604
605 case R_ARM_THM_PC22:
606
bb3b4377
CM
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. */
2c3c46ad 610
bb3b4377
CM
611 if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC)
612 record_thumb_to_arm_glue (link_info, h);
2c3c46ad
CM
613 break;
614
615 default:
616 break;
617 }
618 }
619 }
620
621 return true;
622error_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}
efaa65c9
CM
632
633#define USE_RELA
634#define TARGET_UNDERSCORE '_'
635
636static reloc_howto_type elf32_arm_howto_table[] =
637{
638 /* No relocation */
2c3c46ad
CM
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 */
efaa65c9
CM
666
667 /* 32 bit absolute */
2c3c46ad
CM
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 */
efaa65c9
CM
681
682 /* standard 32bit pc-relative reloc */
2c3c46ad
CM
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 */
efaa65c9
CM
696
697 /* 8 bit absolute */
2c3c46ad
CM
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 */
efaa65c9
CM
711
712 /* 16 bit absolute */
2c3c46ad
CM
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 */
efaa65c9
CM
726
727 /* 12 bit absolute */
2c3c46ad
CM
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 */
efaa65c9
CM
797
798 /* 12 bit pc relative */
2c3c46ad
CM
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 */
efaa65c9
CM
812
813 /* 12 bit pc relative */
2c3c46ad
CM
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 */
efaa65c9
CM
827
828/* FILL ME IN (#13-249) */
829
830
2c3c46ad
CM
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 */
efaa65c9
CM
886
887};
888struct elf32_arm_reloc_map
2c3c46ad
CM
889 {
890 unsigned char bfd_reloc_val;
891 unsigned char elf_reloc_val;
892 };
efaa65c9
CM
893
894static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
895{
2c3c46ad
CM
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,}
efaa65c9
CM
909};
910
911static reloc_howto_type *
912elf32_arm_reloc_type_lookup (abfd, code)
913 bfd *abfd;
914 bfd_reloc_code_real_type code;
915{
916 unsigned int i;
2c3c46ad 917
efaa65c9 918 for (i = 0;
2c3c46ad 919 i < sizeof (elf32_arm_reloc_map) / sizeof (struct elf32_arm_reloc_map);
efaa65c9
CM
920 i++)
921 {
922 if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
2c3c46ad 923 return &elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val];
efaa65c9 924 }
2c3c46ad 925
efaa65c9
CM
926 return NULL;
927}
928
929static void
930elf32_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
2c3c46ad
CM
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
974static insn32
975insert_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}
774852e9
NC
1000
1001/* Thumb code calling an ARM function */
1002int
2c3c46ad
CM
1003elf32_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{
2c3c46ad
CM
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 {
774852e9
NC
1043 if (sym_sec != NULL
1044 && sym_sec->owner != NULL
2c3c46ad
CM
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}
774852e9
NC
1096
1097/* Arm code calling a Thumb function */
1098int
2c3c46ad
CM
1099elf32_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{
2c3c46ad
CM
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 {
774852e9
NC
1138 if (sym_sec != NULL
1139 && sym_sec->owner != NULL
2c3c46ad
CM
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}
774852e9 1183
efaa65c9
CM
1184/* Perform a relocation as part of a final link. */
1185static bfd_reloc_status_type
1186elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
2c3c46ad
CM
1187 input_section, contents, offset, value,
1188 addend, info, sym_sec, sym_name, sym_flags)
efaa65c9
CM
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;
774852e9 1199 const char *sym_name;
a17e14c1 1200 unsigned char sym_flags;
efaa65c9
CM
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:
2c3c46ad
CM
1212 /* Arm B/BL instruction */
1213
1214 /* check for arm calling thumb function */
bb3b4377 1215 if (sym_flags == STT_ARM_TFUNC)
2c3c46ad
CM
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;
efaa65c9 1227
efaa65c9
CM
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;
bb3b4377 1235 if (sym_flags == STT_ARM_TFUNC)
2c3c46ad 1236 value |= 1;
efaa65c9
CM
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
2c3c46ad 1242 + input_section->output_offset);
efaa65c9
CM
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;
2c3c46ad 1250
efaa65c9 1251 if ((long) value > 0x7f || (long) value < -0x80)
2c3c46ad
CM
1252 return bfd_reloc_overflow;
1253
efaa65c9
CM
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)
2c3c46ad
CM
1261 return bfd_reloc_overflow;
1262
efaa65c9
CM
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)
2c3c46ad 1272 return bfd_reloc_overflow;
efaa65c9
CM
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)
2c3c46ad 1283 return bfd_reloc_overflow;
efaa65c9
CM
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;
efaa65c9 1288
efaa65c9 1289
efaa65c9 1290 case R_ARM_THM_PC22:
2c3c46ad 1291 /* thumb BL (branch long instruction). */
efaa65c9 1292 {
2c3c46ad
CM
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
bb3b4377
CM
1304 /* If it's not a call to thumb, assume call to arm */
1305 if (sym_flags != STT_ARM_TFUNC)
2c3c46ad
CM
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);
efaa65c9
CM
1370 }
1371 break;
2c3c46ad 1372
efaa65c9 1373 case R_ARM_SBREL32:
a17e14c1 1374 return bfd_reloc_notsupported;
efaa65c9
CM
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}
774852e9
NC
1401
1402
efaa65c9
CM
1403/* Relocate an ARM ELF section. */
1404static boolean
1405elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
2c3c46ad 1406 contents, relocs, local_syms, local_sections)
efaa65c9
CM
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;
774852e9 1419 const char *name;
efaa65c9
CM
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
2c3c46ad
CM
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. */
efaa65c9
CM
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 {
2c3c46ad
CM
1490 if (!((*info->callbacks->undefined_symbol)
1491 (info, h->root.root.string, input_bfd,
1492 input_section, rel->r_offset)))
efaa65c9
CM
1493 return false;
1494 relocation = 0;
1495 }
1496 }
1497
774852e9
NC
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
efaa65c9 1508 r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
2c3c46ad
CM
1509 input_section,
1510 contents, rel->r_offset,
1511 relocation, rel->r_addend,
774852e9 1512 info, sec, name,
bb3b4377 1513 (h ? ELF_ST_TYPE (h->type) : ELF_ST_TYPE (sym->st_info)));
efaa65c9
CM
1514
1515
1516 if (r != bfd_reloc_ok)
1517 {
2c3c46ad 1518 const char *msg = (const char *) 0;
efaa65c9 1519
efaa65c9
CM
1520 switch (r)
1521 {
1522 case bfd_reloc_overflow:
2c3c46ad
CM
1523 if (!((*info->callbacks->reloc_overflow)
1524 (info, name, howto->name, (bfd_vma) 0,
1525 input_bfd, input_section, rel->r_offset)))
efaa65c9
CM
1526 return false;
1527 break;
1528
1529 case bfd_reloc_undefined:
2c3c46ad
CM
1530 if (!((*info->callbacks->undefined_symbol)
1531 (info, name, input_bfd, input_section,
1532 rel->r_offset)))
efaa65c9
CM
1533 return false;
1534 break;
1535
1536 case bfd_reloc_outofrange:
2c3c46ad 1537 msg = _ ("internal error: out of range error");
efaa65c9
CM
1538 goto common_error;
1539
1540 case bfd_reloc_notsupported:
2c3c46ad 1541 msg = _ ("internal error: unsupported relocation error");
efaa65c9
CM
1542 goto common_error;
1543
1544 case bfd_reloc_dangerous:
2c3c46ad 1545 msg = _ ("internal error: dangerous error");
efaa65c9
CM
1546 goto common_error;
1547
1548 default:
2c3c46ad 1549 msg = _ ("internal error: unknown error");
efaa65c9
CM
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
0e7361bc
NC
1565/* Function to keep ARM specific flags in the ELF header. */
1566static boolean
1567elf32_arm_set_private_flags (abfd, flags)
2c3c46ad 1568 bfd *abfd;
0e7361bc
NC
1569 flagword flags;
1570{
1571 if (elf_flags_init (abfd)
1572 && elf_elfheader (abfd)->e_flags != flags)
1573 {
1574 if (flags & EF_INTERWORK)
2c3c46ad 1575 _bfd_error_handler (_ ("\
0e7361bc
NC
1576Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
1577 bfd_get_filename (abfd));
1578 else
2c3c46ad 1579 _bfd_error_handler (_ ("\
0e7361bc 1580Warning: Clearing the interwork flag of %s due to outside request"),
2c3c46ad 1581 bfd_get_filename (abfd));
0e7361bc
NC
1582 }
1583 else
1584 {
1585 elf_elfheader (abfd)->e_flags = flags;
1586 elf_flags_init (abfd) = true;
1587 }
2c3c46ad 1588
0e7361bc
NC
1589 return true;
1590}
1591
1592/* Copy backend specific data from one object module to another */
1593static boolean
1594elf32_arm_copy_private_bfd_data (ibfd, obfd)
2c3c46ad
CM
1595 bfd *ibfd;
1596 bfd *obfd;
0e7361bc
NC
1597{
1598 flagword in_flags;
1599 flagword out_flags;
2c3c46ad
CM
1600
1601 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
0e7361bc
NC
1602 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1603 return true;
1604
2c3c46ad 1605 in_flags = elf_elfheader (ibfd)->e_flags;
0e7361bc 1606 out_flags = elf_elfheader (obfd)->e_flags;
2c3c46ad
CM
1607
1608 if (elf_flags_init (obfd) && in_flags != out_flags)
0e7361bc
NC
1609 {
1610 /* Cannot mix PIC and non-PIC code. */
1611 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
1612 return false;
2c3c46ad 1613
0e7361bc
NC
1614 /* Cannot mix APCS26 and APCS32 code. */
1615 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
1616 return false;
2c3c46ad 1617
0e7361bc
NC
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
2c3c46ad 1623 then turn off the interworking bit. */
0e7361bc
NC
1624 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
1625 {
1626 if (out_flags & EF_INTERWORK)
2c3c46ad 1627 _bfd_error_handler (_ ("\
0e7361bc 1628Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
2c3c46ad
CM
1629 bfd_get_filename (obfd), bfd_get_filename (ibfd));
1630
1631 in_flags &= ~EF_INTERWORK;
0e7361bc
NC
1632 }
1633 }
1634
1635 elf_elfheader (obfd)->e_flags = in_flags;
1636 elf_flags_init (obfd) = true;
2c3c46ad 1637
0e7361bc
NC
1638 return true;
1639}
1640
1641/* Merge backend specific data from an object file to the output
1642 object file when linking. */
1643static boolean
1644elf32_arm_merge_private_bfd_data (ibfd, obfd)
2c3c46ad
CM
1645 bfd *ibfd;
1646 bfd *obfd;
0e7361bc
NC
1647{
1648 flagword out_flags;
1649 flagword in_flags;
1650
2c3c46ad 1651 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
0e7361bc
NC
1652 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1653 return true;
1654
1655 /* The input BFD must have had its flags initialised. */
a17e14c1
CM
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)); */
2c3c46ad
CM
1660
1661 in_flags = elf_elfheader (ibfd)->e_flags;
0e7361bc
NC
1662 out_flags = elf_elfheader (obfd)->e_flags;
1663
2c3c46ad 1664 if (!elf_flags_init (obfd))
0e7361bc
NC
1665 {
1666 /* If the input is the default architecture then do not
2c3c46ad
CM
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. */
0e7361bc
NC
1672 if (bfd_get_arch_info (ibfd)->the_default)
1673 return true;
2c3c46ad 1674
0e7361bc
NC
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. */
2c3c46ad 1690
0e7361bc 1691 if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
2c3c46ad 1692 _bfd_error_handler (_ ("\
0e7361bc
NC
1693Error: %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);
2c3c46ad 1698
0e7361bc 1699 if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT))
2c3c46ad 1700 _bfd_error_handler (_ ("\
0e7361bc
NC
1701Error: %s passes floats in %s registers, whereas %s passes them in %s registers"),
1702 bfd_get_filename (ibfd),
2c3c46ad 1703 in_flags & EF_APCS_FLOAT ? _ ("float") : _ ("integer"),
0e7361bc 1704 bfd_get_filename (obfd),
2c3c46ad
CM
1705 out_flags & EF_APCS_26 ? _ ("float") : _ ("integer"));
1706
0e7361bc 1707 if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
2c3c46ad 1708 _bfd_error_handler (_ ("\
0e7361bc
NC
1709Error: %s is compiled as position %s code, whereas %s is not"),
1710 bfd_get_filename (ibfd),
2c3c46ad 1711 in_flags & EF_PIC ? _ ("independent") : _ ("dependent"),
0e7361bc
NC
1712 bfd_get_filename (obfd));
1713
1714 /* Interworking mismatch is only a warning. */
1715 if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK))
1716 {
2c3c46ad 1717 _bfd_error_handler (_ ("\
0e7361bc
NC
1718Warning: %s %s interworking, whereas %s %s"),
1719 bfd_get_filename (ibfd),
2c3c46ad 1720 in_flags & EF_INTERWORK ? _ ("supports") : _ ("does not support"),
0e7361bc 1721 bfd_get_filename (obfd),
2c3c46ad 1722 out_flags & EF_INTERWORK ? _ ("does not") : _ ("does"));
0e7361bc
NC
1723 return true;
1724 }
1725
1726 return false;
1727}
1728
1729/* Display the flags field */
1730static boolean
1731elf32_arm_print_private_bfd_data (abfd, ptr)
2c3c46ad
CM
1732 bfd *abfd;
1733 PTR ptr;
0e7361bc 1734{
2c3c46ad
CM
1735 FILE *file = (FILE *) ptr;
1736
0e7361bc
NC
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. */
2c3c46ad 1743
0e7361bc 1744 /* xgettext:c-format */
2c3c46ad 1745 fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
0e7361bc
NC
1746
1747 if (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
2c3c46ad 1748 fprintf (file, _ (" [interworking enabled]"));
0e7361bc 1749 else
2c3c46ad
CM
1750 fprintf (file, _ (" [interworking not enabled]"));
1751
0e7361bc 1752 if (elf_elfheader (abfd)->e_flags & EF_APCS_26)
2c3c46ad 1753 fprintf (file, _ (" [APCS-26]"));
0e7361bc 1754 else
2c3c46ad
CM
1755 fprintf (file, _ (" [APCS-32]"));
1756
0e7361bc 1757 if (elf_elfheader (abfd)->e_flags & EF_APCS_FLOAT)
2c3c46ad 1758 fprintf (file, _ (" [floats passed in float registers]"));
0e7361bc 1759 else
2c3c46ad
CM
1760 fprintf (file, _ (" [floats passed in integer registers]"));
1761
0e7361bc 1762 if (elf_elfheader (abfd)->e_flags & EF_PIC)
2c3c46ad 1763 fprintf (file, _ (" [position independent]"));
0e7361bc 1764 else
2c3c46ad
CM
1765 fprintf (file, _ (" [absolute position]"));
1766
0e7361bc 1767 fputc ('\n', file);
2c3c46ad 1768
0e7361bc
NC
1769 return true;
1770}
1771
bb3b4377
CM
1772static int
1773elf32_arm_get_symbol_type (elf_sym)
1774 Elf_Internal_Sym *elf_sym;
1775{
1776 return ELF_ST_TYPE(elf_sym->st_info);
1777}
1778
0e7361bc 1779
efaa65c9
CM
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
0e7361bc
NC
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
2c3c46ad 1795#define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
bb3b4377 1796#define elf_backend_get_symbol_type elf32_arm_get_symbol_type
efaa65c9
CM
1797#define elf_symbol_leading_char '_'
1798
1799#include "elf32-target.h"
This page took 0.099698 seconds and 4 git commands to generate.