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