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