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
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
43static reloc_howto_type * elf32_arm_reloc_type_lookup
44  PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
45static bfd_boolean elf32_arm_nabi_grok_prstatus
46  PARAMS ((bfd *abfd, Elf_Internal_Note *note));
47static bfd_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
54static 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 */
522static 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 */
538static 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 */
554static 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 */
570static 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
585static void elf32_arm_info_to_howto
586  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
587
588static void
589elf32_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
625struct elf32_arm_reloc_map
626  {
627    bfd_reloc_code_real_type  bfd_reloc_val;
628    unsigned char             elf_reloc_val;
629  };
630
631static 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
654static reloc_howto_type *
655elf32_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 */
685static bfd_boolean
686elf32_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
717static bfd_boolean
718elf32_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