xref: /netbsd-src/external/gpl3/binutils/dist/bfd/cpu-arm.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* BFD support for the ARM processor
2    Copyright (C) 1994-2024 Free Software Foundation, Inc.
3    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
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
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
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.
16 
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
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "libiberty.h"
26 #include "cpu-arm.h"
27 
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
30    to its info structure.  */
31 
32 static const bfd_arch_info_type *
compatible(const bfd_arch_info_type * a,const bfd_arch_info_type * b)33 compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
34 {
35   /* If a & b are for different architecture we can do nothing.  */
36   if (a->arch != b->arch)
37       return NULL;
38 
39   /* If a & b are for the same machine then all is well.  */
40   if (a->mach == b->mach)
41     return a;
42 
43   /* Otherwise if either a or b is the 'default' machine
44      then it can be polymorphed into the other.  */
45   if (a->the_default)
46     return b;
47 
48   if (b->the_default)
49     return a;
50 
51   /* So far all newer ARM architecture cores are
52      supersets of previous cores.  */
53   if (a->mach < b->mach)
54     return b;
55   else if (a->mach > b->mach)
56     return a;
57 
58   /* Never reached!  */
59   return NULL;
60 }
61 
62 static struct
63 {
64   unsigned int mach;
65   char *       name;
66 }
67 processors[] =
68 {
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"	    },
151   { bfd_mach_arm_8,	  "cortex-a76ae"    },
152   { bfd_mach_arm_8,	  "cortex-a77"	    },
153   { bfd_mach_arm_8,	  "cortex-a78"	    },
154   { bfd_mach_arm_8,	  "cortex-a78ae"    },
155   { bfd_mach_arm_8,	  "cortex-a78c"     },
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"	    },
162   { bfd_mach_arm_8M_MAIN, "cortex-m35p"	    },
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"	    },
169   { bfd_mach_arm_8R,	  "cortex-r52plus"	    },
170   { bfd_mach_arm_7,	  "cortex-r7"	    },
171   { bfd_mach_arm_7,	  "cortex-r8"	    },
172   { bfd_mach_arm_8,	  "cortex-x1"	    },
173   { bfd_mach_arm_8,	  "cortex-x1c"	    },
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"	    },
197   { bfd_mach_arm_9,	  "cortex-a710"	    },
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"	    }
202 };
203 
204 static bool
scan(const struct bfd_arch_info * info,const char * string)205 scan (const struct bfd_arch_info *info, const char *string)
206 {
207   int  i;
208 
209   /* First test for an exact match.  */
210   if (strcasecmp (string, info->printable_name) == 0)
211     return true;
212 
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 
222   /* Next check for a processor name instead of an Architecture name.  */
223   for (i = sizeof (processors) / sizeof (processors[0]); i--;)
224     {
225       if (strcasecmp (string, processors [i].name) == 0)
226 	break;
227     }
228 
229   if (i != -1 && info->mach == processors [i].mach)
230     return true;
231 
232   /* Finally check for the default architecture.  */
233   if (strcasecmp (string, "arm") == 0)
234     return info->the_default;
235 
236   return false;
237 }
238 
239 #define N(number, print, default, next)  \
240 {  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
241     scan, bfd_arch_default_fill, next, 0 }
242 
243 static const bfd_arch_info_type arch_info_struct[] =
244 {
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]),
272   N (bfd_mach_arm_9,         "armv9-a",        false, & arch_info_struct[28]),
273   N (bfd_mach_arm_unknown,   "arm_any",        false, NULL)
274 };
275 
276 const bfd_arch_info_type bfd_arm_arch =
277   N (0, "arm", true, & arch_info_struct[0]);
278 
279 /* Support functions used by both the COFF and ELF versions of the ARM port.  */
280 
281 /* Handle the merging of the 'machine' settings of input file IBFD
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 
286 bool
bfd_arm_merge_machines(bfd * ibfd,bfd * obfd)287 bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
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 
296   /* If the input architecture is unknown,
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
308      linked with a later architecture to produce a binary that will execute
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
315 	   && (out == bfd_mach_arm_XScale
316 	       || out == bfd_mach_arm_iWMMXt
317 	       || out == bfd_mach_arm_iWMMXt2))
318     {
319       /* xgettext: c-format */
320       _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
321 			    "whereas %pB is compiled for XScale"),
322 			  ibfd, obfd);
323       bfd_set_error (bfd_error_wrong_format);
324       return false;
325     }
326   else if (out == bfd_mach_arm_ep9312
327 	   && (in == bfd_mach_arm_XScale
328 	       || in == bfd_mach_arm_iWMMXt
329 	       || in == bfd_mach_arm_iWMMXt2))
330     {
331       /* xgettext: c-format */
332       _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
333 			    "whereas %pB is compiled for XScale"),
334 			  obfd, ibfd);
335       bfd_set_error (bfd_error_wrong_format);
336       return false;
337     }
338   else if (in > out)
339     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
340   /* else
341      Nothing to do.  */
342 
343   return true;
344 }
345 
346 typedef 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 
354 static bool
arm_check_note(bfd * abfd,bfd_byte * buffer,bfd_size_type buffer_size,const char * expected_name,char ** description_return)355 arm_check_note (bfd *abfd,
356 		bfd_byte *buffer,
357 		bfd_size_type buffer_size,
358 		const char *expected_name,
359 		char **description_return)
360 {
361   unsigned long namesz;
362   unsigned long descsz;
363   unsigned long type;
364   char *	descr;
365 
366   if (buffer_size < offsetof (arm_Note, name))
367     return false;
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));
374   descr  = (char *) buffer + offsetof (arm_Note, name);
375 
376   /* Check for buffer overflow.  */
377   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
378     return false;
379 
380   if (expected_name == NULL)
381     {
382       if (namesz != 0)
383 	return false;
384     }
385   else
386     {
387       if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
388 	return false;
389 
390       if (strcmp (descr, expected_name) != 0)
391 	return false;
392 
393       descr += (namesz + 3) & ~3;
394     }
395 
396   /* FIXME: We should probably check the type as well.  */
397   (void) type;
398 
399   if (description_return != NULL)
400     * description_return = descr;
401 
402   return true;
403 }
404 
405 #define NOTE_ARCH_STRING	"arch: "
406 
407 bool
bfd_arm_update_notes(bfd * abfd,const char * note_section)408 bfd_arm_update_notes (bfd *abfd, const char *note_section)
409 {
410   asection *	 arm_arch_section;
411   bfd_size_type	 buffer_size;
412   bfd_byte *	 buffer;
413   char *	 arch_string;
414   char *	 expected;
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
422       || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0)
423     return true;
424 
425   buffer_size = arm_arch_section->size;
426   if (buffer_size == 0)
427     return false;
428 
429   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
430     goto FAIL;
431 
432   /* Parse the note.  */
433   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
434     goto FAIL;
435 
436   /* Check the architecture in the note against the architecture of the bfd.
437      Newer architectures versions should not be added here as build attribute
438      are a better mechanism to convey ISA used.  */
439   switch (bfd_get_mach (abfd))
440     {
441     default:
442     case bfd_mach_arm_unknown: expected = "unknown"; break;
443     case bfd_mach_arm_2:       expected = "armv2"; break;
444     case bfd_mach_arm_2a:      expected = "armv2a"; break;
445     case bfd_mach_arm_3:       expected = "armv3"; break;
446     case bfd_mach_arm_3M:      expected = "armv3M"; break;
447     case bfd_mach_arm_4:       expected = "armv4"; break;
448     case bfd_mach_arm_4T:      expected = "armv4t"; break;
449     case bfd_mach_arm_5:       expected = "armv5"; break;
450     case bfd_mach_arm_5T:      expected = "armv5t"; break;
451     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
452     case bfd_mach_arm_XScale:  expected = "XScale"; break;
453     case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
454     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
455     case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
456     }
457 
458   if (strcmp (arch_string, expected) != 0)
459     {
460       strcpy ((char *) buffer + (offsetof (arm_Note, name)
461 				 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
462 	      expected);
463 
464       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
465 				      (file_ptr) 0, buffer_size))
466 	{
467 	  _bfd_error_handler
468 	    /* xgettext: c-format */
469 	    (_("warning: unable to update contents of %s section in %pB"),
470 	     note_section, abfd);
471 	  goto FAIL;
472 	}
473     }
474 
475   free (buffer);
476   return true;
477 
478  FAIL:
479   free (buffer);
480   return false;
481 }
482 
483 
484 static struct
485 {
486   const char * string;
487   unsigned int mach;
488 }
489 
490 /* Newer architectures versions should not be added here as build attribute are
491    a better mechanism to convey ISA used.  */
492 architectures[] =
493 {
494   { "armv2",   bfd_mach_arm_2 },
495   { "armv2a",  bfd_mach_arm_2a },
496   { "armv3",   bfd_mach_arm_3 },
497   { "armv3M",  bfd_mach_arm_3M },
498   { "armv4",   bfd_mach_arm_4 },
499   { "armv4t",  bfd_mach_arm_4T },
500   { "armv5",   bfd_mach_arm_5 },
501   { "armv5t",  bfd_mach_arm_5T },
502   { "armv5te", bfd_mach_arm_5TE },
503   { "XScale",  bfd_mach_arm_XScale },
504   { "ep9312",  bfd_mach_arm_ep9312 },
505   { "iWMMXt",  bfd_mach_arm_iWMMXt },
506   { "iWMMXt2", bfd_mach_arm_iWMMXt2 },
507   { "arm_any", bfd_mach_arm_unknown }
508 };
509 
510 /* Extract the machine number stored in a note section.  */
511 unsigned int
bfd_arm_get_mach_from_notes(bfd * abfd,const char * note_section)512 bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
513 {
514   asection *	 arm_arch_section;
515   bfd_size_type	 buffer_size;
516   bfd_byte *	 buffer;
517   char *	 arch_string;
518   int		 i;
519 
520   /* Look for a note section.  If one is present check the architecture
521      string encoded in it, and set it to the current architecture if it is
522      different.  */
523   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
524 
525   if (arm_arch_section == NULL
526       || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0)
527     return bfd_mach_arm_unknown;
528 
529   buffer_size = arm_arch_section->size;
530   if (buffer_size == 0)
531     return bfd_mach_arm_unknown;
532 
533   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
534     goto FAIL;
535 
536   /* Parse the note.  */
537   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
538     goto FAIL;
539 
540   /* Interpret the architecture string.  */
541   for (i = ARRAY_SIZE (architectures); i--;)
542     if (strcmp (arch_string, architectures[i].string) == 0)
543       {
544 	free (buffer);
545 	return architectures[i].mach;
546       }
547 
548  FAIL:
549   free (buffer);
550   return bfd_mach_arm_unknown;
551 }
552 
553 bool
bfd_is_arm_special_symbol_name(const char * name,int type)554 bfd_is_arm_special_symbol_name (const char * name, int type)
555 {
556   /* The ARM compiler outputs several obsolete forms.  Recognize them
557      in addition to the standard $a, $t and $d.  We are somewhat loose
558      in what we accept here, since the full set is not documented.  */
559   if (!name || name[0] != '$')
560     return false;
561   if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
562     type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
563   else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
564     type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
565   else if (name[1] >= 'a' && name[1] <= 'z')
566     type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
567   else
568     return false;
569 
570   return (type != 0 && (name[2] == 0 || name[2] == '.'));
571 }
572 
573