xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/cpu-arm.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* BFD support for the ARM processor
2    Copyright (C) 1994-2020 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 *
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_6SM,	  "cortex-m0"	    },
154   { bfd_mach_arm_6SM,	  "cortex-m0plus"   },
155   { bfd_mach_arm_6SM,	  "cortex-m1"	    },
156   { bfd_mach_arm_8M_BASE, "cortex-m23"	    },
157   { bfd_mach_arm_7,	  "cortex-m3"	    },
158   { bfd_mach_arm_8M_MAIN, "cortex-m33"	    },
159   { bfd_mach_arm_8M_MAIN, "cortex-m35p"	    },
160   { bfd_mach_arm_7EM,	  "cortex-m4"	    },
161   { bfd_mach_arm_7EM,	  "cortex-m7"	    },
162   { bfd_mach_arm_7,	  "cortex-r4"	    },
163   { bfd_mach_arm_7,	  "cortex-r4f"	    },
164   { bfd_mach_arm_7,	  "cortex-r5"	    },
165   { bfd_mach_arm_8R,	  "cortex-r52"	    },
166   { bfd_mach_arm_7,	  "cortex-r7"	    },
167   { bfd_mach_arm_7,	  "cortex-r8"	    },
168   { bfd_mach_arm_4T,	  "ep9312"	    },
169   { bfd_mach_arm_8,	  "exynos-m1"	    },
170   { bfd_mach_arm_4,	  "fa526"	    },
171   { bfd_mach_arm_5TE,	  "fa606te"	    },
172   { bfd_mach_arm_5TE,	  "fa616te"	    },
173   { bfd_mach_arm_4,	  "fa626"	    },
174   { bfd_mach_arm_5TE,	  "fa626te"	    },
175   { bfd_mach_arm_5TE,	  "fa726te"	    },
176   { bfd_mach_arm_5TE,	  "fmp626"	    },
177   { bfd_mach_arm_XScale,  "i80200"	    },
178   { bfd_mach_arm_7,	  "marvell-pj4"	    },
179   { bfd_mach_arm_7,	  "marvell-whitney" },
180   { bfd_mach_arm_6K,	  "mpcore"	    },
181   { bfd_mach_arm_6K,	  "mpcorenovfp"	    },
182   { bfd_mach_arm_4,	  "sa1"		    },
183   { bfd_mach_arm_4,	  "strongarm"	    },
184   { bfd_mach_arm_4,	  "strongarm1"	    },
185   { bfd_mach_arm_4,	  "strongarm110"    },
186   { bfd_mach_arm_4,	  "strongarm1100"   },
187   { bfd_mach_arm_4,	  "strongarm1110"   },
188   { bfd_mach_arm_XScale,  "xscale"	    },
189   { bfd_mach_arm_8,	  "xgene1"	    },
190   { bfd_mach_arm_8,	  "xgene2"	    },
191   { bfd_mach_arm_ep9312,  "ep9312"	    },
192   { bfd_mach_arm_iWMMXt,  "iwmmxt"	    },
193   { bfd_mach_arm_iWMMXt2, "iwmmxt2"	    },
194   { bfd_mach_arm_unknown, "arm_any"	    }
195 };
196 
197 static bfd_boolean
198 scan (const struct bfd_arch_info *info, const char *string)
199 {
200   int  i;
201 
202   /* First test for an exact match.  */
203   if (strcasecmp (string, info->printable_name) == 0)
204     return TRUE;
205 
206   /* Next check for a processor name instead of an Architecture name.  */
207   for (i = sizeof (processors) / sizeof (processors[0]); i--;)
208     {
209       if (strcasecmp (string, processors [i].name) == 0)
210 	break;
211     }
212 
213   if (i != -1 && info->mach == processors [i].mach)
214     return TRUE;
215 
216   /* Finally check for the default architecture.  */
217   if (strcasecmp (string, "arm") == 0)
218     return info->the_default;
219 
220   return FALSE;
221 }
222 
223 #define N(number, print, default, next)  \
224 {  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
225     scan, bfd_arch_default_fill, next, 0 }
226 
227 static const bfd_arch_info_type arch_info_struct[] =
228 {
229   N (bfd_mach_arm_2,         "armv2",          FALSE, & arch_info_struct[1]),
230   N (bfd_mach_arm_2a,        "armv2a",         FALSE, & arch_info_struct[2]),
231   N (bfd_mach_arm_3,         "armv3",          FALSE, & arch_info_struct[3]),
232   N (bfd_mach_arm_3M,        "armv3m",         FALSE, & arch_info_struct[4]),
233   N (bfd_mach_arm_4,         "armv4",          FALSE, & arch_info_struct[5]),
234   N (bfd_mach_arm_4T,        "armv4t",         FALSE, & arch_info_struct[6]),
235   N (bfd_mach_arm_5,         "armv5",          FALSE, & arch_info_struct[7]),
236   N (bfd_mach_arm_5T,        "armv5t",         FALSE, & arch_info_struct[8]),
237   N (bfd_mach_arm_5TE,       "armv5te",        FALSE, & arch_info_struct[9]),
238   N (bfd_mach_arm_XScale,    "xscale",         FALSE, & arch_info_struct[10]),
239   N (bfd_mach_arm_ep9312,    "ep9312",         FALSE, & arch_info_struct[11]),
240   N (bfd_mach_arm_iWMMXt,    "iwmmxt",         FALSE, & arch_info_struct[12]),
241   N (bfd_mach_arm_iWMMXt2,   "iwmmxt2",        FALSE, & arch_info_struct[13]),
242   N (bfd_mach_arm_5TEJ,      "armv5tej",       FALSE, & arch_info_struct[14]),
243   N (bfd_mach_arm_6,         "armv6",          FALSE, & arch_info_struct[15]),
244   N (bfd_mach_arm_6KZ,       "armv6kz",        FALSE, & arch_info_struct[16]),
245   N (bfd_mach_arm_6T2,       "armv6t2",        FALSE, & arch_info_struct[17]),
246   N (bfd_mach_arm_6K,        "armv6k",         FALSE, & arch_info_struct[18]),
247   N (bfd_mach_arm_7,         "armv7",          FALSE, & arch_info_struct[19]),
248   N (bfd_mach_arm_6M,        "armv6-m",        FALSE, & arch_info_struct[20]),
249   N (bfd_mach_arm_6SM,       "armv6s-m",       FALSE, & arch_info_struct[21]),
250   N (bfd_mach_arm_7EM,       "armv7e-m",       FALSE, & arch_info_struct[22]),
251   N (bfd_mach_arm_8,         "armv8-a",        FALSE, & arch_info_struct[23]),
252   N (bfd_mach_arm_8R,        "armv8-r",        FALSE, & arch_info_struct[24]),
253   N (bfd_mach_arm_8M_BASE,   "armv8-m.base",   FALSE, & arch_info_struct[25]),
254   N (bfd_mach_arm_8M_MAIN,   "armv8-m.main",   FALSE, & arch_info_struct[26]),
255   N (bfd_mach_arm_8_1M_MAIN, "armv8.1-m.main", FALSE, & arch_info_struct[27]),
256   N (bfd_mach_arm_unknown,   "arm_any",        FALSE, NULL)
257 };
258 
259 const bfd_arch_info_type bfd_arm_arch =
260   N (0, "arm", TRUE, & arch_info_struct[0]);
261 
262 /* Support functions used by both the COFF and ELF versions of the ARM port.  */
263 
264 /* Handle the merging of the 'machine' settings of input file IBFD
265    and an output file OBFD.  These values actually represent the
266    different possible ARM architecture variants.
267    Returns TRUE if they were merged successfully or FALSE otherwise.  */
268 
269 bfd_boolean
270 bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
271 {
272   unsigned int in  = bfd_get_mach (ibfd);
273   unsigned int out = bfd_get_mach (obfd);
274 
275   /* If the output architecture is unknown, we now have a value to set.  */
276   if (out == bfd_mach_arm_unknown)
277     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
278 
279   /* If the input architecture is unknown,
280      then so must be the output architecture.  */
281   else if (in == bfd_mach_arm_unknown)
282     /* FIXME: We ought to have some way to
283        override this on the command line.  */
284     bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
285 
286   /* If they are the same then nothing needs to be done.  */
287   else if (out == in)
288     ;
289 
290   /* Otherwise the general principle that a earlier architecture can be
291      linked with a later architecture to produce a binary that will execute
292      on the later architecture.
293 
294      We fail however if we attempt to link a Cirrus EP9312 binary with an
295      Intel XScale binary, since these architecture have co-processors which
296      will not both be present on the same physical hardware.  */
297   else if (in == bfd_mach_arm_ep9312
298 	   && (out == bfd_mach_arm_XScale
299 	       || out == bfd_mach_arm_iWMMXt
300 	       || out == bfd_mach_arm_iWMMXt2))
301     {
302       /* xgettext: c-format */
303       _bfd_error_handler (_("\
304 error: %pB is compiled for the EP9312, whereas %pB is compiled for XScale"),
305 			  ibfd, obfd);
306       bfd_set_error (bfd_error_wrong_format);
307       return FALSE;
308     }
309   else if (out == bfd_mach_arm_ep9312
310 	   && (in == bfd_mach_arm_XScale
311 	       || in == bfd_mach_arm_iWMMXt
312 	       || in == bfd_mach_arm_iWMMXt2))
313     {
314       /* xgettext: c-format */
315       _bfd_error_handler (_("\
316 error: %pB is compiled for the EP9312, whereas %pB is compiled for XScale"),
317 			  obfd, ibfd);
318       bfd_set_error (bfd_error_wrong_format);
319       return FALSE;
320     }
321   else if (in > out)
322     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
323   /* else
324      Nothing to do.  */
325 
326   return TRUE;
327 }
328 
329 typedef struct
330 {
331   unsigned char	namesz[4];	/* Size of entry's owner string.  */
332   unsigned char	descsz[4];	/* Size of the note descriptor.  */
333   unsigned char	type[4];	/* Interpretation of the descriptor.  */
334   char		name[1];	/* Start of the name+desc data.  */
335 } arm_Note;
336 
337 static bfd_boolean
338 arm_check_note (bfd *abfd,
339 		bfd_byte *buffer,
340 		bfd_size_type buffer_size,
341 		const char *expected_name,
342 		char **description_return)
343 {
344   unsigned long namesz;
345   unsigned long descsz;
346   unsigned long type;
347   char *	descr;
348 
349   if (buffer_size < offsetof (arm_Note, name))
350     return FALSE;
351 
352   /* We have to extract the values this way to allow for a
353      host whose endian-ness is different from the target.  */
354   namesz = bfd_get_32 (abfd, buffer);
355   descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
356   type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
357   descr  = (char *) buffer + offsetof (arm_Note, name);
358 
359   /* Check for buffer overflow.  */
360   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
361     return FALSE;
362 
363   if (expected_name == NULL)
364     {
365       if (namesz != 0)
366 	return FALSE;
367     }
368   else
369     {
370       if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
371 	return FALSE;
372 
373       if (strcmp (descr, expected_name) != 0)
374 	return FALSE;
375 
376       descr += (namesz + 3) & ~3;
377     }
378 
379   /* FIXME: We should probably check the type as well.  */
380   (void) type;
381 
382   if (description_return != NULL)
383     * description_return = descr;
384 
385   return TRUE;
386 }
387 
388 #define NOTE_ARCH_STRING	"arch: "
389 
390 bfd_boolean
391 bfd_arm_update_notes (bfd *abfd, const char *note_section)
392 {
393   asection *	 arm_arch_section;
394   bfd_size_type	 buffer_size;
395   bfd_byte *	 buffer;
396   char *	 arch_string;
397   char *	 expected;
398 
399   /* Look for a note section.  If one is present check the architecture
400      string encoded in it, and set it to the current architecture if it is
401      different.  */
402   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
403 
404   if (arm_arch_section == NULL)
405     return TRUE;
406 
407   buffer_size = arm_arch_section->size;
408   if (buffer_size == 0)
409     return FALSE;
410 
411   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
412     goto FAIL;
413 
414   /* Parse the note.  */
415   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
416     goto FAIL;
417 
418   /* Check the architecture in the note against the architecture of the bfd.
419      Newer architectures versions should not be added here as build attribute
420      are a better mechanism to convey ISA used.  */
421   switch (bfd_get_mach (abfd))
422     {
423     default:
424     case bfd_mach_arm_unknown: expected = "unknown"; break;
425     case bfd_mach_arm_2:       expected = "armv2"; break;
426     case bfd_mach_arm_2a:      expected = "armv2a"; break;
427     case bfd_mach_arm_3:       expected = "armv3"; break;
428     case bfd_mach_arm_3M:      expected = "armv3M"; break;
429     case bfd_mach_arm_4:       expected = "armv4"; break;
430     case bfd_mach_arm_4T:      expected = "armv4t"; break;
431     case bfd_mach_arm_5:       expected = "armv5"; break;
432     case bfd_mach_arm_5T:      expected = "armv5t"; break;
433     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
434     case bfd_mach_arm_XScale:  expected = "XScale"; break;
435     case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
436     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
437     case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
438     }
439 
440   if (strcmp (arch_string, expected) != 0)
441     {
442       strcpy ((char *) buffer + (offsetof (arm_Note, name)
443 				 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
444 	      expected);
445 
446       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
447 				      (file_ptr) 0, buffer_size))
448 	{
449 	  _bfd_error_handler
450 	    /* xgettext: c-format */
451 	    (_("warning: unable to update contents of %s section in %pB"),
452 	     note_section, abfd);
453 	  goto FAIL;
454 	}
455     }
456 
457   free (buffer);
458   return TRUE;
459 
460  FAIL:
461   if (buffer != NULL)
462     free (buffer);
463   return FALSE;
464 }
465 
466 
467 static struct
468 {
469   const char * string;
470   unsigned int mach;
471 }
472 
473 /* Newer architectures versions should not be added here as build attribute are
474    a better mechanism to convey ISA used.  */
475 architectures[] =
476 {
477   { "armv2",   bfd_mach_arm_2 },
478   { "armv2a",  bfd_mach_arm_2a },
479   { "armv3",   bfd_mach_arm_3 },
480   { "armv3M",  bfd_mach_arm_3M },
481   { "armv4",   bfd_mach_arm_4 },
482   { "armv4t",  bfd_mach_arm_4T },
483   { "armv5",   bfd_mach_arm_5 },
484   { "armv5t",  bfd_mach_arm_5T },
485   { "armv5te", bfd_mach_arm_5TE },
486   { "XScale",  bfd_mach_arm_XScale },
487   { "ep9312",  bfd_mach_arm_ep9312 },
488   { "iWMMXt",  bfd_mach_arm_iWMMXt },
489   { "iWMMXt2", bfd_mach_arm_iWMMXt2 },
490   { "arm_any", bfd_mach_arm_unknown }
491 };
492 
493 /* Extract the machine number stored in a note section.  */
494 unsigned int
495 bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
496 {
497   asection *	 arm_arch_section;
498   bfd_size_type	 buffer_size;
499   bfd_byte *	 buffer;
500   char *	 arch_string;
501   int		 i;
502 
503   /* Look for a note section.  If one is present check the architecture
504      string encoded in it, and set it to the current architecture if it is
505      different.  */
506   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
507 
508   if (arm_arch_section == NULL)
509     return bfd_mach_arm_unknown;
510 
511   buffer_size = arm_arch_section->size;
512   if (buffer_size == 0)
513     return bfd_mach_arm_unknown;
514 
515   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
516     goto FAIL;
517 
518   /* Parse the note.  */
519   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
520     goto FAIL;
521 
522   /* Interpret the architecture string.  */
523   for (i = ARRAY_SIZE (architectures); i--;)
524     if (strcmp (arch_string, architectures[i].string) == 0)
525       {
526 	free (buffer);
527 	return architectures[i].mach;
528       }
529 
530  FAIL:
531   if (buffer != NULL)
532     free (buffer);
533   return bfd_mach_arm_unknown;
534 }
535 
536 bfd_boolean
537 bfd_is_arm_special_symbol_name (const char * name, int type)
538 {
539   /* The ARM compiler outputs several obsolete forms.  Recognize them
540      in addition to the standard $a, $t and $d.  We are somewhat loose
541      in what we accept here, since the full set is not documented.  */
542   if (!name || name[0] != '$')
543     return FALSE;
544   if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
545     type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
546   else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
547     type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
548   else if (name[1] >= 'a' && name[1] <= 'z')
549     type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
550   else
551     return FALSE;
552 
553   return (type != 0 && (name[2] == 0 || name[2] == '.'));
554 }
555 
556