xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/cpu-arm.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* BFD support for the ARM processor
2*3d8817e4Smiod    Copyright 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2005
3*3d8817e4Smiod    Free Software Foundation, Inc.
4*3d8817e4Smiod    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of BFD, the Binary File Descriptor library.
7*3d8817e4Smiod 
8*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod    (at your option) any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod    GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with this program; if not, write to the Free Software
20*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod #include "bfd.h"
23*3d8817e4Smiod #include "sysdep.h"
24*3d8817e4Smiod #include "libbfd.h"
25*3d8817e4Smiod #include "libiberty.h"
26*3d8817e4Smiod 
27*3d8817e4Smiod /* This routine is provided two arch_infos and works out which ARM
28*3d8817e4Smiod    machine which would be compatible with both and returns a pointer
29*3d8817e4Smiod    to its info structure.  */
30*3d8817e4Smiod 
31*3d8817e4Smiod static const bfd_arch_info_type *
compatible(const bfd_arch_info_type * a,const bfd_arch_info_type * b)32*3d8817e4Smiod compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
33*3d8817e4Smiod {
34*3d8817e4Smiod   /* If a & b are for different architecture we can do nothing.  */
35*3d8817e4Smiod   if (a->arch != b->arch)
36*3d8817e4Smiod       return NULL;
37*3d8817e4Smiod 
38*3d8817e4Smiod   /* If a & b are for the same machine then all is well.  */
39*3d8817e4Smiod   if (a->mach == b->mach)
40*3d8817e4Smiod     return a;
41*3d8817e4Smiod 
42*3d8817e4Smiod   /* Otherwise if either a or b is the 'default' machine
43*3d8817e4Smiod      then it can be polymorphed into the other.  */
44*3d8817e4Smiod   if (a->the_default)
45*3d8817e4Smiod     return b;
46*3d8817e4Smiod 
47*3d8817e4Smiod   if (b->the_default)
48*3d8817e4Smiod     return a;
49*3d8817e4Smiod 
50*3d8817e4Smiod   /* So far all newer ARM architecture cores are
51*3d8817e4Smiod      supersets of previous cores.  */
52*3d8817e4Smiod   if (a->mach < b->mach)
53*3d8817e4Smiod     return b;
54*3d8817e4Smiod   else if (a->mach > b->mach)
55*3d8817e4Smiod     return a;
56*3d8817e4Smiod 
57*3d8817e4Smiod   /* Never reached!  */
58*3d8817e4Smiod   return NULL;
59*3d8817e4Smiod }
60*3d8817e4Smiod 
61*3d8817e4Smiod static struct
62*3d8817e4Smiod {
63*3d8817e4Smiod   unsigned int mach;
64*3d8817e4Smiod   char *       name;
65*3d8817e4Smiod }
66*3d8817e4Smiod processors[] =
67*3d8817e4Smiod {
68*3d8817e4Smiod   { bfd_mach_arm_2,  "arm2"     },
69*3d8817e4Smiod   { bfd_mach_arm_2a, "arm250"   },
70*3d8817e4Smiod   { bfd_mach_arm_2a, "arm3"     },
71*3d8817e4Smiod   { bfd_mach_arm_3,  "arm6"     },
72*3d8817e4Smiod   { bfd_mach_arm_3,  "arm60"    },
73*3d8817e4Smiod   { bfd_mach_arm_3,  "arm600"   },
74*3d8817e4Smiod   { bfd_mach_arm_3,  "arm610"   },
75*3d8817e4Smiod   { bfd_mach_arm_3,  "arm7"     },
76*3d8817e4Smiod   { bfd_mach_arm_3,  "arm710"   },
77*3d8817e4Smiod   { bfd_mach_arm_3,  "arm7500"  },
78*3d8817e4Smiod   { bfd_mach_arm_3,  "arm7d"    },
79*3d8817e4Smiod   { bfd_mach_arm_3,  "arm7di"   },
80*3d8817e4Smiod   { bfd_mach_arm_3M, "arm7dm"   },
81*3d8817e4Smiod   { bfd_mach_arm_3M, "arm7dmi"  },
82*3d8817e4Smiod   { bfd_mach_arm_4T, "arm7tdmi" },
83*3d8817e4Smiod   { bfd_mach_arm_4,  "arm8"     },
84*3d8817e4Smiod   { bfd_mach_arm_4,  "arm810"   },
85*3d8817e4Smiod   { bfd_mach_arm_4,  "arm9"     },
86*3d8817e4Smiod   { bfd_mach_arm_4,  "arm920"   },
87*3d8817e4Smiod   { bfd_mach_arm_4T, "arm920t"  },
88*3d8817e4Smiod   { bfd_mach_arm_4T, "arm9tdmi" },
89*3d8817e4Smiod   { bfd_mach_arm_4,  "sa1"      },
90*3d8817e4Smiod   { bfd_mach_arm_4,  "strongarm"},
91*3d8817e4Smiod   { bfd_mach_arm_4,  "strongarm110" },
92*3d8817e4Smiod   { bfd_mach_arm_4,  "strongarm1100" },
93*3d8817e4Smiod   { bfd_mach_arm_XScale, "xscale" },
94*3d8817e4Smiod   { bfd_mach_arm_ep9312, "ep9312" },
95*3d8817e4Smiod   { bfd_mach_arm_iWMMXt, "iwmmxt" }
96*3d8817e4Smiod };
97*3d8817e4Smiod 
98*3d8817e4Smiod static bfd_boolean
scan(const struct bfd_arch_info * info,const char * string)99*3d8817e4Smiod scan (const struct bfd_arch_info *info, const char *string)
100*3d8817e4Smiod {
101*3d8817e4Smiod   int  i;
102*3d8817e4Smiod 
103*3d8817e4Smiod   /* First test for an exact match.  */
104*3d8817e4Smiod   if (strcasecmp (string, info->printable_name) == 0)
105*3d8817e4Smiod     return TRUE;
106*3d8817e4Smiod 
107*3d8817e4Smiod   /* Next check for a processor name instead of an Architecture name.  */
108*3d8817e4Smiod   for (i = sizeof (processors) / sizeof (processors[0]); i--;)
109*3d8817e4Smiod     {
110*3d8817e4Smiod       if (strcasecmp (string, processors [i].name) == 0)
111*3d8817e4Smiod 	break;
112*3d8817e4Smiod     }
113*3d8817e4Smiod 
114*3d8817e4Smiod   if (i != -1 && info->mach == processors [i].mach)
115*3d8817e4Smiod     return TRUE;
116*3d8817e4Smiod 
117*3d8817e4Smiod   /* Finally check for the default architecture.  */
118*3d8817e4Smiod   if (strcasecmp (string, "arm") == 0)
119*3d8817e4Smiod     return info->the_default;
120*3d8817e4Smiod 
121*3d8817e4Smiod   return FALSE;
122*3d8817e4Smiod }
123*3d8817e4Smiod 
124*3d8817e4Smiod #define N(number, print, default, next)  \
125*3d8817e4Smiod {  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }
126*3d8817e4Smiod 
127*3d8817e4Smiod static const bfd_arch_info_type arch_info_struct[] =
128*3d8817e4Smiod {
129*3d8817e4Smiod   N (bfd_mach_arm_2,      "armv2",   FALSE, & arch_info_struct[1]),
130*3d8817e4Smiod   N (bfd_mach_arm_2a,     "armv2a",  FALSE, & arch_info_struct[2]),
131*3d8817e4Smiod   N (bfd_mach_arm_3,      "armv3",   FALSE, & arch_info_struct[3]),
132*3d8817e4Smiod   N (bfd_mach_arm_3M,     "armv3m",  FALSE, & arch_info_struct[4]),
133*3d8817e4Smiod   N (bfd_mach_arm_4,      "armv4",   FALSE, & arch_info_struct[5]),
134*3d8817e4Smiod   N (bfd_mach_arm_4T,     "armv4t",  FALSE, & arch_info_struct[6]),
135*3d8817e4Smiod   N (bfd_mach_arm_5,      "armv5",   FALSE, & arch_info_struct[7]),
136*3d8817e4Smiod   N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
137*3d8817e4Smiod   N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
138*3d8817e4Smiod   N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
139*3d8817e4Smiod   N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
140*3d8817e4Smiod   N (bfd_mach_arm_iWMMXt,"iwmmxt",  FALSE, NULL)
141*3d8817e4Smiod };
142*3d8817e4Smiod 
143*3d8817e4Smiod const bfd_arch_info_type bfd_arm_arch =
144*3d8817e4Smiod   N (0, "arm", TRUE, & arch_info_struct[0]);
145*3d8817e4Smiod 
146*3d8817e4Smiod /* Support functions used by both the COFF and ELF versions of the ARM port.  */
147*3d8817e4Smiod 
148*3d8817e4Smiod /* Handle the merging of the 'machine' settings of input file IBFD
149*3d8817e4Smiod    and an output file OBFD.  These values actually represent the
150*3d8817e4Smiod    different possible ARM architecture variants.
151*3d8817e4Smiod    Returns TRUE if they were merged successfully or FALSE otherwise.  */
152*3d8817e4Smiod 
153*3d8817e4Smiod bfd_boolean
bfd_arm_merge_machines(bfd * ibfd,bfd * obfd)154*3d8817e4Smiod bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
155*3d8817e4Smiod {
156*3d8817e4Smiod   unsigned int in  = bfd_get_mach (ibfd);
157*3d8817e4Smiod   unsigned int out = bfd_get_mach (obfd);
158*3d8817e4Smiod 
159*3d8817e4Smiod   /* If the output architecture is unknown, we now have a value to set.  */
160*3d8817e4Smiod   if (out == bfd_mach_arm_unknown)
161*3d8817e4Smiod     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
162*3d8817e4Smiod 
163*3d8817e4Smiod   /* If the input architecture is unknown,
164*3d8817e4Smiod      then so must be the output architecture.  */
165*3d8817e4Smiod   else if (in == bfd_mach_arm_unknown)
166*3d8817e4Smiod     /* FIXME: We ought to have some way to
167*3d8817e4Smiod        override this on the command line.  */
168*3d8817e4Smiod     bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
169*3d8817e4Smiod 
170*3d8817e4Smiod   /* If they are the same then nothing needs to be done.  */
171*3d8817e4Smiod   else if (out == in)
172*3d8817e4Smiod     ;
173*3d8817e4Smiod 
174*3d8817e4Smiod   /* Otherwise the general principle that a earlier architecture can be
175*3d8817e4Smiod      linked with a later architecture to produce a binary that will execute
176*3d8817e4Smiod      on the later architecture.
177*3d8817e4Smiod 
178*3d8817e4Smiod      We fail however if we attempt to link a Cirrus EP9312 binary with an
179*3d8817e4Smiod      Intel XScale binary, since these architecture have co-processors which
180*3d8817e4Smiod      will not both be present on the same physical hardware.  */
181*3d8817e4Smiod   else if (in == bfd_mach_arm_ep9312
182*3d8817e4Smiod 	   && (out == bfd_mach_arm_XScale || out == bfd_mach_arm_iWMMXt))
183*3d8817e4Smiod     {
184*3d8817e4Smiod       _bfd_error_handler (_("\
185*3d8817e4Smiod ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
186*3d8817e4Smiod 			  ibfd, obfd);
187*3d8817e4Smiod       bfd_set_error (bfd_error_wrong_format);
188*3d8817e4Smiod       return FALSE;
189*3d8817e4Smiod     }
190*3d8817e4Smiod   else if (out == bfd_mach_arm_ep9312
191*3d8817e4Smiod 	   && (in == bfd_mach_arm_XScale || in == bfd_mach_arm_iWMMXt))
192*3d8817e4Smiod     {
193*3d8817e4Smiod       _bfd_error_handler (_("\
194*3d8817e4Smiod ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
195*3d8817e4Smiod 			  obfd, ibfd);
196*3d8817e4Smiod       bfd_set_error (bfd_error_wrong_format);
197*3d8817e4Smiod       return FALSE;
198*3d8817e4Smiod     }
199*3d8817e4Smiod   else if (in > out)
200*3d8817e4Smiod     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
201*3d8817e4Smiod   /* else
202*3d8817e4Smiod      Nothing to do.  */
203*3d8817e4Smiod 
204*3d8817e4Smiod   return TRUE;
205*3d8817e4Smiod }
206*3d8817e4Smiod 
207*3d8817e4Smiod typedef struct
208*3d8817e4Smiod {
209*3d8817e4Smiod   unsigned char	namesz[4];	/* Size of entry's owner string.  */
210*3d8817e4Smiod   unsigned char	descsz[4];	/* Size of the note descriptor.  */
211*3d8817e4Smiod   unsigned char	type[4];	/* Interpretation of the descriptor.  */
212*3d8817e4Smiod   char		name[1];	/* Start of the name+desc data.  */
213*3d8817e4Smiod } arm_Note;
214*3d8817e4Smiod 
215*3d8817e4Smiod static bfd_boolean
arm_check_note(bfd * abfd,bfd_byte * buffer,bfd_size_type buffer_size,const char * expected_name,char ** description_return)216*3d8817e4Smiod arm_check_note (bfd *abfd,
217*3d8817e4Smiod 		bfd_byte *buffer,
218*3d8817e4Smiod 		bfd_size_type buffer_size,
219*3d8817e4Smiod 		const char *expected_name,
220*3d8817e4Smiod 		char **description_return)
221*3d8817e4Smiod {
222*3d8817e4Smiod   unsigned long namesz;
223*3d8817e4Smiod   unsigned long descsz;
224*3d8817e4Smiod   unsigned long type;
225*3d8817e4Smiod   char *        descr;
226*3d8817e4Smiod 
227*3d8817e4Smiod   if (buffer_size < offsetof (arm_Note, name))
228*3d8817e4Smiod     return FALSE;
229*3d8817e4Smiod 
230*3d8817e4Smiod   /* We have to extract the values this way to allow for a
231*3d8817e4Smiod      host whose endian-ness is different from the target.  */
232*3d8817e4Smiod   namesz = bfd_get_32 (abfd, buffer);
233*3d8817e4Smiod   descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
234*3d8817e4Smiod   type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
235*3d8817e4Smiod   descr  = (char *) buffer + offsetof (arm_Note, name);
236*3d8817e4Smiod 
237*3d8817e4Smiod   /* Check for buffer overflow.  */
238*3d8817e4Smiod   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
239*3d8817e4Smiod     return FALSE;
240*3d8817e4Smiod 
241*3d8817e4Smiod   if (expected_name == NULL)
242*3d8817e4Smiod     {
243*3d8817e4Smiod       if (namesz != 0)
244*3d8817e4Smiod 	return FALSE;
245*3d8817e4Smiod     }
246*3d8817e4Smiod   else
247*3d8817e4Smiod     {
248*3d8817e4Smiod       if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
249*3d8817e4Smiod 	return FALSE;
250*3d8817e4Smiod 
251*3d8817e4Smiod       if (strcmp (descr, expected_name) != 0)
252*3d8817e4Smiod 	return FALSE;
253*3d8817e4Smiod 
254*3d8817e4Smiod       descr += (namesz + 3) & ~3;
255*3d8817e4Smiod     }
256*3d8817e4Smiod 
257*3d8817e4Smiod   /* FIXME: We should probably check the type as well.  */
258*3d8817e4Smiod 
259*3d8817e4Smiod   if (description_return != NULL)
260*3d8817e4Smiod     * description_return = descr;
261*3d8817e4Smiod 
262*3d8817e4Smiod   return TRUE;
263*3d8817e4Smiod }
264*3d8817e4Smiod 
265*3d8817e4Smiod #define NOTE_ARCH_STRING 	"arch: "
266*3d8817e4Smiod 
267*3d8817e4Smiod bfd_boolean
bfd_arm_update_notes(bfd * abfd,const char * note_section)268*3d8817e4Smiod bfd_arm_update_notes (bfd *abfd, const char *note_section)
269*3d8817e4Smiod {
270*3d8817e4Smiod   asection *     arm_arch_section;
271*3d8817e4Smiod   bfd_size_type  buffer_size;
272*3d8817e4Smiod   bfd_byte *     buffer;
273*3d8817e4Smiod   char *         arch_string;
274*3d8817e4Smiod   char *         expected;
275*3d8817e4Smiod 
276*3d8817e4Smiod   /* Look for a note section.  If one is present check the architecture
277*3d8817e4Smiod      string encoded in it, and set it to the current architecture if it is
278*3d8817e4Smiod      different.  */
279*3d8817e4Smiod   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
280*3d8817e4Smiod 
281*3d8817e4Smiod   if (arm_arch_section == NULL)
282*3d8817e4Smiod     return TRUE;
283*3d8817e4Smiod 
284*3d8817e4Smiod   buffer_size = arm_arch_section->size;
285*3d8817e4Smiod   if (buffer_size == 0)
286*3d8817e4Smiod     return FALSE;
287*3d8817e4Smiod 
288*3d8817e4Smiod   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
289*3d8817e4Smiod     goto FAIL;
290*3d8817e4Smiod 
291*3d8817e4Smiod   /* Parse the note.  */
292*3d8817e4Smiod   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
293*3d8817e4Smiod     goto FAIL;
294*3d8817e4Smiod 
295*3d8817e4Smiod   /* Check the architecture in the note against the architecture of the bfd.  */
296*3d8817e4Smiod   switch (bfd_get_mach (abfd))
297*3d8817e4Smiod     {
298*3d8817e4Smiod     default:
299*3d8817e4Smiod     case bfd_mach_arm_unknown: expected = "unknown"; break;
300*3d8817e4Smiod     case bfd_mach_arm_2:       expected = "armv2"; break;
301*3d8817e4Smiod     case bfd_mach_arm_2a:      expected = "armv2a"; break;
302*3d8817e4Smiod     case bfd_mach_arm_3:       expected = "armv3"; break;
303*3d8817e4Smiod     case bfd_mach_arm_3M:      expected = "armv3M"; break;
304*3d8817e4Smiod     case bfd_mach_arm_4:       expected = "armv4"; break;
305*3d8817e4Smiod     case bfd_mach_arm_4T:      expected = "armv4t"; break;
306*3d8817e4Smiod     case bfd_mach_arm_5:       expected = "armv5"; break;
307*3d8817e4Smiod     case bfd_mach_arm_5T:      expected = "armv5t"; break;
308*3d8817e4Smiod     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
309*3d8817e4Smiod     case bfd_mach_arm_XScale:  expected = "XScale"; break;
310*3d8817e4Smiod     case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
311*3d8817e4Smiod     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
312*3d8817e4Smiod     }
313*3d8817e4Smiod 
314*3d8817e4Smiod   if (strcmp (arch_string, expected) != 0)
315*3d8817e4Smiod     {
316*3d8817e4Smiod       strcpy ((char *) buffer + (offsetof (arm_Note, name)
317*3d8817e4Smiod 				 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
318*3d8817e4Smiod 	      expected);
319*3d8817e4Smiod 
320*3d8817e4Smiod       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
321*3d8817e4Smiod 				      (file_ptr) 0, buffer_size))
322*3d8817e4Smiod 	{
323*3d8817e4Smiod 	  (*_bfd_error_handler)
324*3d8817e4Smiod 	    (_("warning: unable to update contents of %s section in %s"),
325*3d8817e4Smiod 	     note_section, bfd_get_filename (abfd));
326*3d8817e4Smiod 	  goto FAIL;
327*3d8817e4Smiod 	}
328*3d8817e4Smiod     }
329*3d8817e4Smiod 
330*3d8817e4Smiod   free (buffer);
331*3d8817e4Smiod   return TRUE;
332*3d8817e4Smiod 
333*3d8817e4Smiod  FAIL:
334*3d8817e4Smiod   if (buffer != NULL)
335*3d8817e4Smiod     free (buffer);
336*3d8817e4Smiod   return FALSE;
337*3d8817e4Smiod }
338*3d8817e4Smiod 
339*3d8817e4Smiod 
340*3d8817e4Smiod static struct
341*3d8817e4Smiod {
342*3d8817e4Smiod   const char * string;
343*3d8817e4Smiod   unsigned int mach;
344*3d8817e4Smiod }
345*3d8817e4Smiod architectures[] =
346*3d8817e4Smiod {
347*3d8817e4Smiod   { "armv2",   bfd_mach_arm_2 },
348*3d8817e4Smiod   { "armv2a",  bfd_mach_arm_2a },
349*3d8817e4Smiod   { "armv3",   bfd_mach_arm_3 },
350*3d8817e4Smiod   { "armv3M",  bfd_mach_arm_3M },
351*3d8817e4Smiod   { "armv4",   bfd_mach_arm_4 },
352*3d8817e4Smiod   { "armv4t",  bfd_mach_arm_4T },
353*3d8817e4Smiod   { "armv5",   bfd_mach_arm_5 },
354*3d8817e4Smiod   { "armv5t",  bfd_mach_arm_5T },
355*3d8817e4Smiod   { "armv5te", bfd_mach_arm_5TE },
356*3d8817e4Smiod   { "XScale",  bfd_mach_arm_XScale },
357*3d8817e4Smiod   { "ep9312",  bfd_mach_arm_ep9312 },
358*3d8817e4Smiod   { "iWMMXt",  bfd_mach_arm_iWMMXt }
359*3d8817e4Smiod };
360*3d8817e4Smiod 
361*3d8817e4Smiod /* Extract the machine number stored in a note section.  */
362*3d8817e4Smiod unsigned int
bfd_arm_get_mach_from_notes(bfd * abfd,const char * note_section)363*3d8817e4Smiod bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
364*3d8817e4Smiod {
365*3d8817e4Smiod   asection *     arm_arch_section;
366*3d8817e4Smiod   bfd_size_type  buffer_size;
367*3d8817e4Smiod   bfd_byte *     buffer;
368*3d8817e4Smiod   char *         arch_string;
369*3d8817e4Smiod   int            i;
370*3d8817e4Smiod 
371*3d8817e4Smiod   /* Look for a note section.  If one is present check the architecture
372*3d8817e4Smiod      string encoded in it, and set it to the current architecture if it is
373*3d8817e4Smiod      different.  */
374*3d8817e4Smiod   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
375*3d8817e4Smiod 
376*3d8817e4Smiod   if (arm_arch_section == NULL)
377*3d8817e4Smiod     return bfd_mach_arm_unknown;
378*3d8817e4Smiod 
379*3d8817e4Smiod   buffer_size = arm_arch_section->size;
380*3d8817e4Smiod   if (buffer_size == 0)
381*3d8817e4Smiod     return bfd_mach_arm_unknown;
382*3d8817e4Smiod 
383*3d8817e4Smiod   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
384*3d8817e4Smiod     goto FAIL;
385*3d8817e4Smiod 
386*3d8817e4Smiod   /* Parse the note.  */
387*3d8817e4Smiod   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
388*3d8817e4Smiod     goto FAIL;
389*3d8817e4Smiod 
390*3d8817e4Smiod   /* Interpret the architecture string.  */
391*3d8817e4Smiod   for (i = ARRAY_SIZE (architectures); i--;)
392*3d8817e4Smiod     if (strcmp (arch_string, architectures[i].string) == 0)
393*3d8817e4Smiod       {
394*3d8817e4Smiod 	free (buffer);
395*3d8817e4Smiod 	return architectures[i].mach;
396*3d8817e4Smiod       }
397*3d8817e4Smiod 
398*3d8817e4Smiod  FAIL:
399*3d8817e4Smiod   if (buffer != NULL)
400*3d8817e4Smiod     free (buffer);
401*3d8817e4Smiod   return bfd_mach_arm_unknown;
402*3d8817e4Smiod }
403*3d8817e4Smiod 
404*3d8817e4Smiod bfd_boolean
bfd_is_arm_mapping_symbol_name(const char * name)405*3d8817e4Smiod bfd_is_arm_mapping_symbol_name (const char * name)
406*3d8817e4Smiod {
407*3d8817e4Smiod   /* The ARM compiler outputs several obsolete forms.  Recognize them
408*3d8817e4Smiod      in addition to the standard $a, $t and $d.  */
409*3d8817e4Smiod   return (name != NULL)
410*3d8817e4Smiod     && (name[0] == '$')
411*3d8817e4Smiod     && ((name[1] == 'a') || (name[1] == 't') || (name[1] == 'd')
412*3d8817e4Smiod 	|| (name[1] == 'm') || (name[1] == 'f') || (name[1] == 'p'))
413*3d8817e4Smiod     && (name[2] == 0 || name[2] == '.');
414*3d8817e4Smiod }
415*3d8817e4Smiod 
416