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