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