1 /* 32-bit ELF support for ARM new 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 #include "elf/arm.h"
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25 
26 #ifndef NUM_ELEM
27 #define NUM_ELEM(a)  (sizeof (a) / (sizeof (a)[0]))
28 #endif
29 
30 #define USE_REL	1
31 
QhullVertex(const Qhull & q)32 #define TARGET_LITTLE_SYM               bfd_elf32_littlearm_vec
33 #define TARGET_LITTLE_NAME              "elf32-littlearm"
34 #define TARGET_BIG_SYM                  bfd_elf32_bigarm_vec
35 #define TARGET_BIG_NAME                 "elf32-bigarm"
36 
37 #define elf_info_to_howto               0
38 #define elf_info_to_howto_rel           elf32_arm_info_to_howto
39 
40 #define ARM_ELF_ABI_VERSION		0
41 #define ARM_ELF_OS_ABI_VERSION		ELFOSABI_ARM
42 
43 static reloc_howto_type * elf32_arm_reloc_type_lookup
44   PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
45 static bfd_boolean elf32_arm_nabi_grok_prstatus
46   PARAMS ((bfd *abfd, Elf_Internal_Note *note));
47 static bfd_boolean elf32_arm_nabi_grok_psinfo
48   PARAMS ((bfd *abfd, Elf_Internal_Note *note));
neighborFacets() const49 
50 /* Note: code such as elf32_arm_reloc_type_lookup expect to use e.g.
51    R_ARM_PC24 as an index into this, and find the R_ARM_PC24 HOWTO
52    in that slot.  */
53 
54 static reloc_howto_type elf32_arm_howto_table[] =
55 {
56   /* No relocation */
57   HOWTO (R_ARM_NONE,		/* type */
58 	 0,			/* rightshift */
59 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
60 	 0,			/* bitsize */
61 	 FALSE,			/* pc_relative */
62 	 0,			/* bitpos */
63 	 complain_overflow_dont,/* complain_on_overflow */
64 	 bfd_elf_generic_reloc,	/* special_function */
65 	 "R_ARM_NONE",		/* name */
66 	 FALSE,			/* partial_inplace */
67 	 0,			/* src_mask */
68 	 0,			/* dst_mask */
69 	 FALSE),		/* pcrel_offset */
70 
71   HOWTO (R_ARM_PC24,		/* type */
72 	 2,			/* rightshift */
73 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
74 	 24,			/* bitsize */
75 	 TRUE,			/* pc_relative */
76 	 0,			/* bitpos */
77 	 complain_overflow_signed,/* complain_on_overflow */
78 	 bfd_elf_generic_reloc,	/* special_function */
79 	 "R_ARM_PC24",		/* name */
80 	 FALSE,			/* partial_inplace */
81 	 0x00ffffff,		/* src_mask */
82 	 0x00ffffff,		/* dst_mask */
83 	 TRUE),			/* pcrel_offset */
84 
85   /* 32 bit absolute */
86   HOWTO (R_ARM_ABS32,		/* type */
87 	 0,			/* rightshift */
88 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
89 	 32,			/* bitsize */
90 	 FALSE,			/* pc_relative */
91 	 0,			/* bitpos */
92 	 complain_overflow_bitfield,/* complain_on_overflow */
93 	 bfd_elf_generic_reloc,	/* special_function */
94 	 "R_ARM_ABS32",		/* name */
95 	 FALSE,			/* partial_inplace */
96 	 0xffffffff,		/* src_mask */
97 	 0xffffffff,		/* dst_mask */
98 	 FALSE),		/* pcrel_offset */
99 
100   /* standard 32bit pc-relative reloc */
101   HOWTO (R_ARM_REL32,		/* type */
102 	 0,			/* rightshift */
103 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
104 	 32,			/* bitsize */
105 	 TRUE,			/* pc_relative */
106 	 0,			/* bitpos */
107 	 complain_overflow_bitfield,/* complain_on_overflow */
108 	 bfd_elf_generic_reloc,	/* special_function */
109 	 "R_ARM_REL32",		/* name */
110 	 FALSE,			/* partial_inplace */
111 	 0xffffffff,		/* src_mask */
112 	 0xffffffff,		/* dst_mask */
113 	 TRUE),			/* pcrel_offset */
114 
115   /* 8 bit absolute */
116   HOWTO (R_ARM_PC13,		/* type */
117 	 0,			/* rightshift */
118 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
119 	 8,			/* bitsize */
120 	 FALSE,			/* pc_relative */
121 	 0,			/* bitpos */
122 	 complain_overflow_bitfield,/* complain_on_overflow */
123 	 bfd_elf_generic_reloc,	/* special_function */
124 	 "R_ARM_PC13",		/* name */
125 	 FALSE,			/* partial_inplace */
126 	 0x000000ff,		/* src_mask */
127 	 0x000000ff,		/* dst_mask */
128 	 FALSE),		/* pcrel_offset */
129 
130    /* 16 bit absolute */
131   HOWTO (R_ARM_ABS16,		/* type */
132 	 0,			/* rightshift */
133 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
134 	 16,			/* bitsize */
135 	 FALSE,			/* pc_relative */
136 	 0,			/* bitpos */
137 	 complain_overflow_bitfield,/* complain_on_overflow */
138 	 bfd_elf_generic_reloc,	/* special_function */
139 	 "R_ARM_ABS16",		/* name */
140 	 FALSE,			/* partial_inplace */
141 	 0x0000ffff,		/* src_mask */
142 	 0x0000ffff,		/* dst_mask */
143 	 FALSE),		/* pcrel_offset */
144 
145   /* 12 bit absolute */
146   HOWTO (R_ARM_ABS12,		/* type */
147 	 0,			/* rightshift */
148 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
149 	 12,			/* bitsize */
150 	 FALSE,			/* pc_relative */
151 	 0,			/* bitpos */
152 	 complain_overflow_bitfield,/* complain_on_overflow */
153 	 bfd_elf_generic_reloc,	/* special_function */
154 	 "R_ARM_ABS12",		/* name */
155 	 FALSE,			/* partial_inplace */
156 	 0x000008ff,		/* src_mask */
157 	 0x000008ff,		/* dst_mask */
158 	 FALSE),		/* pcrel_offset */
159 
160   HOWTO (R_ARM_THM_ABS5,	/* type */
161 	 6,			/* rightshift */
162 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
163 	 5,			/* bitsize */
164 	 FALSE,			/* pc_relative */
165 	 0,			/* bitpos */
166 	 complain_overflow_bitfield,/* complain_on_overflow */
167 	 bfd_elf_generic_reloc,	/* special_function */
168 	 "R_ARM_THM_ABS5",	/* name */
169 	 FALSE,			/* partial_inplace */
170 	 0x000007e0,		/* src_mask */
171 	 0x000007e0,		/* dst_mask */
172 	 FALSE),		/* pcrel_offset */
173 
174   /* 8 bit absolute */
175   HOWTO (R_ARM_ABS8,		/* type */
176 	 0,			/* rightshift */
177 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
178 	 8,			/* bitsize */
179 	 FALSE,			/* pc_relative */
180 	 0,			/* bitpos */
181 	 complain_overflow_bitfield,/* complain_on_overflow */
182 	 bfd_elf_generic_reloc,	/* special_function */
183 	 "R_ARM_ABS8",		/* name */
184 	 FALSE,			/* partial_inplace */
185 	 0x000000ff,		/* src_mask */
186 	 0x000000ff,		/* dst_mask */
187 	 FALSE),		/* 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_THM_PC22,	/* type */
204 	 1,			/* rightshift */
205 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
206 	 23,			/* 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_THM_PC22",	/* name */
212 	 FALSE,			/* partial_inplace */
213 	 0x07ff07ff,		/* src_mask */
214 	 0x07ff07ff,		/* dst_mask */
215 	 TRUE),			/* pcrel_offset */
216 
217   HOWTO (R_ARM_THM_PC8,	        /* type */
218 	 1,			/* rightshift */
219 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
220 	 8,			/* bitsize */
221 	 TRUE,			/* pc_relative */
222 	 0,			/* bitpos */
223 	 complain_overflow_signed,/* complain_on_overflow */
224 	 bfd_elf_generic_reloc,	/* special_function */
225 	 "R_ARM_THM_PC8",	/* name */
226 	 FALSE,			/* partial_inplace */
227 	 0x000000ff,		/* src_mask */
228 	 0x000000ff,		/* dst_mask */
229 	 TRUE),			/* pcrel_offset */
230 
231   HOWTO (R_ARM_AMP_VCALL9,	/* type */
232 	 1,			/* rightshift */
233 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
234 	 8,			/* bitsize */
235 	 TRUE,			/* pc_relative */
236 	 0,			/* bitpos */
237 	 complain_overflow_signed,/* complain_on_overflow */
238 	 bfd_elf_generic_reloc,	/* special_function */
239 	 "R_ARM_AMP_VCALL9",	/* name */
240 	 FALSE,			/* partial_inplace */
241 	 0x000000ff,		/* src_mask */
242 	 0x000000ff,		/* dst_mask */
243 	 TRUE),			/* pcrel_offset */
244 
245   HOWTO (R_ARM_SWI24,		/* type */
246 	 0,			/* rightshift */
247 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
248 	 0,			/* bitsize */
249 	 FALSE,			/* pc_relative */
250 	 0,			/* bitpos */
251 	 complain_overflow_signed,/* complain_on_overflow */
252 	 bfd_elf_generic_reloc,	/* special_function */
253 	 "R_ARM_SWI24",		/* name */
254 	 FALSE,			/* partial_inplace */
255 	 0x00000000,		/* src_mask */
256 	 0x00000000,		/* dst_mask */
257 	 FALSE),		/* pcrel_offset */
258 
259   HOWTO (R_ARM_THM_SWI8,	/* type */
260 	 0,			/* rightshift */
261 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
262 	 0,			/* bitsize */
263 	 FALSE,			/* pc_relative */
264 	 0,			/* bitpos */
265 	 complain_overflow_signed,/* complain_on_overflow */
266 	 bfd_elf_generic_reloc,	/* special_function */
267 	 "R_ARM_SWI8",		/* name */
268 	 FALSE,			/* partial_inplace */
269 	 0x00000000,		/* src_mask */
270 	 0x00000000,		/* dst_mask */
271 	 FALSE),		/* pcrel_offset */
272 
273   /* BLX instruction for the ARM.  */
274   HOWTO (R_ARM_XPC25,		/* type */
275 	 2,			/* rightshift */
276 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
277 	 25,			/* bitsize */
278 	 TRUE,			/* pc_relative */
279 	 0,			/* bitpos */
280 	 complain_overflow_signed,/* complain_on_overflow */
281 	 bfd_elf_generic_reloc,	/* special_function */
282 	 "R_ARM_XPC25",		/* name */
283 	 FALSE,			/* partial_inplace */
284 	 0x00ffffff,		/* src_mask */
285 	 0x00ffffff,		/* dst_mask */
286 	 TRUE),			/* pcrel_offset */
287 
288   /* BLX instruction for the Thumb.  */
289   HOWTO (R_ARM_THM_XPC22,	/* type */
290 	 2,			/* rightshift */
291 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
292 	 22,			/* bitsize */
293 	 TRUE,			/* pc_relative */
294 	 0,			/* bitpos */
295 	 complain_overflow_signed,/* complain_on_overflow */
296 	 bfd_elf_generic_reloc,	/* special_function */
297 	 "R_ARM_THM_XPC22",	/* name */
298 	 FALSE,			/* partial_inplace */
299 	 0x07ff07ff,		/* src_mask */
300 	 0x07ff07ff,		/* dst_mask */
301 	 TRUE),			/* pcrel_offset */
302 
303   /* These next three relocs are not defined, but we need to fill the space.  */
304 
305   HOWTO (R_ARM_NONE,		/* type */
306 	 0,			/* rightshift */
307 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
308 	 0,			/* bitsize */
309 	 FALSE,			/* pc_relative */
310 	 0,			/* bitpos */
311 	 complain_overflow_dont,/* complain_on_overflow */
312 	 bfd_elf_generic_reloc,	/* special_function */
313 	 "R_ARM_unknown_17",	/* name */
314 	 FALSE,			/* partial_inplace */
315 	 0,			/* src_mask */
316 	 0,			/* dst_mask */
317 	 FALSE),		/* pcrel_offset */
318 
319   HOWTO (R_ARM_NONE,		/* type */
320 	 0,			/* rightshift */
321 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
322 	 0,			/* bitsize */
323 	 FALSE,			/* pc_relative */
324 	 0,			/* bitpos */
325 	 complain_overflow_dont,/* complain_on_overflow */
326 	 bfd_elf_generic_reloc,	/* special_function */
327 	 "R_ARM_unknown_18",	/* name */
328 	 FALSE,			/* partial_inplace */
329 	 0,			/* src_mask */
330 	 0,			/* dst_mask */
331 	 FALSE),		/* pcrel_offset */
332 
333   HOWTO (R_ARM_NONE,		/* type */
334 	 0,			/* rightshift */
335 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
336 	 0,			/* bitsize */
337 	 FALSE,			/* pc_relative */
338 	 0,			/* bitpos */
339 	 complain_overflow_dont,/* complain_on_overflow */
340 	 bfd_elf_generic_reloc,	/* special_function */
341 	 "R_ARM_unknown_19",	/* name */
342 	 FALSE,			/* partial_inplace */
343 	 0,			/* src_mask */
344 	 0,			/* dst_mask */
345 	 FALSE),		/* pcrel_offset */
346 
347   /* Relocs used in ARM Linux */
348 
349   HOWTO (R_ARM_COPY,		/* type */
350          0,                     /* rightshift */
351          2,                     /* size (0 = byte, 1 = short, 2 = long) */
352          32,                    /* bitsize */
353          FALSE,                 /* pc_relative */
354          0,                     /* bitpos */
355          complain_overflow_bitfield,/* complain_on_overflow */
356          bfd_elf_generic_reloc, /* special_function */
357          "R_ARM_COPY",		/* name */
358          TRUE,			/* partial_inplace */
359          0xffffffff,		/* src_mask */
360          0xffffffff,		/* dst_mask */
361          FALSE),                /* pcrel_offset */
362 
363   HOWTO (R_ARM_GLOB_DAT,	/* type */
364          0,                     /* rightshift */
365          2,                     /* size (0 = byte, 1 = short, 2 = long) */
366          32,                    /* bitsize */
367          FALSE,                 /* pc_relative */
368          0,                     /* bitpos */
369          complain_overflow_bitfield,/* complain_on_overflow */
370          bfd_elf_generic_reloc, /* special_function */
371          "R_ARM_GLOB_DAT",	/* name */
372          TRUE,			/* partial_inplace */
373          0xffffffff,		/* src_mask */
374          0xffffffff,		/* dst_mask */
375          FALSE),                /* pcrel_offset */
376 
377   HOWTO (R_ARM_JUMP_SLOT,	/* type */
378          0,                     /* rightshift */
379          2,                     /* size (0 = byte, 1 = short, 2 = long) */
380          32,                    /* bitsize */
381          FALSE,                 /* pc_relative */
382          0,                     /* bitpos */
383          complain_overflow_bitfield,/* complain_on_overflow */
384          bfd_elf_generic_reloc, /* special_function */
385          "R_ARM_JUMP_SLOT",	/* name */
386          TRUE,			/* partial_inplace */
387          0xffffffff,		/* src_mask */
388          0xffffffff,		/* dst_mask */
389          FALSE),                /* pcrel_offset */
390 
391   HOWTO (R_ARM_RELATIVE,	/* type */
392          0,                     /* rightshift */
393          2,                     /* size (0 = byte, 1 = short, 2 = long) */
394          32,                    /* bitsize */
395          FALSE,                 /* pc_relative */
396          0,                     /* bitpos */
397          complain_overflow_bitfield,/* complain_on_overflow */
398          bfd_elf_generic_reloc, /* special_function */
399          "R_ARM_RELATIVE",	/* name */
400          TRUE,			/* partial_inplace */
401          0xffffffff,		/* src_mask */
402          0xffffffff,		/* dst_mask */
403          FALSE),                /* pcrel_offset */
404 
405   HOWTO (R_ARM_GOTOFF,		/* type */
406          0,                     /* rightshift */
407          2,                     /* size (0 = byte, 1 = short, 2 = long) */
408          32,                    /* bitsize */
409          FALSE,                 /* pc_relative */
410          0,                     /* bitpos */
411          complain_overflow_bitfield,/* complain_on_overflow */
412          bfd_elf_generic_reloc, /* special_function */
413          "R_ARM_GOTOFF",	/* name */
414          TRUE,			/* partial_inplace */
415          0xffffffff,		/* src_mask */
416          0xffffffff,		/* dst_mask */
417          FALSE),                /* pcrel_offset */
418 
419   HOWTO (R_ARM_GOTPC,		/* type */
420          0,                     /* rightshift */
421          2,                     /* size (0 = byte, 1 = short, 2 = long) */
422          32,                    /* bitsize */
423          TRUE,			/* pc_relative */
424          0,                     /* bitpos */
425          complain_overflow_bitfield,/* complain_on_overflow */
426          bfd_elf_generic_reloc, /* special_function */
427          "R_ARM_GOTPC",		/* name */
428          TRUE,			/* partial_inplace */
429          0xffffffff,		/* src_mask */
430          0xffffffff,		/* dst_mask */
431          TRUE),			/* pcrel_offset */
432 
433   HOWTO (R_ARM_GOT32,		/* type */
434          0,                     /* rightshift */
435          2,                     /* size (0 = byte, 1 = short, 2 = long) */
436          32,                    /* bitsize */
437          FALSE,			/* pc_relative */
438          0,                     /* bitpos */
439          complain_overflow_bitfield,/* complain_on_overflow */
440          bfd_elf_generic_reloc, /* special_function */
441          "R_ARM_GOT32",		/* name */
442          TRUE,			/* partial_inplace */
443          0xffffffff,		/* src_mask */
444          0xffffffff,		/* dst_mask */
445          FALSE),		/* pcrel_offset */
446 
447   HOWTO (R_ARM_PLT32,		/* type */
448          2,                     /* rightshift */
449          2,                     /* size (0 = byte, 1 = short, 2 = long) */
450          26,                    /* bitsize */
451          TRUE,			/* pc_relative */
452          0,                     /* bitpos */
453          complain_overflow_bitfield,/* complain_on_overflow */
454          bfd_elf_generic_reloc, /* special_function */
455          "R_ARM_PLT32",		/* name */
456          TRUE,			/* partial_inplace */
457          0x00ffffff,		/* src_mask */
458          0x00ffffff,		/* dst_mask */
459          TRUE),			/* pcrel_offset */
460 
461   /* End of relocs used in ARM Linux */
462 
463   HOWTO (R_ARM_RREL32,		/* type */
464 	 0,			/* rightshift */
465 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
466 	 0,			/* bitsize */
467 	 FALSE,			/* pc_relative */
468 	 0,			/* bitpos */
469 	 complain_overflow_dont,/* complain_on_overflow */
470 	 bfd_elf_generic_reloc,	/* special_function */
471 	 "R_ARM_RREL32",	/* name */
472 	 FALSE,			/* partial_inplace */
473 	 0,			/* src_mask */
474 	 0,			/* dst_mask */
475 	 FALSE),		/* pcrel_offset */
476 
477   HOWTO (R_ARM_RABS32,		/* type */
478 	 0,			/* rightshift */
479 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
480 	 0,			/* bitsize */
481 	 FALSE,			/* pc_relative */
482 	 0,			/* bitpos */
483 	 complain_overflow_dont,/* complain_on_overflow */
484 	 bfd_elf_generic_reloc,	/* special_function */
485 	 "R_ARM_RABS32",	/* name */
486 	 FALSE,			/* partial_inplace */
487 	 0,			/* src_mask */
488 	 0,			/* dst_mask */
489 	 FALSE),		/* pcrel_offset */
490 
491   HOWTO (R_ARM_RPC24,		/* type */
492 	 0,			/* rightshift */
493 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
494 	 0,			/* bitsize */
495 	 FALSE,			/* pc_relative */
496 	 0,			/* bitpos */
497 	 complain_overflow_dont,/* complain_on_overflow */
498 	 bfd_elf_generic_reloc,	/* special_function */
499 	 "R_ARM_RPC24",		/* name */
500 	 FALSE,			/* partial_inplace */
501 	 0,			/* src_mask */
502 	 0,			/* dst_mask */
503 	 FALSE),		/* pcrel_offset */
504 
505   HOWTO (R_ARM_RBASE,		/* type */
506 	 0,			/* rightshift */
507 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
508 	 0,			/* bitsize */
509 	 FALSE,			/* pc_relative */
510 	 0,			/* bitpos */
511 	 complain_overflow_dont,/* complain_on_overflow */
512 	 bfd_elf_generic_reloc,	/* special_function */
513 	 "R_ARM_RBASE",		/* name */
514 	 FALSE,			/* partial_inplace */
515 	 0,			/* src_mask */
516 	 0,			/* dst_mask */
517 	 FALSE),		/* pcrel_offset */
518 
519 };
520 
521   /* GNU extension to record C++ vtable hierarchy */
522 static reloc_howto_type elf32_arm_vtinherit_howto =
523   HOWTO (R_ARM_GNU_VTINHERIT, /* type */
524          0,                     /* rightshift */
525          2,                     /* size (0 = byte, 1 = short, 2 = long) */
526          0,                     /* bitsize */
527          FALSE,                 /* pc_relative */
528          0,                     /* bitpos */
529          complain_overflow_dont, /* complain_on_overflow */
530          NULL,                  /* special_function */
531          "R_ARM_GNU_VTINHERIT", /* name */
532          FALSE,                 /* partial_inplace */
533          0,                     /* src_mask */
534          0,                     /* dst_mask */
535          FALSE);                /* pcrel_offset */
536 
537   /* GNU extension to record C++ vtable member usage */
538 static reloc_howto_type elf32_arm_vtentry_howto =
539   HOWTO (R_ARM_GNU_VTENTRY,     /* type */
540          0,                     /* rightshift */
541          2,                     /* size (0 = byte, 1 = short, 2 = long) */
542          0,                     /* bitsize */
543          FALSE,                 /* pc_relative */
544          0,                     /* bitpos */
545          complain_overflow_dont, /* complain_on_overflow */
546          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
547          "R_ARM_GNU_VTENTRY",   /* name */
548          FALSE,                 /* partial_inplace */
549          0,                     /* src_mask */
550          0,                     /* dst_mask */
551          FALSE);                /* pcrel_offset */
552 
553   /* 12 bit pc relative */
554 static reloc_howto_type elf32_arm_thm_pc11_howto =
555   HOWTO (R_ARM_THM_PC11,	/* type */
556 	 1,			/* rightshift */
557 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
558 	 11,			/* bitsize */
559 	 TRUE,			/* pc_relative */
560 	 0,			/* bitpos */
561 	 complain_overflow_signed,	/* complain_on_overflow */
562 	 bfd_elf_generic_reloc,	/* special_function */
563 	 "R_ARM_THM_PC11",	/* name */
564 	 FALSE,			/* partial_inplace */
565 	 0x000007ff,		/* src_mask */
566 	 0x000007ff,		/* dst_mask */
567 	 TRUE);			/* pcrel_offset */
568 
569   /* 12 bit pc relative */
570 static reloc_howto_type elf32_arm_thm_pc9_howto =
571   HOWTO (R_ARM_THM_PC9,		/* type */
572 	 1,			/* rightshift */
573 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
574 	 8,			/* bitsize */
575 	 TRUE,			/* pc_relative */
576 	 0,			/* bitpos */
577 	 complain_overflow_signed,	/* complain_on_overflow */
578 	 bfd_elf_generic_reloc,	/* special_function */
579 	 "R_ARM_THM_PC9",	/* name */
580 	 FALSE,			/* partial_inplace */
581 	 0x000000ff,		/* src_mask */
582 	 0x000000ff,		/* dst_mask */
583 	 TRUE);			/* pcrel_offset */
584 
585 static void elf32_arm_info_to_howto
586   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
587 
588 static void
589 elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc)
590      bfd * abfd ATTRIBUTE_UNUSED;
591      arelent * bfd_reloc;
592      Elf_Internal_Rela * elf_reloc;
593 {
594   unsigned int r_type;
595 
596   r_type = ELF32_R_TYPE (elf_reloc->r_info);
597 
598   switch (r_type)
599     {
600     case R_ARM_GNU_VTINHERIT:
601       bfd_reloc->howto = & elf32_arm_vtinherit_howto;
602       break;
603 
604     case R_ARM_GNU_VTENTRY:
605       bfd_reloc->howto = & elf32_arm_vtentry_howto;
606       break;
607 
608     case R_ARM_THM_PC11:
609       bfd_reloc->howto = & elf32_arm_thm_pc11_howto;
610       break;
611 
612     case R_ARM_THM_PC9:
613       bfd_reloc->howto = & elf32_arm_thm_pc9_howto;
614       break;
615 
616     default:
617       if (r_type >= NUM_ELEM (elf32_arm_howto_table))
618 	bfd_reloc->howto = NULL;
619       else
620         bfd_reloc->howto = & elf32_arm_howto_table[r_type];
621       break;
622     }
623 }
624 
625 struct elf32_arm_reloc_map
626   {
627     bfd_reloc_code_real_type  bfd_reloc_val;
628     unsigned char             elf_reloc_val;
629   };
630 
631 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
632   {
633     {BFD_RELOC_NONE,                 R_ARM_NONE},
634     {BFD_RELOC_ARM_PCREL_BRANCH,     R_ARM_PC24},
635     {BFD_RELOC_ARM_PCREL_BLX,        R_ARM_XPC25},
636     {BFD_RELOC_THUMB_PCREL_BLX,      R_ARM_THM_XPC22},
637     {BFD_RELOC_32,                   R_ARM_ABS32},
638     {BFD_RELOC_32_PCREL,             R_ARM_REL32},
639     {BFD_RELOC_8,                    R_ARM_ABS8},
640     {BFD_RELOC_16,                   R_ARM_ABS16},
641     {BFD_RELOC_ARM_OFFSET_IMM,       R_ARM_ABS12},
642     {BFD_RELOC_ARM_THUMB_OFFSET,     R_ARM_THM_ABS5},
643     {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22},
644     {BFD_RELOC_ARM_COPY,             R_ARM_COPY},
645     {BFD_RELOC_ARM_GLOB_DAT,         R_ARM_GLOB_DAT},
646     {BFD_RELOC_ARM_JUMP_SLOT,        R_ARM_JUMP_SLOT},
647     {BFD_RELOC_ARM_RELATIVE,         R_ARM_RELATIVE},
648     {BFD_RELOC_ARM_GOTOFF,           R_ARM_GOTOFF},
649     {BFD_RELOC_ARM_GOTPC,            R_ARM_GOTPC},
650     {BFD_RELOC_ARM_GOT32,            R_ARM_GOT32},
651     {BFD_RELOC_ARM_PLT32,            R_ARM_PLT32}
652   };
653 
654 static reloc_howto_type *
655 elf32_arm_reloc_type_lookup (abfd, code)
656      bfd *abfd ATTRIBUTE_UNUSED;
657      bfd_reloc_code_real_type code;
658 {
659   unsigned int i;
660 
661   switch (code)
662     {
663     case BFD_RELOC_VTABLE_INHERIT:
664       return & elf32_arm_vtinherit_howto;
665 
666     case BFD_RELOC_VTABLE_ENTRY:
667       return & elf32_arm_vtentry_howto;
668 
669     case BFD_RELOC_THUMB_PCREL_BRANCH12:
670       return & elf32_arm_thm_pc11_howto;
671 
672     case BFD_RELOC_THUMB_PCREL_BRANCH9:
673       return & elf32_arm_thm_pc9_howto;
674 
675     default:
676       for (i = 0; i < NUM_ELEM (elf32_arm_reloc_map); i ++)
677 	if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
678 	  return & elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val];
679 
680       return NULL;
681    }
682 }
683 
684 /* Support for core dump NOTE sections */
685 static bfd_boolean
686 elf32_arm_nabi_grok_prstatus (abfd, note)
687      bfd *abfd;
688      Elf_Internal_Note *note;
689 {
690   int offset;
691   size_t raw_size;
692 
693   switch (note->descsz)
694     {
695       default:
696 	return FALSE;
697 
698       case 148:		/* Linux/ARM 32-bit*/
699 	/* pr_cursig */
700 	elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
701 
702 	/* pr_pid */
703 	elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
704 
705 	/* pr_reg */
706 	offset = 72;
707 	raw_size = 72;
708 
709 	break;
710     }
711 
712   /* Make a ".reg/999" section.  */
713   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
714 					  raw_size, note->descpos + offset);
715 }
716 
717 static bfd_boolean
718 elf32_arm_nabi_grok_psinfo (abfd, note)
719      bfd *abfd;
720      Elf_Internal_Note *note;
721 {
722   switch (note->descsz)
723     {
724       default:
725 	return FALSE;
726 
727       case 124:		/* Linux/ARM elf_prpsinfo */
728 	elf_tdata (abfd)->core_program
729 	 = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
730 	elf_tdata (abfd)->core_command
731 	 = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
732     }
733 
734   /* Note that for some reason, a spurious space is tacked
735      onto the end of the args in some (at least one anyway)
736      implementations, so strip it off if it exists.  */
737 
738   {
739     char *command = elf_tdata (abfd)->core_command;
740     int n = strlen (command);
741 
742     if (0 < n && command[n - 1] == ' ')
743       command[n - 1] = '\0';
744   }
745 
746   return TRUE;
747 }
748 
749 #define elf_backend_grok_prstatus	elf32_arm_nabi_grok_prstatus
750 #define elf_backend_grok_psinfo		elf32_arm_nabi_grok_psinfo
751 
752 #include "elf32-arm.h"
753