* elf-bfd.h (struct elf_size_info): Add swap_symbol_in field.
[platform/upstream/binutils.git] / bfd / elfarm-oabi.c
1 /* 32-bit ELF support for ARM old abi option.
2    Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4    This file is part of BFD, the Binary File Descriptor library.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #define OLD_ARM_ABI
21 #define bfd_elf32_arm_allocate_interworking_sections \
22         bfd_elf32_arm_oabi_allocate_interworking_sections
23 #define bfd_elf32_arm_get_bfd_for_interworking \
24         bfd_elf32_arm_oabi_get_bfd_for_interworking
25 #define bfd_elf32_arm_process_before_allocation \
26         bfd_elf32_arm_oabi_process_before_allocation
27 #define bfd_elf32_arm_add_glue_sections_to_bfd \
28         bfd_elf32_arm_oabi_add_glue_sections_to_bfd
29
30 #include "elf/arm.h"
31 #include "bfd.h"
32 #include "sysdep.h"
33 #include "libbfd.h"
34 #include "elf-bfd.h"
35
36 #ifndef NUM_ELEM
37 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
38 #endif
39
40 #define USE_RELA
41
42 #define TARGET_LITTLE_SYM               bfd_elf32_littlearm_oabi_vec
43 #define TARGET_LITTLE_NAME              "elf32-littlearm-oabi"
44 #define TARGET_BIG_SYM                  bfd_elf32_bigarm_oabi_vec
45 #define TARGET_BIG_NAME                 "elf32-bigarm-oabi"
46
47 #define elf_info_to_howto               elf32_arm_info_to_howto
48 #define elf_info_to_howto_rel           0
49
50 #define ARM_ELF_ABI_VERSION             0
51 #define ARM_ELF_OS_ABI_VERSION          0
52
53 static reloc_howto_type * find_howto                  PARAMS ((unsigned int));
54 static void               elf32_arm_info_to_howto     PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
55 static reloc_howto_type * elf32_arm_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
56
57 static reloc_howto_type elf32_arm_howto_table[] =
58   {
59     /* No relocation.  */
60     HOWTO (R_ARM_NONE,          /* type */
61            0,                   /* rightshift */
62            0,                   /* size (0 = byte, 1 = short, 2 = long) */
63            0,                   /* bitsize */
64            false,               /* pc_relative */
65            0,                   /* bitpos */
66            complain_overflow_dont,      /* complain_on_overflow */
67            bfd_elf_generic_reloc,       /* special_function */
68            "R_ARM_NONE",        /* name */
69            false,               /* partial_inplace */
70            0,                   /* src_mask */
71            0,                   /* dst_mask */
72            false),              /* pcrel_offset */
73
74     HOWTO (R_ARM_PC24,          /* type */
75            2,                   /* rightshift */
76            2,                   /* size (0 = byte, 1 = short, 2 = long) */
77            24,                  /* bitsize */
78            true,                /* pc_relative */
79            0,                   /* bitpos */
80            complain_overflow_signed,    /* complain_on_overflow */
81            bfd_elf_generic_reloc,       /* special_function */
82            "R_ARM_PC24",        /* name */
83            false,               /* partial_inplace */
84            0x00ffffff,          /* src_mask */
85            0x00ffffff,          /* dst_mask */
86            true),                       /* pcrel_offset */
87
88     /* 32 bit absolute.  */
89     HOWTO (R_ARM_ABS32,         /* type */
90            0,                   /* rightshift */
91            2,                   /* size (0 = byte, 1 = short, 2 = long) */
92            32,                  /* bitsize */
93            false,               /* pc_relative */
94            0,                   /* bitpos */
95            complain_overflow_bitfield,  /* complain_on_overflow */
96            bfd_elf_generic_reloc,       /* special_function */
97            "R_ARM_ABS32",       /* name */
98            false,               /* partial_inplace */
99            0xffffffff,          /* src_mask */
100            0xffffffff,          /* dst_mask */
101            false),              /* pcrel_offset */
102
103     /* Standard 32bit pc-relative reloc.  */
104     HOWTO (R_ARM_REL32,         /* type */
105            0,                   /* rightshift */
106            2,                   /* size (0 = byte, 1 = short, 2 = long) */
107            32,                  /* bitsize */
108            true,                /* pc_relative */
109            0,                   /* bitpos */
110            complain_overflow_bitfield,  /* complain_on_overflow */
111            bfd_elf_generic_reloc,       /* special_function */
112            "R_ARM_REL32",       /* name */
113            false,               /* partial_inplace */
114            0xffffffff,          /* src_mask */
115            0xffffffff,          /* dst_mask */
116            true),               /* pcrel_offset */
117
118     /* 8 bit absolute.  */
119     HOWTO (R_ARM_ABS8,          /* type */
120            0,                   /* rightshift */
121            0,                   /* size (0 = byte, 1 = short, 2 = long) */
122            8,                   /* bitsize */
123            false,               /* pc_relative */
124            0,                   /* bitpos */
125            complain_overflow_bitfield,  /* complain_on_overflow */
126            bfd_elf_generic_reloc,       /* special_function */
127            "R_ARM_ABS8",        /* name */
128            false,               /* partial_inplace */
129            0x000000ff,          /* src_mask */
130            0x000000ff,          /* dst_mask */
131            false),              /* pcrel_offset */
132
133     /* 16 bit absolute.  */
134     HOWTO (R_ARM_ABS16,         /* type */
135            0,                   /* rightshift */
136            1,                   /* size (0 = byte, 1 = short, 2 = long) */
137            16,                  /* bitsize */
138            false,               /* pc_relative */
139            0,                   /* bitpos */
140            complain_overflow_bitfield,  /* complain_on_overflow */
141            bfd_elf_generic_reloc,       /* special_function */
142            "R_ARM_ABS16",       /* name */
143            false,               /* partial_inplace */
144            0,                   /* src_mask */
145            0,                   /* dst_mask */
146            false),              /* pcrel_offset */
147
148     /* 12 bit absolute.  */
149     HOWTO (R_ARM_ABS12,         /* type */
150            0,                   /* rightshift */
151            2,                   /* size (0 = byte, 1 = short, 2 = long) */
152            12,                  /* bitsize */
153            false,               /* pc_relative */
154            0,                   /* bitpos */
155            complain_overflow_bitfield,  /* complain_on_overflow */
156            bfd_elf_generic_reloc,       /* special_function */
157            "R_ARM_ABS12",       /* name */
158            false,               /* partial_inplace */
159            0x000008ff,          /* src_mask */
160            0x000008ff,          /* dst_mask */
161            false),              /* pcrel_offset */
162
163     HOWTO (R_ARM_THM_ABS5,      /* type */
164            6,                   /* rightshift */
165            1,                   /* size (0 = byte, 1 = short, 2 = long) */
166            5,                   /* bitsize */
167            false,               /* pc_relative */
168            0,                   /* bitpos */
169            complain_overflow_bitfield,  /* complain_on_overflow */
170            bfd_elf_generic_reloc,       /* special_function */
171            "R_ARM_THM_ABS5",    /* name */
172            false,               /* partial_inplace */
173            0x000007e0,          /* src_mask */
174            0x000007e0,          /* dst_mask */
175            false),              /* pcrel_offset */
176
177     HOWTO (R_ARM_THM_PC22,      /* type */
178            1,                   /* rightshift */
179            2,                   /* size (0 = byte, 1 = short, 2 = long) */
180            23,                  /* bitsize */
181            true,                /* pc_relative */
182            0,                   /* bitpos */
183            complain_overflow_signed,    /* complain_on_overflow */
184            bfd_elf_generic_reloc,       /* special_function */
185            "R_ARM_THM_PC22",    /* name */
186            false,               /* partial_inplace */
187            0x07ff07ff,          /* src_mask */
188            0x07ff07ff,          /* dst_mask */
189            true),                       /* pcrel_offset */
190
191     HOWTO (R_ARM_SBREL32,               /* type */
192            0,                   /* rightshift */
193            0,                   /* size (0 = byte, 1 = short, 2 = long) */
194            0,                   /* bitsize */
195            false,               /* pc_relative */
196            0,                   /* bitpos */
197            complain_overflow_dont,/* complain_on_overflow */
198            bfd_elf_generic_reloc,       /* special_function */
199            "R_ARM_SBREL32",     /* name */
200            false,               /* partial_inplace */
201            0,                   /* src_mask */
202            0,                   /* dst_mask */
203            false),              /* pcrel_offset */
204
205     HOWTO (R_ARM_AMP_VCALL9,    /* type */
206            1,                   /* rightshift */
207            1,                   /* size (0 = byte, 1 = short, 2 = long) */
208            8,                   /* bitsize */
209            true,                /* pc_relative */
210            0,                   /* bitpos */
211            complain_overflow_signed,    /* complain_on_overflow */
212            bfd_elf_generic_reloc,       /* special_function */
213            "R_ARM_AMP_VCALL9",  /* name */
214            false,               /* partial_inplace */
215            0x000000ff,          /* src_mask */
216            0x000000ff,          /* dst_mask */
217            true),               /* pcrel_offset */
218
219     /* 12 bit pc relative.  */
220     HOWTO (R_ARM_THM_PC11,      /* type */
221            1,                   /* rightshift */
222            1,                   /* size (0 = byte, 1 = short, 2 = long) */
223            11,                  /* bitsize */
224            true,                /* pc_relative */
225            0,                   /* bitpos */
226            complain_overflow_signed,    /* complain_on_overflow */
227            bfd_elf_generic_reloc,       /* special_function */
228            "R_ARM_THM_PC11",    /* name */
229            false,               /* partial_inplace */
230            0x000007ff,          /* src_mask */
231            0x000007ff,          /* dst_mask */
232            true),               /* pcrel_offset */
233
234     /* 12 bit pc relative.  */
235     HOWTO (R_ARM_THM_PC9,       /* type */
236            1,                   /* rightshift */
237            1,                   /* size (0 = byte, 1 = short, 2 = long) */
238            8,                   /* bitsize */
239            true,                /* pc_relative */
240            0,                   /* bitpos */
241            complain_overflow_signed,    /* complain_on_overflow */
242            bfd_elf_generic_reloc,       /* special_function */
243            "R_ARM_THM_PC9",     /* name */
244            false,               /* partial_inplace */
245            0x000000ff,          /* src_mask */
246            0x000000ff,          /* dst_mask */
247            true),               /* pcrel_offset */
248
249     /* GNU extension to record C++ vtable hierarchy.  */
250     HOWTO (R_ARM_GNU_VTINHERIT, /* type */
251            0,                     /* rightshift */
252            2,                     /* size (0 = byte, 1 = short, 2 = long) */
253            0,                     /* bitsize */
254            false,                 /* pc_relative */
255            0,                     /* bitpos */
256            complain_overflow_dont, /* complain_on_overflow */
257            NULL,                  /* special_function */
258            "R_ARM_GNU_VTINHERIT", /* name */
259            false,                 /* partial_inplace */
260            0,                     /* src_mask */
261            0,                     /* dst_mask */
262            false),                /* pcrel_offset */
263
264     /* GNU extension to record C++ vtable member usage.  */
265     HOWTO (R_ARM_GNU_VTENTRY,     /* type */
266            0,                     /* rightshift */
267            2,                     /* size (0 = byte, 1 = short, 2 = long) */
268            0,                     /* bitsize */
269            false,                 /* pc_relative */
270            0,                     /* bitpos */
271            complain_overflow_dont, /* complain_on_overflow */
272            _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
273            "R_ARM_GNU_VTENTRY",   /* name */
274            false,                 /* partial_inplace */
275            0,                     /* src_mask */
276            0,                     /* dst_mask */
277            false),                /* pcrel_offset */
278
279     /* XXX - gap in index numbering here.  */
280
281     HOWTO (R_ARM_PLT32,         /* type */
282            2,                   /* rightshift */
283            2,                   /* size (0 = byte, 1 = short, 2 = long) */
284            26,                  /* bitsize */
285            true,                /* pc_relative */
286            0,                   /* bitpos */
287            complain_overflow_bitfield,/* complain_on_overflow */
288            bfd_elf_generic_reloc, /* special_function */
289            "R_ARM_PLT32",       /* name */
290            true,                /* partial_inplace */
291            0x00ffffff,          /* src_mask */
292            0x00ffffff,          /* dst_mask */
293            true),                       /* pcrel_offset */
294
295     /* XXX - gap in index numbering here.  */
296
297     HOWTO (R_ARM_RREL32,        /* type */
298            0,                   /* rightshift */
299            0,                   /* size (0 = byte, 1 = short, 2 = long) */
300            0,                   /* bitsize */
301            false,               /* pc_relative */
302            0,                   /* bitpos */
303            complain_overflow_dont,      /* complain_on_overflow */
304            bfd_elf_generic_reloc,       /* special_function */
305            "R_ARM_RREL32",      /* name */
306            false,               /* partial_inplace */
307            0,                   /* src_mask */
308            0,                   /* dst_mask */
309            false),              /* pcrel_offset */
310
311     HOWTO (R_ARM_RABS32,        /* type */
312            0,                   /* rightshift */
313            0,                   /* size (0 = byte, 1 = short, 2 = long) */
314            0,                   /* bitsize */
315            false,               /* pc_relative */
316            0,                   /* bitpos */
317            complain_overflow_dont,      /* complain_on_overflow */
318            bfd_elf_generic_reloc,       /* special_function */
319            "R_ARM_RABS32",      /* name */
320            false,               /* partial_inplace */
321            0,                   /* src_mask */
322            0,                   /* dst_mask */
323            false),              /* pcrel_offset */
324
325     HOWTO (R_ARM_RPC24,         /* type */
326            0,                   /* rightshift */
327            0,                   /* size (0 = byte, 1 = short, 2 = long) */
328            0,                   /* bitsize */
329            false,               /* pc_relative */
330            0,                   /* bitpos */
331            complain_overflow_dont,      /* complain_on_overflow */
332            bfd_elf_generic_reloc,       /* special_function */
333            "R_ARM_RPC24",       /* name */
334            false,               /* partial_inplace */
335            0,                   /* src_mask */
336            0,                   /* dst_mask */
337            false),              /* pcrel_offset */
338
339     HOWTO (R_ARM_RBASE,         /* type */
340            0,                   /* rightshift */
341            0,                   /* size (0 = byte, 1 = short, 2 = long) */
342            0,                   /* bitsize */
343            false,               /* pc_relative */
344            0,                   /* bitpos */
345            complain_overflow_dont,      /* complain_on_overflow */
346            bfd_elf_generic_reloc,       /* special_function */
347            "R_ARM_RBASE",       /* name */
348            false,               /* partial_inplace */
349            0,                   /* src_mask */
350            0,                   /* dst_mask */
351            false)               /* pcrel_offset */
352   };
353
354 /* Locate a reloc in the howto table.  This function must be used
355    when the entry number is is > R_ARM_GNU_VTINHERIT.  */
356
357 static reloc_howto_type *
358 find_howto (r_type)
359      unsigned int r_type;
360 {
361   int i;
362
363   for (i = NUM_ELEM (elf32_arm_howto_table); i--;)
364     if (elf32_arm_howto_table [i].type == r_type)
365       return elf32_arm_howto_table + i;
366
367   return NULL;
368 }
369
370 static void
371 elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc)
372      bfd *abfd ATTRIBUTE_UNUSED;
373      arelent *bfd_reloc;
374      Elf32_Internal_Rela *elf_reloc;
375 {
376   unsigned int r_type;
377
378   r_type = ELF32_R_TYPE (elf_reloc->r_info);
379
380   if (r_type <= R_ARM_GNU_VTINHERIT)
381     bfd_reloc->howto = & elf32_arm_howto_table[r_type];
382   else
383     bfd_reloc->howto = find_howto (r_type);
384 }
385
386 struct elf32_arm_reloc_map
387   {
388     bfd_reloc_code_real_type bfd_reloc_val;
389     unsigned char elf_reloc_val;
390   };
391
392 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
393   {
394     {BFD_RELOC_NONE,                 R_ARM_NONE },
395     {BFD_RELOC_ARM_PCREL_BRANCH,     R_ARM_PC24 },
396     {BFD_RELOC_32,                   R_ARM_ABS32 },
397     {BFD_RELOC_32_PCREL,             R_ARM_REL32 },
398     {BFD_RELOC_8,                    R_ARM_ABS8 },
399     {BFD_RELOC_16,                   R_ARM_ABS16 },
400     {BFD_RELOC_ARM_OFFSET_IMM,       R_ARM_ABS12 },
401     {BFD_RELOC_ARM_THUMB_OFFSET,     R_ARM_THM_ABS5 },
402     {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22 },
403     {BFD_RELOC_NONE,                 R_ARM_SBREL32 },
404     {BFD_RELOC_NONE,                 R_ARM_AMP_VCALL9 },
405     {BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_PC11 },
406     {BFD_RELOC_THUMB_PCREL_BRANCH9,  R_ARM_THM_PC9 },
407     {BFD_RELOC_VTABLE_INHERIT,       R_ARM_GNU_VTINHERIT },
408     {BFD_RELOC_VTABLE_ENTRY,         R_ARM_GNU_VTENTRY }
409   };
410
411 static reloc_howto_type *
412 elf32_arm_reloc_type_lookup (abfd, code)
413      bfd * abfd ATTRIBUTE_UNUSED;
414      bfd_reloc_code_real_type code;
415 {
416   unsigned int i;
417
418   for (i = NUM_ELEM (elf32_arm_reloc_map); i--;)
419     if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
420       return & elf32_arm_howto_table [elf32_arm_reloc_map[i].elf_reloc_val];
421
422   if (code == BFD_RELOC_ARM_PLT32)
423     return find_howto (R_ARM_PLT32);
424
425   return NULL;
426 }
427
428 #include "elf32-arm.h"