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