xref: /openbsd/gnu/usr.bin/binutils/bfd/elfarm-oabi.c (revision d2201f2f)
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 *
find_howto(r_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
elf32_arm_info_to_howto(abfd,bfd_reloc,elf_reloc)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 *
elf32_arm_reloc_type_lookup(abfd,code)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"
427