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