]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/cpu-arm.c
Fix ARM and AArch64 assembler tests to work in a multi-arch environment.
[thirdparty/binutils-gdb.git] / bfd / cpu-arm.c
CommitLineData
252b5132 1/* BFD support for the ARM processor
a2c58332 2 Copyright (C) 1994-2022 Free Software Foundation, Inc.
252b5132
RH
3 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4
e2fd756b 5 This file is part of BFD, the Binary File Descriptor library.
252b5132 6
e2fd756b
NC
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
e2fd756b 10 (at your option) any later version.
252b5132 11
e2fd756b
NC
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
252b5132 16
e2fd756b
NC
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132 21
252b5132 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
252b5132 24#include "libbfd.h"
5a6c6817 25#include "libiberty.h"
f37164d7 26#include "cpu-arm.h"
252b5132 27
252b5132
RH
28/* This routine is provided two arch_infos and works out which ARM
29 machine which would be compatible with both and returns a pointer
e2fd756b 30 to its info structure. */
252b5132
RH
31
32static const bfd_arch_info_type *
f075ee0c 33compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
252b5132 34{
e2fd756b 35 /* If a & b are for different architecture we can do nothing. */
252b5132
RH
36 if (a->arch != b->arch)
37 return NULL;
38
e2fd756b 39 /* If a & b are for the same machine then all is well. */
252b5132
RH
40 if (a->mach == b->mach)
41 return a;
42
e2fd756b
NC
43 /* Otherwise if either a or b is the 'default' machine
44 then it can be polymorphed into the other. */
252b5132
RH
45 if (a->the_default)
46 return b;
71f6b586 47
252b5132
RH
48 if (b->the_default)
49 return a;
50
e2fd756b
NC
51 /* So far all newer ARM architecture cores are
52 supersets of previous cores. */
252b5132
RH
53 if (a->mach < b->mach)
54 return b;
55 else if (a->mach > b->mach)
56 return a;
57
e2fd756b 58 /* Never reached! */
252b5132
RH
59 return NULL;
60}
61
62static struct
63{
e2fd756b
NC
64 unsigned int mach;
65 char * name;
252b5132
RH
66}
67processors[] =
68{
b5ab3163
TP
69 { bfd_mach_arm_2, "arm2" },
70 { bfd_mach_arm_2a, "arm250" },
71 { bfd_mach_arm_2a, "arm3" },
72 { bfd_mach_arm_3, "arm6" },
73 { bfd_mach_arm_3, "arm60" },
74 { bfd_mach_arm_3, "arm600" },
75 { bfd_mach_arm_3, "arm610" },
76 { bfd_mach_arm_3, "arm620" },
77 { bfd_mach_arm_3, "arm7" },
78 { bfd_mach_arm_3, "arm70" },
79 { bfd_mach_arm_3, "arm700" },
80 { bfd_mach_arm_3, "arm700i" },
81 { bfd_mach_arm_3, "arm710" },
82 { bfd_mach_arm_3, "arm7100" },
83 { bfd_mach_arm_3, "arm710c" },
84 { bfd_mach_arm_4T, "arm710t" },
85 { bfd_mach_arm_3, "arm720" },
86 { bfd_mach_arm_4T, "arm720t" },
87 { bfd_mach_arm_4T, "arm740t" },
88 { bfd_mach_arm_3, "arm7500" },
89 { bfd_mach_arm_3, "arm7500fe" },
90 { bfd_mach_arm_3, "arm7d" },
91 { bfd_mach_arm_3, "arm7di" },
92 { bfd_mach_arm_3M, "arm7dm" },
93 { bfd_mach_arm_3M, "arm7dmi" },
94 { bfd_mach_arm_4T, "arm7t" },
95 { bfd_mach_arm_4T, "arm7tdmi" },
96 { bfd_mach_arm_4T, "arm7tdmi-s" },
97 { bfd_mach_arm_3M, "arm7m" },
98 { bfd_mach_arm_4, "arm8" },
99 { bfd_mach_arm_4, "arm810" },
100 { bfd_mach_arm_4, "arm9" },
101 { bfd_mach_arm_4T, "arm920" },
102 { bfd_mach_arm_4T, "arm920t" },
103 { bfd_mach_arm_4T, "arm922t" },
104 { bfd_mach_arm_5TEJ, "arm926ej" },
105 { bfd_mach_arm_5TEJ, "arm926ejs" },
106 { bfd_mach_arm_5TEJ, "arm926ej-s" },
107 { bfd_mach_arm_4T, "arm940t" },
108 { bfd_mach_arm_5TE, "arm946e" },
109 { bfd_mach_arm_5TE, "arm946e-r0" },
110 { bfd_mach_arm_5TE, "arm946e-s" },
111 { bfd_mach_arm_5TE, "arm966e" },
112 { bfd_mach_arm_5TE, "arm966e-r0" },
113 { bfd_mach_arm_5TE, "arm966e-s" },
114 { bfd_mach_arm_5TE, "arm968e-s" },
115 { bfd_mach_arm_5TE, "arm9e" },
116 { bfd_mach_arm_5TE, "arm9e-r0" },
117 { bfd_mach_arm_4T, "arm9tdmi" },
118 { bfd_mach_arm_5TE, "arm1020" },
119 { bfd_mach_arm_5T, "arm1020t" },
120 { bfd_mach_arm_5TE, "arm1020e" },
121 { bfd_mach_arm_5TE, "arm1022e" },
122 { bfd_mach_arm_5TEJ, "arm1026ejs" },
123 { bfd_mach_arm_5TEJ, "arm1026ej-s" },
124 { bfd_mach_arm_5TE, "arm10e" },
125 { bfd_mach_arm_5T, "arm10t" },
126 { bfd_mach_arm_5T, "arm10tdmi" },
127 { bfd_mach_arm_6, "arm1136j-s" },
128 { bfd_mach_arm_6, "arm1136js" },
129 { bfd_mach_arm_6, "arm1136jf-s" },
130 { bfd_mach_arm_6, "arm1136jfs" },
131 { bfd_mach_arm_6KZ, "arm1176jz-s" },
132 { bfd_mach_arm_6KZ, "arm1176jzf-s" },
133 { bfd_mach_arm_6T2, "arm1156t2-s" },
134 { bfd_mach_arm_6T2, "arm1156t2f-s" },
135 { bfd_mach_arm_7, "cortex-a5" },
136 { bfd_mach_arm_7, "cortex-a7" },
137 { bfd_mach_arm_7, "cortex-a8" },
138 { bfd_mach_arm_7, "cortex-a9" },
139 { bfd_mach_arm_7, "cortex-a12" },
140 { bfd_mach_arm_7, "cortex-a15" },
141 { bfd_mach_arm_7, "cortex-a17" },
142 { bfd_mach_arm_8, "cortex-a32" },
143 { bfd_mach_arm_8, "cortex-a35" },
144 { bfd_mach_arm_8, "cortex-a53" },
145 { bfd_mach_arm_8, "cortex-a55" },
146 { bfd_mach_arm_8, "cortex-a57" },
147 { bfd_mach_arm_8, "cortex-a72" },
148 { bfd_mach_arm_8, "cortex-a73" },
149 { bfd_mach_arm_8, "cortex-a75" },
150 { bfd_mach_arm_8, "cortex-a76" },
0535e5d7
DZ
151 { bfd_mach_arm_8, "cortex-a76ae" },
152 { bfd_mach_arm_8, "cortex-a77" },
42c36b73
PW
153 { bfd_mach_arm_8, "cortex-a78" },
154 { bfd_mach_arm_8, "cortex-a78ae" },
1bbda94f 155 { bfd_mach_arm_8, "cortex-a78c" },
b5ab3163
TP
156 { bfd_mach_arm_6SM, "cortex-m0" },
157 { bfd_mach_arm_6SM, "cortex-m0plus" },
158 { bfd_mach_arm_6SM, "cortex-m1" },
159 { bfd_mach_arm_8M_BASE, "cortex-m23" },
160 { bfd_mach_arm_7, "cortex-m3" },
161 { bfd_mach_arm_8M_MAIN, "cortex-m33" },
0535e5d7 162 { bfd_mach_arm_8M_MAIN, "cortex-m35p" },
b5ab3163
TP
163 { bfd_mach_arm_7EM, "cortex-m4" },
164 { bfd_mach_arm_7EM, "cortex-m7" },
165 { bfd_mach_arm_7, "cortex-r4" },
166 { bfd_mach_arm_7, "cortex-r4f" },
167 { bfd_mach_arm_7, "cortex-r5" },
168 { bfd_mach_arm_8R, "cortex-r52" },
80cfde76 169 { bfd_mach_arm_8R, "cortex-r52plus" },
b5ab3163
TP
170 { bfd_mach_arm_7, "cortex-r7" },
171 { bfd_mach_arm_7, "cortex-r8" },
394e9bf6 172 { bfd_mach_arm_8, "cortex-x1" },
cafdb713 173 { bfd_mach_arm_8, "cortex-x1c" },
b5ab3163
TP
174 { bfd_mach_arm_4T, "ep9312" },
175 { bfd_mach_arm_8, "exynos-m1" },
176 { bfd_mach_arm_4, "fa526" },
177 { bfd_mach_arm_5TE, "fa606te" },
178 { bfd_mach_arm_5TE, "fa616te" },
179 { bfd_mach_arm_4, "fa626" },
180 { bfd_mach_arm_5TE, "fa626te" },
181 { bfd_mach_arm_5TE, "fa726te" },
182 { bfd_mach_arm_5TE, "fmp626" },
183 { bfd_mach_arm_XScale, "i80200" },
184 { bfd_mach_arm_7, "marvell-pj4" },
185 { bfd_mach_arm_7, "marvell-whitney" },
186 { bfd_mach_arm_6K, "mpcore" },
187 { bfd_mach_arm_6K, "mpcorenovfp" },
188 { bfd_mach_arm_4, "sa1" },
189 { bfd_mach_arm_4, "strongarm" },
190 { bfd_mach_arm_4, "strongarm1" },
191 { bfd_mach_arm_4, "strongarm110" },
192 { bfd_mach_arm_4, "strongarm1100" },
193 { bfd_mach_arm_4, "strongarm1110" },
194 { bfd_mach_arm_XScale, "xscale" },
195 { bfd_mach_arm_8, "xgene1" },
196 { bfd_mach_arm_8, "xgene2" },
14f45859 197 { bfd_mach_arm_9, "cortex-a710" },
b5ab3163
TP
198 { bfd_mach_arm_ep9312, "ep9312" },
199 { bfd_mach_arm_iWMMXt, "iwmmxt" },
200 { bfd_mach_arm_iWMMXt2, "iwmmxt2" },
201 { bfd_mach_arm_unknown, "arm_any" }
252b5132
RH
202};
203
0a1b45a2 204static bool
f075ee0c 205scan (const struct bfd_arch_info *info, const char *string)
252b5132
RH
206{
207 int i;
208
e2fd756b 209 /* First test for an exact match. */
252b5132 210 if (strcasecmp (string, info->printable_name) == 0)
0a1b45a2 211 return true;
252b5132 212
1a7e622b
NC
213 /* If there is a prefix of "arm:" then skip it. */
214 const char * colon;
215 if ((colon = strchr (string, ':')) != NULL)
216 {
217 if (strncasecmp (string, "arm", colon - string) != 0)
218 return false;
219 string = colon + 1;
220 }
221
e2fd756b 222 /* Next check for a processor name instead of an Architecture name. */
252b5132
RH
223 for (i = sizeof (processors) / sizeof (processors[0]); i--;)
224 {
e2fd756b 225 if (strcasecmp (string, processors [i].name) == 0)
252b5132
RH
226 break;
227 }
228
e2fd756b 229 if (i != -1 && info->mach == processors [i].mach)
0a1b45a2 230 return true;
252b5132 231
e2fd756b 232 /* Finally check for the default architecture. */
252b5132
RH
233 if (strcasecmp (string, "arm") == 0)
234 return info->the_default;
71f6b586 235
0a1b45a2 236 return false;
252b5132
RH
237}
238
252b5132 239#define N(number, print, default, next) \
b7761f11 240{ 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
aebcfb76 241 scan, bfd_arch_default_fill, next, 0 }
252b5132
RH
242
243static const bfd_arch_info_type arch_info_struct[] =
71f6b586 244{
0a1b45a2
AM
245 N (bfd_mach_arm_2, "armv2", false, & arch_info_struct[1]),
246 N (bfd_mach_arm_2a, "armv2a", false, & arch_info_struct[2]),
247 N (bfd_mach_arm_3, "armv3", false, & arch_info_struct[3]),
248 N (bfd_mach_arm_3M, "armv3m", false, & arch_info_struct[4]),
249 N (bfd_mach_arm_4, "armv4", false, & arch_info_struct[5]),
250 N (bfd_mach_arm_4T, "armv4t", false, & arch_info_struct[6]),
251 N (bfd_mach_arm_5, "armv5", false, & arch_info_struct[7]),
252 N (bfd_mach_arm_5T, "armv5t", false, & arch_info_struct[8]),
253 N (bfd_mach_arm_5TE, "armv5te", false, & arch_info_struct[9]),
254 N (bfd_mach_arm_XScale, "xscale", false, & arch_info_struct[10]),
255 N (bfd_mach_arm_ep9312, "ep9312", false, & arch_info_struct[11]),
256 N (bfd_mach_arm_iWMMXt, "iwmmxt", false, & arch_info_struct[12]),
257 N (bfd_mach_arm_iWMMXt2, "iwmmxt2", false, & arch_info_struct[13]),
258 N (bfd_mach_arm_5TEJ, "armv5tej", false, & arch_info_struct[14]),
259 N (bfd_mach_arm_6, "armv6", false, & arch_info_struct[15]),
260 N (bfd_mach_arm_6KZ, "armv6kz", false, & arch_info_struct[16]),
261 N (bfd_mach_arm_6T2, "armv6t2", false, & arch_info_struct[17]),
262 N (bfd_mach_arm_6K, "armv6k", false, & arch_info_struct[18]),
263 N (bfd_mach_arm_7, "armv7", false, & arch_info_struct[19]),
264 N (bfd_mach_arm_6M, "armv6-m", false, & arch_info_struct[20]),
265 N (bfd_mach_arm_6SM, "armv6s-m", false, & arch_info_struct[21]),
266 N (bfd_mach_arm_7EM, "armv7e-m", false, & arch_info_struct[22]),
267 N (bfd_mach_arm_8, "armv8-a", false, & arch_info_struct[23]),
268 N (bfd_mach_arm_8R, "armv8-r", false, & arch_info_struct[24]),
269 N (bfd_mach_arm_8M_BASE, "armv8-m.base", false, & arch_info_struct[25]),
270 N (bfd_mach_arm_8M_MAIN, "armv8-m.main", false, & arch_info_struct[26]),
271 N (bfd_mach_arm_8_1M_MAIN, "armv8.1-m.main", false, & arch_info_struct[27]),
3197e593 272 N (bfd_mach_arm_9, "armv9-a", false, & arch_info_struct[28]),
0a1b45a2 273 N (bfd_mach_arm_unknown, "arm_any", false, NULL)
252b5132
RH
274};
275
276const bfd_arch_info_type bfd_arm_arch =
0a1b45a2 277 N (0, "arm", true, & arch_info_struct[0]);
5a6c6817
NC
278
279/* Support functions used by both the COFF and ELF versions of the ARM port. */
280
5c4491d3 281/* Handle the merging of the 'machine' settings of input file IBFD
5a6c6817
NC
282 and an output file OBFD. These values actually represent the
283 different possible ARM architecture variants.
284 Returns TRUE if they were merged successfully or FALSE otherwise. */
285
0a1b45a2 286bool
f075ee0c 287bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
5a6c6817
NC
288{
289 unsigned int in = bfd_get_mach (ibfd);
290 unsigned int out = bfd_get_mach (obfd);
291
292 /* If the output architecture is unknown, we now have a value to set. */
293 if (out == bfd_mach_arm_unknown)
294 bfd_set_arch_mach (obfd, bfd_arch_arm, in);
295
5c4491d3 296 /* If the input architecture is unknown,
5a6c6817
NC
297 then so must be the output architecture. */
298 else if (in == bfd_mach_arm_unknown)
299 /* FIXME: We ought to have some way to
300 override this on the command line. */
301 bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
302
303 /* If they are the same then nothing needs to be done. */
304 else if (out == in)
305 ;
306
307 /* Otherwise the general principle that a earlier architecture can be
5c4491d3 308 linked with a later architecture to produce a binary that will execute
5a6c6817
NC
309 on the later architecture.
310
311 We fail however if we attempt to link a Cirrus EP9312 binary with an
312 Intel XScale binary, since these architecture have co-processors which
313 will not both be present on the same physical hardware. */
314 else if (in == bfd_mach_arm_ep9312
2d447fca
JM
315 && (out == bfd_mach_arm_XScale
316 || out == bfd_mach_arm_iWMMXt
317 || out == bfd_mach_arm_iWMMXt2))
5a6c6817 318 {
695344c0 319 /* xgettext: c-format */
dc1e8a47
AM
320 _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
321 "whereas %pB is compiled for XScale"),
d003868e 322 ibfd, obfd);
5a6c6817 323 bfd_set_error (bfd_error_wrong_format);
0a1b45a2 324 return false;
5a6c6817
NC
325 }
326 else if (out == bfd_mach_arm_ep9312
2d447fca
JM
327 && (in == bfd_mach_arm_XScale
328 || in == bfd_mach_arm_iWMMXt
329 || in == bfd_mach_arm_iWMMXt2))
5a6c6817 330 {
695344c0 331 /* xgettext: c-format */
dc1e8a47
AM
332 _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
333 "whereas %pB is compiled for XScale"),
d003868e 334 obfd, ibfd);
5a6c6817 335 bfd_set_error (bfd_error_wrong_format);
0a1b45a2 336 return false;
5a6c6817
NC
337 }
338 else if (in > out)
339 bfd_set_arch_mach (obfd, bfd_arch_arm, in);
340 /* else
341 Nothing to do. */
342
0a1b45a2 343 return true;
5a6c6817
NC
344}
345
346typedef struct
347{
348 unsigned char namesz[4]; /* Size of entry's owner string. */
349 unsigned char descsz[4]; /* Size of the note descriptor. */
350 unsigned char type[4]; /* Interpretation of the descriptor. */
351 char name[1]; /* Start of the name+desc data. */
352} arm_Note;
353
0a1b45a2 354static bool
f075ee0c
AM
355arm_check_note (bfd *abfd,
356 bfd_byte *buffer,
357 bfd_size_type buffer_size,
358 const char *expected_name,
359 char **description_return)
5a6c6817
NC
360{
361 unsigned long namesz;
362 unsigned long descsz;
363 unsigned long type;
07d6d2b8 364 char * descr;
5a6c6817
NC
365
366 if (buffer_size < offsetof (arm_Note, name))
0a1b45a2 367 return false;
5a6c6817
NC
368
369 /* We have to extract the values this way to allow for a
370 host whose endian-ness is different from the target. */
371 namesz = bfd_get_32 (abfd, buffer);
372 descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
373 type = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
f075ee0c 374 descr = (char *) buffer + offsetof (arm_Note, name);
5a6c6817
NC
375
376 /* Check for buffer overflow. */
377 if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
0a1b45a2 378 return false;
5a6c6817
NC
379
380 if (expected_name == NULL)
381 {
382 if (namesz != 0)
0a1b45a2 383 return false;
5a6c6817
NC
384 }
385 else
68ffbac6 386 {
60d8b524 387 if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
0a1b45a2 388 return false;
68ffbac6 389
5a6c6817 390 if (strcmp (descr, expected_name) != 0)
0a1b45a2 391 return false;
5a6c6817
NC
392
393 descr += (namesz + 3) & ~3;
394 }
395
396 /* FIXME: We should probably check the type as well. */
c7e2358a 397 (void) type;
5a6c6817
NC
398
399 if (description_return != NULL)
400 * description_return = descr;
401
0a1b45a2 402 return true;
5a6c6817
NC
403}
404
07d6d2b8 405#define NOTE_ARCH_STRING "arch: "
5a6c6817 406
0a1b45a2 407bool
f075ee0c 408bfd_arm_update_notes (bfd *abfd, const char *note_section)
5a6c6817 409{
07d6d2b8
AM
410 asection * arm_arch_section;
411 bfd_size_type buffer_size;
412 bfd_byte * buffer;
413 char * arch_string;
414 char * expected;
5a6c6817
NC
415
416 /* Look for a note section. If one is present check the architecture
417 string encoded in it, and set it to the current architecture if it is
418 different. */
419 arm_arch_section = bfd_get_section_by_name (abfd, note_section);
420
421 if (arm_arch_section == NULL)
0a1b45a2 422 return true;
5a6c6817 423
eea6121a 424 buffer_size = arm_arch_section->size;
5a6c6817 425 if (buffer_size == 0)
0a1b45a2 426 return false;
5a6c6817 427
eea6121a 428 if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
5a6c6817
NC
429 goto FAIL;
430
431 /* Parse the note. */
432 if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
433 goto FAIL;
434
b5ab3163
TP
435 /* Check the architecture in the note against the architecture of the bfd.
436 Newer architectures versions should not be added here as build attribute
437 are a better mechanism to convey ISA used. */
5a6c6817
NC
438 switch (bfd_get_mach (abfd))
439 {
440 default:
441 case bfd_mach_arm_unknown: expected = "unknown"; break;
442 case bfd_mach_arm_2: expected = "armv2"; break;
443 case bfd_mach_arm_2a: expected = "armv2a"; break;
444 case bfd_mach_arm_3: expected = "armv3"; break;
445 case bfd_mach_arm_3M: expected = "armv3M"; break;
446 case bfd_mach_arm_4: expected = "armv4"; break;
447 case bfd_mach_arm_4T: expected = "armv4t"; break;
448 case bfd_mach_arm_5: expected = "armv5"; break;
449 case bfd_mach_arm_5T: expected = "armv5t"; break;
450 case bfd_mach_arm_5TE: expected = "armv5te"; break;
451 case bfd_mach_arm_XScale: expected = "XScale"; break;
452 case bfd_mach_arm_ep9312: expected = "ep9312"; break;
453 case bfd_mach_arm_iWMMXt: expected = "iWMMXt"; break;
2d447fca 454 case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
5a6c6817
NC
455 }
456
457 if (strcmp (arch_string, expected) != 0)
458 {
f075ee0c
AM
459 strcpy ((char *) buffer + (offsetof (arm_Note, name)
460 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
461 expected);
5a6c6817
NC
462
463 if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
464 (file_ptr) 0, buffer_size))
465 {
4eca0228 466 _bfd_error_handler
695344c0 467 /* xgettext: c-format */
871b3ab2 468 (_("warning: unable to update contents of %s section in %pB"),
dae82561 469 note_section, abfd);
5a6c6817
NC
470 goto FAIL;
471 }
472 }
473
474 free (buffer);
0a1b45a2 475 return true;
5a6c6817
NC
476
477 FAIL:
c9594989 478 free (buffer);
0a1b45a2 479 return false;
5a6c6817
NC
480}
481
482
483static struct
484{
485 const char * string;
486 unsigned int mach;
487}
b5ab3163
TP
488
489/* Newer architectures versions should not be added here as build attribute are
490 a better mechanism to convey ISA used. */
5a6c6817
NC
491architectures[] =
492{
493 { "armv2", bfd_mach_arm_2 },
494 { "armv2a", bfd_mach_arm_2a },
495 { "armv3", bfd_mach_arm_3 },
496 { "armv3M", bfd_mach_arm_3M },
497 { "armv4", bfd_mach_arm_4 },
498 { "armv4t", bfd_mach_arm_4T },
499 { "armv5", bfd_mach_arm_5 },
500 { "armv5t", bfd_mach_arm_5T },
501 { "armv5te", bfd_mach_arm_5TE },
502 { "XScale", bfd_mach_arm_XScale },
503 { "ep9312", bfd_mach_arm_ep9312 },
2d447fca 504 { "iWMMXt", bfd_mach_arm_iWMMXt },
99914dfd
NC
505 { "iWMMXt2", bfd_mach_arm_iWMMXt2 },
506 { "arm_any", bfd_mach_arm_unknown }
5a6c6817
NC
507};
508
509/* Extract the machine number stored in a note section. */
510unsigned int
f075ee0c 511bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
5a6c6817 512{
07d6d2b8
AM
513 asection * arm_arch_section;
514 bfd_size_type buffer_size;
515 bfd_byte * buffer;
516 char * arch_string;
517 int i;
5a6c6817
NC
518
519 /* Look for a note section. If one is present check the architecture
520 string encoded in it, and set it to the current architecture if it is
521 different. */
522 arm_arch_section = bfd_get_section_by_name (abfd, note_section);
523
524 if (arm_arch_section == NULL)
525 return bfd_mach_arm_unknown;
526
eea6121a 527 buffer_size = arm_arch_section->size;
5a6c6817
NC
528 if (buffer_size == 0)
529 return bfd_mach_arm_unknown;
530
eea6121a 531 if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
5a6c6817
NC
532 goto FAIL;
533
534 /* Parse the note. */
535 if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
536 goto FAIL;
537
538 /* Interpret the architecture string. */
539 for (i = ARRAY_SIZE (architectures); i--;)
540 if (strcmp (arch_string, architectures[i].string) == 0)
541 {
542 free (buffer);
543 return architectures[i].mach;
544 }
545
546 FAIL:
c9594989 547 free (buffer);
5a6c6817
NC
548 return bfd_mach_arm_unknown;
549}
9d2da7ca 550
0a1b45a2 551bool
b0796911 552bfd_is_arm_special_symbol_name (const char * name, int type)
9d2da7ca 553{
38406048 554 /* The ARM compiler outputs several obsolete forms. Recognize them
efacb0fb
DJ
555 in addition to the standard $a, $t and $d. We are somewhat loose
556 in what we accept here, since the full set is not documented. */
b0796911 557 if (!name || name[0] != '$')
0a1b45a2 558 return false;
b0796911
PB
559 if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
560 type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
561 else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
562 type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
563 else if (name[1] >= 'a' && name[1] <= 'z')
564 type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
565 else
0a1b45a2 566 return false;
b0796911
PB
567
568 return (type != 0 && (name[2] == 0 || name[2] == '.'));
9d2da7ca
JB
569}
570