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