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