1377e23a2Schristos /* BFD support for the ARM processor
2*1424dfb3Schristos Copyright (C) 1994-2020 Free Software Foundation, Inc.
3377e23a2Schristos Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4377e23a2Schristos
5377e23a2Schristos This file is part of BFD, the Binary File Descriptor library.
6377e23a2Schristos
7377e23a2Schristos This program is free software; you can redistribute it and/or modify
8377e23a2Schristos it under the terms of the GNU General Public License as published by
9377e23a2Schristos the Free Software Foundation; either version 3 of the License, or
10377e23a2Schristos (at your option) any later version.
11377e23a2Schristos
12377e23a2Schristos This program is distributed in the hope that it will be useful,
13377e23a2Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
14377e23a2Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15377e23a2Schristos GNU General Public License for more details.
16377e23a2Schristos
17377e23a2Schristos You should have received a copy of the GNU General Public License
18377e23a2Schristos along with this program; if not, write to the Free Software
19377e23a2Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20377e23a2Schristos MA 02110-1301, USA. */
21377e23a2Schristos
22377e23a2Schristos #include "sysdep.h"
23377e23a2Schristos #include "bfd.h"
24377e23a2Schristos #include "libbfd.h"
25377e23a2Schristos #include "libiberty.h"
26*1424dfb3Schristos #include "cpu-arm.h"
27377e23a2Schristos
28377e23a2Schristos /* This routine is provided two arch_infos and works out which ARM
29377e23a2Schristos machine which would be compatible with both and returns a pointer
30377e23a2Schristos to its info structure. */
31377e23a2Schristos
32377e23a2Schristos static const bfd_arch_info_type *
compatible(const bfd_arch_info_type * a,const bfd_arch_info_type * b)33377e23a2Schristos compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
34377e23a2Schristos {
35377e23a2Schristos /* If a & b are for different architecture we can do nothing. */
36377e23a2Schristos if (a->arch != b->arch)
37377e23a2Schristos return NULL;
38377e23a2Schristos
39377e23a2Schristos /* If a & b are for the same machine then all is well. */
40377e23a2Schristos if (a->mach == b->mach)
41377e23a2Schristos return a;
42377e23a2Schristos
43377e23a2Schristos /* Otherwise if either a or b is the 'default' machine
44377e23a2Schristos then it can be polymorphed into the other. */
45377e23a2Schristos if (a->the_default)
46377e23a2Schristos return b;
47377e23a2Schristos
48377e23a2Schristos if (b->the_default)
49377e23a2Schristos return a;
50377e23a2Schristos
51377e23a2Schristos /* So far all newer ARM architecture cores are
52377e23a2Schristos supersets of previous cores. */
53377e23a2Schristos if (a->mach < b->mach)
54377e23a2Schristos return b;
55377e23a2Schristos else if (a->mach > b->mach)
56377e23a2Schristos return a;
57377e23a2Schristos
58377e23a2Schristos /* Never reached! */
59377e23a2Schristos return NULL;
60377e23a2Schristos }
61377e23a2Schristos
62377e23a2Schristos static struct
63377e23a2Schristos {
64377e23a2Schristos unsigned int mach;
65377e23a2Schristos char * name;
66377e23a2Schristos }
67377e23a2Schristos processors[] =
68377e23a2Schristos {
69377e23a2Schristos { bfd_mach_arm_2, "arm2" },
70377e23a2Schristos { bfd_mach_arm_2a, "arm250" },
71377e23a2Schristos { bfd_mach_arm_2a, "arm3" },
72377e23a2Schristos { bfd_mach_arm_3, "arm6" },
73377e23a2Schristos { bfd_mach_arm_3, "arm60" },
74377e23a2Schristos { bfd_mach_arm_3, "arm600" },
75377e23a2Schristos { bfd_mach_arm_3, "arm610" },
7607163879Schristos { bfd_mach_arm_3, "arm620" },
77377e23a2Schristos { bfd_mach_arm_3, "arm7" },
7807163879Schristos { bfd_mach_arm_3, "arm70" },
7907163879Schristos { bfd_mach_arm_3, "arm700" },
8007163879Schristos { bfd_mach_arm_3, "arm700i" },
81377e23a2Schristos { bfd_mach_arm_3, "arm710" },
8207163879Schristos { bfd_mach_arm_3, "arm7100" },
8307163879Schristos { bfd_mach_arm_3, "arm710c" },
8407163879Schristos { bfd_mach_arm_4T, "arm710t" },
8507163879Schristos { bfd_mach_arm_3, "arm720" },
8607163879Schristos { bfd_mach_arm_4T, "arm720t" },
8707163879Schristos { bfd_mach_arm_4T, "arm740t" },
88377e23a2Schristos { bfd_mach_arm_3, "arm7500" },
8907163879Schristos { bfd_mach_arm_3, "arm7500fe" },
90377e23a2Schristos { bfd_mach_arm_3, "arm7d" },
91377e23a2Schristos { bfd_mach_arm_3, "arm7di" },
92377e23a2Schristos { bfd_mach_arm_3M, "arm7dm" },
93377e23a2Schristos { bfd_mach_arm_3M, "arm7dmi" },
9407163879Schristos { bfd_mach_arm_4T, "arm7t" },
95377e23a2Schristos { bfd_mach_arm_4T, "arm7tdmi" },
9607163879Schristos { bfd_mach_arm_4T, "arm7tdmi-s" },
9707163879Schristos { bfd_mach_arm_3M, "arm7m" },
98377e23a2Schristos { bfd_mach_arm_4, "arm8" },
99377e23a2Schristos { bfd_mach_arm_4, "arm810" },
100377e23a2Schristos { bfd_mach_arm_4, "arm9" },
10107163879Schristos { bfd_mach_arm_4T, "arm920" },
102377e23a2Schristos { bfd_mach_arm_4T, "arm920t" },
10307163879Schristos { bfd_mach_arm_4T, "arm922t" },
10407163879Schristos { bfd_mach_arm_5TEJ, "arm926ej" },
10507163879Schristos { bfd_mach_arm_5TEJ, "arm926ejs" },
10607163879Schristos { bfd_mach_arm_5TEJ, "arm926ej-s" },
10707163879Schristos { bfd_mach_arm_4T, "arm940t" },
10807163879Schristos { bfd_mach_arm_5TE, "arm946e" },
10907163879Schristos { bfd_mach_arm_5TE, "arm946e-r0" },
11007163879Schristos { bfd_mach_arm_5TE, "arm946e-s" },
11107163879Schristos { bfd_mach_arm_5TE, "arm966e" },
11207163879Schristos { bfd_mach_arm_5TE, "arm966e-r0" },
11307163879Schristos { bfd_mach_arm_5TE, "arm966e-s" },
11407163879Schristos { bfd_mach_arm_5TE, "arm968e-s" },
11507163879Schristos { bfd_mach_arm_5TE, "arm9e" },
11607163879Schristos { bfd_mach_arm_5TE, "arm9e-r0" },
117377e23a2Schristos { bfd_mach_arm_4T, "arm9tdmi" },
11807163879Schristos { bfd_mach_arm_5TE, "arm1020" },
11907163879Schristos { bfd_mach_arm_5T, "arm1020t" },
12007163879Schristos { bfd_mach_arm_5TE, "arm1020e" },
12107163879Schristos { bfd_mach_arm_5TE, "arm1022e" },
12207163879Schristos { bfd_mach_arm_5TEJ, "arm1026ejs" },
12307163879Schristos { bfd_mach_arm_5TEJ, "arm1026ej-s" },
12407163879Schristos { bfd_mach_arm_5TE, "arm10e" },
12507163879Schristos { bfd_mach_arm_5T, "arm10t" },
12607163879Schristos { bfd_mach_arm_5T, "arm10tdmi" },
12707163879Schristos { bfd_mach_arm_6, "arm1136j-s" },
12807163879Schristos { bfd_mach_arm_6, "arm1136js" },
12907163879Schristos { bfd_mach_arm_6, "arm1136jf-s" },
13007163879Schristos { bfd_mach_arm_6, "arm1136jfs" },
13107163879Schristos { bfd_mach_arm_6KZ, "arm1176jz-s" },
13207163879Schristos { bfd_mach_arm_6KZ, "arm1176jzf-s" },
13307163879Schristos { bfd_mach_arm_6T2, "arm1156t2-s" },
13407163879Schristos { bfd_mach_arm_6T2, "arm1156t2f-s" },
13507163879Schristos { bfd_mach_arm_7, "cortex-a5" },
13607163879Schristos { bfd_mach_arm_7, "cortex-a7" },
13707163879Schristos { bfd_mach_arm_7, "cortex-a8" },
13807163879Schristos { bfd_mach_arm_7, "cortex-a9" },
13907163879Schristos { bfd_mach_arm_7, "cortex-a12" },
14007163879Schristos { bfd_mach_arm_7, "cortex-a15" },
14107163879Schristos { bfd_mach_arm_7, "cortex-a17" },
14207163879Schristos { bfd_mach_arm_8, "cortex-a32" },
14307163879Schristos { bfd_mach_arm_8, "cortex-a35" },
14407163879Schristos { bfd_mach_arm_8, "cortex-a53" },
14507163879Schristos { bfd_mach_arm_8, "cortex-a55" },
14607163879Schristos { bfd_mach_arm_8, "cortex-a57" },
14707163879Schristos { bfd_mach_arm_8, "cortex-a72" },
14807163879Schristos { bfd_mach_arm_8, "cortex-a73" },
14907163879Schristos { bfd_mach_arm_8, "cortex-a75" },
15007163879Schristos { bfd_mach_arm_8, "cortex-a76" },
151*1424dfb3Schristos { bfd_mach_arm_8, "cortex-a76ae" },
152*1424dfb3Schristos { bfd_mach_arm_8, "cortex-a77" },
15307163879Schristos { bfd_mach_arm_6SM, "cortex-m0" },
15407163879Schristos { bfd_mach_arm_6SM, "cortex-m0plus" },
15507163879Schristos { bfd_mach_arm_6SM, "cortex-m1" },
15607163879Schristos { bfd_mach_arm_8M_BASE, "cortex-m23" },
15707163879Schristos { bfd_mach_arm_7, "cortex-m3" },
15807163879Schristos { bfd_mach_arm_8M_MAIN, "cortex-m33" },
159*1424dfb3Schristos { bfd_mach_arm_8M_MAIN, "cortex-m35p" },
16007163879Schristos { bfd_mach_arm_7EM, "cortex-m4" },
16107163879Schristos { bfd_mach_arm_7EM, "cortex-m7" },
16207163879Schristos { bfd_mach_arm_7, "cortex-r4" },
16307163879Schristos { bfd_mach_arm_7, "cortex-r4f" },
16407163879Schristos { bfd_mach_arm_7, "cortex-r5" },
16507163879Schristos { bfd_mach_arm_8R, "cortex-r52" },
16607163879Schristos { bfd_mach_arm_7, "cortex-r7" },
16707163879Schristos { bfd_mach_arm_7, "cortex-r8" },
16807163879Schristos { bfd_mach_arm_4T, "ep9312" },
16907163879Schristos { bfd_mach_arm_8, "exynos-m1" },
17007163879Schristos { bfd_mach_arm_4, "fa526" },
17107163879Schristos { bfd_mach_arm_5TE, "fa606te" },
17207163879Schristos { bfd_mach_arm_5TE, "fa616te" },
17307163879Schristos { bfd_mach_arm_4, "fa626" },
17407163879Schristos { bfd_mach_arm_5TE, "fa626te" },
17507163879Schristos { bfd_mach_arm_5TE, "fa726te" },
17607163879Schristos { bfd_mach_arm_5TE, "fmp626" },
17707163879Schristos { bfd_mach_arm_XScale, "i80200" },
17807163879Schristos { bfd_mach_arm_7, "marvell-pj4" },
17907163879Schristos { bfd_mach_arm_7, "marvell-whitney" },
18007163879Schristos { bfd_mach_arm_6K, "mpcore" },
18107163879Schristos { bfd_mach_arm_6K, "mpcorenovfp" },
182377e23a2Schristos { bfd_mach_arm_4, "sa1" },
183377e23a2Schristos { bfd_mach_arm_4, "strongarm" },
18407163879Schristos { bfd_mach_arm_4, "strongarm1" },
185377e23a2Schristos { bfd_mach_arm_4, "strongarm110" },
186377e23a2Schristos { bfd_mach_arm_4, "strongarm1100" },
18707163879Schristos { bfd_mach_arm_4, "strongarm1110" },
188377e23a2Schristos { bfd_mach_arm_XScale, "xscale" },
18907163879Schristos { bfd_mach_arm_8, "xgene1" },
19007163879Schristos { bfd_mach_arm_8, "xgene2" },
191377e23a2Schristos { bfd_mach_arm_ep9312, "ep9312" },
192377e23a2Schristos { bfd_mach_arm_iWMMXt, "iwmmxt" },
193c03b94e9Schristos { bfd_mach_arm_iWMMXt2, "iwmmxt2" },
194c03b94e9Schristos { bfd_mach_arm_unknown, "arm_any" }
195377e23a2Schristos };
196377e23a2Schristos
197377e23a2Schristos static bfd_boolean
scan(const struct bfd_arch_info * info,const char * string)198377e23a2Schristos scan (const struct bfd_arch_info *info, const char *string)
199377e23a2Schristos {
200377e23a2Schristos int i;
201377e23a2Schristos
202377e23a2Schristos /* First test for an exact match. */
203377e23a2Schristos if (strcasecmp (string, info->printable_name) == 0)
204377e23a2Schristos return TRUE;
205377e23a2Schristos
206377e23a2Schristos /* Next check for a processor name instead of an Architecture name. */
207377e23a2Schristos for (i = sizeof (processors) / sizeof (processors[0]); i--;)
208377e23a2Schristos {
209377e23a2Schristos if (strcasecmp (string, processors [i].name) == 0)
210377e23a2Schristos break;
211377e23a2Schristos }
212377e23a2Schristos
213377e23a2Schristos if (i != -1 && info->mach == processors [i].mach)
214377e23a2Schristos return TRUE;
215377e23a2Schristos
216377e23a2Schristos /* Finally check for the default architecture. */
217377e23a2Schristos if (strcasecmp (string, "arm") == 0)
218377e23a2Schristos return info->the_default;
219377e23a2Schristos
220377e23a2Schristos return FALSE;
221377e23a2Schristos }
222377e23a2Schristos
223377e23a2Schristos #define N(number, print, default, next) \
22448596154Schristos { 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
225*1424dfb3Schristos scan, bfd_arch_default_fill, next, 0 }
226377e23a2Schristos
227377e23a2Schristos static const bfd_arch_info_type arch_info_struct[] =
228377e23a2Schristos {
229377e23a2Schristos N (bfd_mach_arm_2, "armv2", FALSE, & arch_info_struct[1]),
230377e23a2Schristos N (bfd_mach_arm_2a, "armv2a", FALSE, & arch_info_struct[2]),
231377e23a2Schristos N (bfd_mach_arm_3, "armv3", FALSE, & arch_info_struct[3]),
232377e23a2Schristos N (bfd_mach_arm_3M, "armv3m", FALSE, & arch_info_struct[4]),
233377e23a2Schristos N (bfd_mach_arm_4, "armv4", FALSE, & arch_info_struct[5]),
234377e23a2Schristos N (bfd_mach_arm_4T, "armv4t", FALSE, & arch_info_struct[6]),
235377e23a2Schristos N (bfd_mach_arm_5, "armv5", FALSE, & arch_info_struct[7]),
236377e23a2Schristos N (bfd_mach_arm_5T, "armv5t", FALSE, & arch_info_struct[8]),
237377e23a2Schristos N (bfd_mach_arm_5TE, "armv5te", FALSE, & arch_info_struct[9]),
238377e23a2Schristos N (bfd_mach_arm_XScale, "xscale", FALSE, & arch_info_struct[10]),
239377e23a2Schristos N (bfd_mach_arm_ep9312, "ep9312", FALSE, & arch_info_struct[11]),
240377e23a2Schristos N (bfd_mach_arm_iWMMXt, "iwmmxt", FALSE, & arch_info_struct[12]),
241c03b94e9Schristos N (bfd_mach_arm_iWMMXt2, "iwmmxt2", FALSE, & arch_info_struct[13]),
24207163879Schristos N (bfd_mach_arm_5TEJ, "armv5tej", FALSE, & arch_info_struct[14]),
24307163879Schristos N (bfd_mach_arm_6, "armv6", FALSE, & arch_info_struct[15]),
24407163879Schristos N (bfd_mach_arm_6KZ, "armv6kz", FALSE, & arch_info_struct[16]),
24507163879Schristos N (bfd_mach_arm_6T2, "armv6t2", FALSE, & arch_info_struct[17]),
24607163879Schristos N (bfd_mach_arm_6K, "armv6k", FALSE, & arch_info_struct[18]),
24707163879Schristos N (bfd_mach_arm_7, "armv7", FALSE, & arch_info_struct[19]),
24807163879Schristos N (bfd_mach_arm_6M, "armv6-m", FALSE, & arch_info_struct[20]),
24907163879Schristos N (bfd_mach_arm_6SM, "armv6s-m", FALSE, & arch_info_struct[21]),
25007163879Schristos N (bfd_mach_arm_7EM, "armv7e-m", FALSE, & arch_info_struct[22]),
25107163879Schristos N (bfd_mach_arm_8, "armv8-a", FALSE, & arch_info_struct[23]),
25207163879Schristos N (bfd_mach_arm_8R, "armv8-r", FALSE, & arch_info_struct[24]),
25307163879Schristos N (bfd_mach_arm_8M_BASE, "armv8-m.base", FALSE, & arch_info_struct[25]),
25407163879Schristos N (bfd_mach_arm_8M_MAIN, "armv8-m.main", FALSE, & arch_info_struct[26]),
255*1424dfb3Schristos N (bfd_mach_arm_8_1M_MAIN, "armv8.1-m.main", FALSE, & arch_info_struct[27]),
256c03b94e9Schristos N (bfd_mach_arm_unknown, "arm_any", FALSE, NULL)
257377e23a2Schristos };
258377e23a2Schristos
259377e23a2Schristos const bfd_arch_info_type bfd_arm_arch =
260377e23a2Schristos N (0, "arm", TRUE, & arch_info_struct[0]);
261377e23a2Schristos
262377e23a2Schristos /* Support functions used by both the COFF and ELF versions of the ARM port. */
263377e23a2Schristos
264377e23a2Schristos /* Handle the merging of the 'machine' settings of input file IBFD
265377e23a2Schristos and an output file OBFD. These values actually represent the
266377e23a2Schristos different possible ARM architecture variants.
267377e23a2Schristos Returns TRUE if they were merged successfully or FALSE otherwise. */
268377e23a2Schristos
269377e23a2Schristos bfd_boolean
bfd_arm_merge_machines(bfd * ibfd,bfd * obfd)270377e23a2Schristos bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
271377e23a2Schristos {
272377e23a2Schristos unsigned int in = bfd_get_mach (ibfd);
273377e23a2Schristos unsigned int out = bfd_get_mach (obfd);
274377e23a2Schristos
275377e23a2Schristos /* If the output architecture is unknown, we now have a value to set. */
276377e23a2Schristos if (out == bfd_mach_arm_unknown)
277377e23a2Schristos bfd_set_arch_mach (obfd, bfd_arch_arm, in);
278377e23a2Schristos
279377e23a2Schristos /* If the input architecture is unknown,
280377e23a2Schristos then so must be the output architecture. */
281377e23a2Schristos else if (in == bfd_mach_arm_unknown)
282377e23a2Schristos /* FIXME: We ought to have some way to
283377e23a2Schristos override this on the command line. */
284377e23a2Schristos bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
285377e23a2Schristos
286377e23a2Schristos /* If they are the same then nothing needs to be done. */
287377e23a2Schristos else if (out == in)
288377e23a2Schristos ;
289377e23a2Schristos
290377e23a2Schristos /* Otherwise the general principle that a earlier architecture can be
291377e23a2Schristos linked with a later architecture to produce a binary that will execute
292377e23a2Schristos on the later architecture.
293377e23a2Schristos
294377e23a2Schristos We fail however if we attempt to link a Cirrus EP9312 binary with an
295377e23a2Schristos Intel XScale binary, since these architecture have co-processors which
296377e23a2Schristos will not both be present on the same physical hardware. */
297377e23a2Schristos else if (in == bfd_mach_arm_ep9312
298377e23a2Schristos && (out == bfd_mach_arm_XScale
299377e23a2Schristos || out == bfd_mach_arm_iWMMXt
300377e23a2Schristos || out == bfd_mach_arm_iWMMXt2))
301377e23a2Schristos {
3021c468f90Schristos /* xgettext: c-format */
303*1424dfb3Schristos _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
304*1424dfb3Schristos "whereas %pB is compiled for XScale"),
305377e23a2Schristos ibfd, obfd);
306377e23a2Schristos bfd_set_error (bfd_error_wrong_format);
307377e23a2Schristos return FALSE;
308377e23a2Schristos }
309377e23a2Schristos else if (out == bfd_mach_arm_ep9312
310377e23a2Schristos && (in == bfd_mach_arm_XScale
311377e23a2Schristos || in == bfd_mach_arm_iWMMXt
312377e23a2Schristos || in == bfd_mach_arm_iWMMXt2))
313377e23a2Schristos {
3141c468f90Schristos /* xgettext: c-format */
315*1424dfb3Schristos _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
316*1424dfb3Schristos "whereas %pB is compiled for XScale"),
317377e23a2Schristos obfd, ibfd);
318377e23a2Schristos bfd_set_error (bfd_error_wrong_format);
319377e23a2Schristos return FALSE;
320377e23a2Schristos }
321377e23a2Schristos else if (in > out)
322377e23a2Schristos bfd_set_arch_mach (obfd, bfd_arch_arm, in);
323377e23a2Schristos /* else
324377e23a2Schristos Nothing to do. */
325377e23a2Schristos
326377e23a2Schristos return TRUE;
327377e23a2Schristos }
328377e23a2Schristos
329377e23a2Schristos typedef struct
330377e23a2Schristos {
331377e23a2Schristos unsigned char namesz[4]; /* Size of entry's owner string. */
332377e23a2Schristos unsigned char descsz[4]; /* Size of the note descriptor. */
333377e23a2Schristos unsigned char type[4]; /* Interpretation of the descriptor. */
334377e23a2Schristos char name[1]; /* Start of the name+desc data. */
335377e23a2Schristos } arm_Note;
336377e23a2Schristos
337377e23a2Schristos static bfd_boolean
arm_check_note(bfd * abfd,bfd_byte * buffer,bfd_size_type buffer_size,const char * expected_name,char ** description_return)338377e23a2Schristos arm_check_note (bfd *abfd,
339377e23a2Schristos bfd_byte *buffer,
340377e23a2Schristos bfd_size_type buffer_size,
341377e23a2Schristos const char *expected_name,
342377e23a2Schristos char **description_return)
343377e23a2Schristos {
344377e23a2Schristos unsigned long namesz;
345377e23a2Schristos unsigned long descsz;
346377e23a2Schristos unsigned long type;
347377e23a2Schristos char * descr;
348377e23a2Schristos
349377e23a2Schristos if (buffer_size < offsetof (arm_Note, name))
350377e23a2Schristos return FALSE;
351377e23a2Schristos
352377e23a2Schristos /* We have to extract the values this way to allow for a
353377e23a2Schristos host whose endian-ness is different from the target. */
354377e23a2Schristos namesz = bfd_get_32 (abfd, buffer);
355377e23a2Schristos descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
356377e23a2Schristos type = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
357377e23a2Schristos descr = (char *) buffer + offsetof (arm_Note, name);
358377e23a2Schristos
359377e23a2Schristos /* Check for buffer overflow. */
360377e23a2Schristos if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
361377e23a2Schristos return FALSE;
362377e23a2Schristos
363377e23a2Schristos if (expected_name == NULL)
364377e23a2Schristos {
365377e23a2Schristos if (namesz != 0)
366377e23a2Schristos return FALSE;
367377e23a2Schristos }
368377e23a2Schristos else
369377e23a2Schristos {
370377e23a2Schristos if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
371377e23a2Schristos return FALSE;
372377e23a2Schristos
373377e23a2Schristos if (strcmp (descr, expected_name) != 0)
374377e23a2Schristos return FALSE;
375377e23a2Schristos
376377e23a2Schristos descr += (namesz + 3) & ~3;
377377e23a2Schristos }
378377e23a2Schristos
379377e23a2Schristos /* FIXME: We should probably check the type as well. */
380377e23a2Schristos (void) type;
381377e23a2Schristos
382377e23a2Schristos if (description_return != NULL)
383377e23a2Schristos * description_return = descr;
384377e23a2Schristos
385377e23a2Schristos return TRUE;
386377e23a2Schristos }
387377e23a2Schristos
388377e23a2Schristos #define NOTE_ARCH_STRING "arch: "
389377e23a2Schristos
390377e23a2Schristos bfd_boolean
bfd_arm_update_notes(bfd * abfd,const char * note_section)391377e23a2Schristos bfd_arm_update_notes (bfd *abfd, const char *note_section)
392377e23a2Schristos {
393377e23a2Schristos asection * arm_arch_section;
394377e23a2Schristos bfd_size_type buffer_size;
395377e23a2Schristos bfd_byte * buffer;
396377e23a2Schristos char * arch_string;
397377e23a2Schristos char * expected;
398377e23a2Schristos
399377e23a2Schristos /* Look for a note section. If one is present check the architecture
400377e23a2Schristos string encoded in it, and set it to the current architecture if it is
401377e23a2Schristos different. */
402377e23a2Schristos arm_arch_section = bfd_get_section_by_name (abfd, note_section);
403377e23a2Schristos
404377e23a2Schristos if (arm_arch_section == NULL)
405377e23a2Schristos return TRUE;
406377e23a2Schristos
407377e23a2Schristos buffer_size = arm_arch_section->size;
408377e23a2Schristos if (buffer_size == 0)
409377e23a2Schristos return FALSE;
410377e23a2Schristos
411377e23a2Schristos if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
412377e23a2Schristos goto FAIL;
413377e23a2Schristos
414377e23a2Schristos /* Parse the note. */
415377e23a2Schristos if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
416377e23a2Schristos goto FAIL;
417377e23a2Schristos
41807163879Schristos /* Check the architecture in the note against the architecture of the bfd.
41907163879Schristos Newer architectures versions should not be added here as build attribute
42007163879Schristos are a better mechanism to convey ISA used. */
421377e23a2Schristos switch (bfd_get_mach (abfd))
422377e23a2Schristos {
423377e23a2Schristos default:
424377e23a2Schristos case bfd_mach_arm_unknown: expected = "unknown"; break;
425377e23a2Schristos case bfd_mach_arm_2: expected = "armv2"; break;
426377e23a2Schristos case bfd_mach_arm_2a: expected = "armv2a"; break;
427377e23a2Schristos case bfd_mach_arm_3: expected = "armv3"; break;
428377e23a2Schristos case bfd_mach_arm_3M: expected = "armv3M"; break;
429377e23a2Schristos case bfd_mach_arm_4: expected = "armv4"; break;
430377e23a2Schristos case bfd_mach_arm_4T: expected = "armv4t"; break;
431377e23a2Schristos case bfd_mach_arm_5: expected = "armv5"; break;
432377e23a2Schristos case bfd_mach_arm_5T: expected = "armv5t"; break;
433377e23a2Schristos case bfd_mach_arm_5TE: expected = "armv5te"; break;
434377e23a2Schristos case bfd_mach_arm_XScale: expected = "XScale"; break;
435377e23a2Schristos case bfd_mach_arm_ep9312: expected = "ep9312"; break;
436377e23a2Schristos case bfd_mach_arm_iWMMXt: expected = "iWMMXt"; break;
437377e23a2Schristos case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
438377e23a2Schristos }
439377e23a2Schristos
440377e23a2Schristos if (strcmp (arch_string, expected) != 0)
441377e23a2Schristos {
442377e23a2Schristos strcpy ((char *) buffer + (offsetof (arm_Note, name)
443377e23a2Schristos + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
444377e23a2Schristos expected);
445377e23a2Schristos
446377e23a2Schristos if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
447377e23a2Schristos (file_ptr) 0, buffer_size))
448377e23a2Schristos {
4491c468f90Schristos _bfd_error_handler
4501c468f90Schristos /* xgettext: c-format */
45107163879Schristos (_("warning: unable to update contents of %s section in %pB"),
4521c468f90Schristos note_section, abfd);
453377e23a2Schristos goto FAIL;
454377e23a2Schristos }
455377e23a2Schristos }
456377e23a2Schristos
457377e23a2Schristos free (buffer);
458377e23a2Schristos return TRUE;
459377e23a2Schristos
460377e23a2Schristos FAIL:
461377e23a2Schristos free (buffer);
462377e23a2Schristos return FALSE;
463377e23a2Schristos }
464377e23a2Schristos
465377e23a2Schristos
466377e23a2Schristos static struct
467377e23a2Schristos {
468377e23a2Schristos const char * string;
469377e23a2Schristos unsigned int mach;
470377e23a2Schristos }
47107163879Schristos
47207163879Schristos /* Newer architectures versions should not be added here as build attribute are
47307163879Schristos a better mechanism to convey ISA used. */
474377e23a2Schristos architectures[] =
475377e23a2Schristos {
476377e23a2Schristos { "armv2", bfd_mach_arm_2 },
477377e23a2Schristos { "armv2a", bfd_mach_arm_2a },
478377e23a2Schristos { "armv3", bfd_mach_arm_3 },
479377e23a2Schristos { "armv3M", bfd_mach_arm_3M },
480377e23a2Schristos { "armv4", bfd_mach_arm_4 },
481377e23a2Schristos { "armv4t", bfd_mach_arm_4T },
482377e23a2Schristos { "armv5", bfd_mach_arm_5 },
483377e23a2Schristos { "armv5t", bfd_mach_arm_5T },
484377e23a2Schristos { "armv5te", bfd_mach_arm_5TE },
485377e23a2Schristos { "XScale", bfd_mach_arm_XScale },
486377e23a2Schristos { "ep9312", bfd_mach_arm_ep9312 },
487377e23a2Schristos { "iWMMXt", bfd_mach_arm_iWMMXt },
488c03b94e9Schristos { "iWMMXt2", bfd_mach_arm_iWMMXt2 },
489c03b94e9Schristos { "arm_any", bfd_mach_arm_unknown }
490377e23a2Schristos };
491377e23a2Schristos
492377e23a2Schristos /* Extract the machine number stored in a note section. */
493377e23a2Schristos unsigned int
bfd_arm_get_mach_from_notes(bfd * abfd,const char * note_section)494377e23a2Schristos bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
495377e23a2Schristos {
496377e23a2Schristos asection * arm_arch_section;
497377e23a2Schristos bfd_size_type buffer_size;
498377e23a2Schristos bfd_byte * buffer;
499377e23a2Schristos char * arch_string;
500377e23a2Schristos int i;
501377e23a2Schristos
502377e23a2Schristos /* Look for a note section. If one is present check the architecture
503377e23a2Schristos string encoded in it, and set it to the current architecture if it is
504377e23a2Schristos different. */
505377e23a2Schristos arm_arch_section = bfd_get_section_by_name (abfd, note_section);
506377e23a2Schristos
507377e23a2Schristos if (arm_arch_section == NULL)
508377e23a2Schristos return bfd_mach_arm_unknown;
509377e23a2Schristos
510377e23a2Schristos buffer_size = arm_arch_section->size;
511377e23a2Schristos if (buffer_size == 0)
512377e23a2Schristos return bfd_mach_arm_unknown;
513377e23a2Schristos
514377e23a2Schristos if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
515377e23a2Schristos goto FAIL;
516377e23a2Schristos
517377e23a2Schristos /* Parse the note. */
518377e23a2Schristos if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
519377e23a2Schristos goto FAIL;
520377e23a2Schristos
521377e23a2Schristos /* Interpret the architecture string. */
522377e23a2Schristos for (i = ARRAY_SIZE (architectures); i--;)
523377e23a2Schristos if (strcmp (arch_string, architectures[i].string) == 0)
524377e23a2Schristos {
525377e23a2Schristos free (buffer);
526377e23a2Schristos return architectures[i].mach;
527377e23a2Schristos }
528377e23a2Schristos
529377e23a2Schristos FAIL:
530377e23a2Schristos free (buffer);
531377e23a2Schristos return bfd_mach_arm_unknown;
532377e23a2Schristos }
533377e23a2Schristos
534377e23a2Schristos bfd_boolean
bfd_is_arm_special_symbol_name(const char * name,int type)535377e23a2Schristos bfd_is_arm_special_symbol_name (const char * name, int type)
536377e23a2Schristos {
537377e23a2Schristos /* The ARM compiler outputs several obsolete forms. Recognize them
538377e23a2Schristos in addition to the standard $a, $t and $d. We are somewhat loose
539377e23a2Schristos in what we accept here, since the full set is not documented. */
540377e23a2Schristos if (!name || name[0] != '$')
541377e23a2Schristos return FALSE;
542377e23a2Schristos if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
543377e23a2Schristos type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
544377e23a2Schristos else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
545377e23a2Schristos type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
546377e23a2Schristos else if (name[1] >= 'a' && name[1] <= 'z')
547377e23a2Schristos type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
548377e23a2Schristos else
549377e23a2Schristos return FALSE;
550377e23a2Schristos
551377e23a2Schristos return (type != 0 && (name[2] == 0 || name[2] == '.'));
552377e23a2Schristos }
553377e23a2Schristos
554