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