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