Merge from vendor branch GCC:
[dragonfly.git] / contrib / binutils / bfd / elfarm-nabi.c
1 /* 32-bit ELF support for ARM new abi option.
2    Copyright 1999, 2000, 2001 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
31
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 boolean elf32_arm_nabi_grok_prstatus
46   PARAMS ((bfd *abfd, Elf_Internal_Note *note));
47 static boolean elf32_arm_nabi_grok_psinfo
48   PARAMS ((bfd *abfd, Elf_Internal_Note *note));
49
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 *, Elf32_Internal_Rel *));
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      Elf32_Internal_Rel * 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 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 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"