xref: /netbsd/external/gpl3/gdb/dist/bfd/cpu-arm.c (revision 1424dfb3)
1377e23a2Schristos /* BFD support for the ARM processor
2*1424dfb3Schristos    Copyright (C) 1994-2020 Free Software Foundation, Inc.
3377e23a2Schristos    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4377e23a2Schristos 
5377e23a2Schristos    This file is part of BFD, the Binary File Descriptor library.
6377e23a2Schristos 
7377e23a2Schristos    This program is free software; you can redistribute it and/or modify
8377e23a2Schristos    it under the terms of the GNU General Public License as published by
9377e23a2Schristos    the Free Software Foundation; either version 3 of the License, or
10377e23a2Schristos    (at your option) any later version.
11377e23a2Schristos 
12377e23a2Schristos    This program is distributed in the hope that it will be useful,
13377e23a2Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14377e23a2Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15377e23a2Schristos    GNU General Public License for more details.
16377e23a2Schristos 
17377e23a2Schristos    You should have received a copy of the GNU General Public License
18377e23a2Schristos    along with this program; if not, write to the Free Software
19377e23a2Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20377e23a2Schristos    MA 02110-1301, USA.  */
21377e23a2Schristos 
22377e23a2Schristos #include "sysdep.h"
23377e23a2Schristos #include "bfd.h"
24377e23a2Schristos #include "libbfd.h"
25377e23a2Schristos #include "libiberty.h"
26*1424dfb3Schristos #include "cpu-arm.h"
27377e23a2Schristos 
28377e23a2Schristos /* This routine is provided two arch_infos and works out which ARM
29377e23a2Schristos    machine which would be compatible with both and returns a pointer
30377e23a2Schristos    to its info structure.  */
31377e23a2Schristos 
32377e23a2Schristos static const bfd_arch_info_type *
compatible(const bfd_arch_info_type * a,const bfd_arch_info_type * b)33377e23a2Schristos compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
34377e23a2Schristos {
35377e23a2Schristos   /* If a & b are for different architecture we can do nothing.  */
36377e23a2Schristos   if (a->arch != b->arch)
37377e23a2Schristos       return NULL;
38377e23a2Schristos 
39377e23a2Schristos   /* If a & b are for the same machine then all is well.  */
40377e23a2Schristos   if (a->mach == b->mach)
41377e23a2Schristos     return a;
42377e23a2Schristos 
43377e23a2Schristos   /* Otherwise if either a or b is the 'default' machine
44377e23a2Schristos      then it can be polymorphed into the other.  */
45377e23a2Schristos   if (a->the_default)
46377e23a2Schristos     return b;
47377e23a2Schristos 
48377e23a2Schristos   if (b->the_default)
49377e23a2Schristos     return a;
50377e23a2Schristos 
51377e23a2Schristos   /* So far all newer ARM architecture cores are
52377e23a2Schristos      supersets of previous cores.  */
53377e23a2Schristos   if (a->mach < b->mach)
54377e23a2Schristos     return b;
55377e23a2Schristos   else if (a->mach > b->mach)
56377e23a2Schristos     return a;
57377e23a2Schristos 
58377e23a2Schristos   /* Never reached!  */
59377e23a2Schristos   return NULL;
60377e23a2Schristos }
61377e23a2Schristos 
62377e23a2Schristos static struct
63377e23a2Schristos {
64377e23a2Schristos   unsigned int mach;
65377e23a2Schristos   char *       name;
66377e23a2Schristos }
67377e23a2Schristos processors[] =
68377e23a2Schristos {
69377e23a2Schristos   { bfd_mach_arm_2,	  "arm2"	    },
70377e23a2Schristos   { bfd_mach_arm_2a,	  "arm250"	    },
71377e23a2Schristos   { bfd_mach_arm_2a,	  "arm3"	    },
72377e23a2Schristos   { bfd_mach_arm_3,	  "arm6"	    },
73377e23a2Schristos   { bfd_mach_arm_3,	  "arm60"	    },
74377e23a2Schristos   { bfd_mach_arm_3,	  "arm600"	    },
75377e23a2Schristos   { bfd_mach_arm_3,	  "arm610"	    },
7607163879Schristos   { bfd_mach_arm_3,	  "arm620"	    },
77377e23a2Schristos   { bfd_mach_arm_3,	  "arm7"	    },
7807163879Schristos   { bfd_mach_arm_3,	  "arm70"	    },
7907163879Schristos   { bfd_mach_arm_3,	  "arm700"	    },
8007163879Schristos   { bfd_mach_arm_3,	  "arm700i"	    },
81377e23a2Schristos   { bfd_mach_arm_3,	  "arm710"	    },
8207163879Schristos   { bfd_mach_arm_3,	  "arm7100"	    },
8307163879Schristos   { bfd_mach_arm_3,	  "arm710c"	    },
8407163879Schristos   { bfd_mach_arm_4T,	  "arm710t"	    },
8507163879Schristos   { bfd_mach_arm_3,	  "arm720"	    },
8607163879Schristos   { bfd_mach_arm_4T,	  "arm720t"	    },
8707163879Schristos   { bfd_mach_arm_4T,	  "arm740t"	    },
88377e23a2Schristos   { bfd_mach_arm_3,	  "arm7500"	    },
8907163879Schristos   { bfd_mach_arm_3,	  "arm7500fe"	    },
90377e23a2Schristos   { bfd_mach_arm_3,	  "arm7d"	    },
91377e23a2Schristos   { bfd_mach_arm_3,	  "arm7di"	    },
92377e23a2Schristos   { bfd_mach_arm_3M,	  "arm7dm"	    },
93377e23a2Schristos   { bfd_mach_arm_3M,	  "arm7dmi"	    },
9407163879Schristos   { bfd_mach_arm_4T,	  "arm7t"	    },
95377e23a2Schristos   { bfd_mach_arm_4T,	  "arm7tdmi"	    },
9607163879Schristos   { bfd_mach_arm_4T,	  "arm7tdmi-s"	    },
9707163879Schristos   { bfd_mach_arm_3M,	  "arm7m"	    },
98377e23a2Schristos   { bfd_mach_arm_4,	  "arm8"	    },
99377e23a2Schristos   { bfd_mach_arm_4,	  "arm810"	    },
100377e23a2Schristos   { bfd_mach_arm_4,	  "arm9"	    },
10107163879Schristos   { bfd_mach_arm_4T,	  "arm920"	    },
102377e23a2Schristos   { bfd_mach_arm_4T,	  "arm920t"	    },
10307163879Schristos   { bfd_mach_arm_4T,	  "arm922t"	    },
10407163879Schristos   { bfd_mach_arm_5TEJ,	  "arm926ej"	    },
10507163879Schristos   { bfd_mach_arm_5TEJ,	  "arm926ejs"	    },
10607163879Schristos   { bfd_mach_arm_5TEJ,	  "arm926ej-s"	    },
10707163879Schristos   { bfd_mach_arm_4T,	  "arm940t"	    },
10807163879Schristos   { bfd_mach_arm_5TE,	  "arm946e"	    },
10907163879Schristos   { bfd_mach_arm_5TE,	  "arm946e-r0"	    },
11007163879Schristos   { bfd_mach_arm_5TE,	  "arm946e-s"	    },
11107163879Schristos   { bfd_mach_arm_5TE,	  "arm966e"	    },
11207163879Schristos   { bfd_mach_arm_5TE,	  "arm966e-r0"	    },
11307163879Schristos   { bfd_mach_arm_5TE,	  "arm966e-s"	    },
11407163879Schristos   { bfd_mach_arm_5TE,	  "arm968e-s"	    },
11507163879Schristos   { bfd_mach_arm_5TE,	  "arm9e"	    },
11607163879Schristos   { bfd_mach_arm_5TE,	  "arm9e-r0"	    },
117377e23a2Schristos   { bfd_mach_arm_4T,	  "arm9tdmi"	    },
11807163879Schristos   { bfd_mach_arm_5TE,	  "arm1020"	    },
11907163879Schristos   { bfd_mach_arm_5T,	  "arm1020t"	    },
12007163879Schristos   { bfd_mach_arm_5TE,	  "arm1020e"	    },
12107163879Schristos   { bfd_mach_arm_5TE,	  "arm1022e"	    },
12207163879Schristos   { bfd_mach_arm_5TEJ,	  "arm1026ejs"	    },
12307163879Schristos   { bfd_mach_arm_5TEJ,	  "arm1026ej-s"	    },
12407163879Schristos   { bfd_mach_arm_5TE,	  "arm10e"	    },
12507163879Schristos   { bfd_mach_arm_5T,	  "arm10t"	    },
12607163879Schristos   { bfd_mach_arm_5T,	  "arm10tdmi"	    },
12707163879Schristos   { bfd_mach_arm_6,	  "arm1136j-s"	    },
12807163879Schristos   { bfd_mach_arm_6,	  "arm1136js"	    },
12907163879Schristos   { bfd_mach_arm_6,	  "arm1136jf-s"	    },
13007163879Schristos   { bfd_mach_arm_6,	  "arm1136jfs"	    },
13107163879Schristos   { bfd_mach_arm_6KZ,	  "arm1176jz-s"	    },
13207163879Schristos   { bfd_mach_arm_6KZ,	  "arm1176jzf-s"    },
13307163879Schristos   { bfd_mach_arm_6T2,	  "arm1156t2-s"	    },
13407163879Schristos   { bfd_mach_arm_6T2,	  "arm1156t2f-s"    },
13507163879Schristos   { bfd_mach_arm_7,	  "cortex-a5"	    },
13607163879Schristos   { bfd_mach_arm_7,	  "cortex-a7"	    },
13707163879Schristos   { bfd_mach_arm_7,	  "cortex-a8"	    },
13807163879Schristos   { bfd_mach_arm_7,	  "cortex-a9"	    },
13907163879Schristos   { bfd_mach_arm_7,	  "cortex-a12"	    },
14007163879Schristos   { bfd_mach_arm_7,	  "cortex-a15"	    },
14107163879Schristos   { bfd_mach_arm_7,	  "cortex-a17"	    },
14207163879Schristos   { bfd_mach_arm_8,	  "cortex-a32"	    },
14307163879Schristos   { bfd_mach_arm_8,	  "cortex-a35"	    },
14407163879Schristos   { bfd_mach_arm_8,	  "cortex-a53"	    },
14507163879Schristos   { bfd_mach_arm_8,	  "cortex-a55"	    },
14607163879Schristos   { bfd_mach_arm_8,	  "cortex-a57"	    },
14707163879Schristos   { bfd_mach_arm_8,	  "cortex-a72"	    },
14807163879Schristos   { bfd_mach_arm_8,	  "cortex-a73"	    },
14907163879Schristos   { bfd_mach_arm_8,	  "cortex-a75"	    },
15007163879Schristos   { bfd_mach_arm_8,	  "cortex-a76"	    },
151*1424dfb3Schristos   { bfd_mach_arm_8,	  "cortex-a76ae"    },
152*1424dfb3Schristos   { bfd_mach_arm_8,	  "cortex-a77"	    },
15307163879Schristos   { bfd_mach_arm_6SM,	  "cortex-m0"	    },
15407163879Schristos   { bfd_mach_arm_6SM,	  "cortex-m0plus"   },
15507163879Schristos   { bfd_mach_arm_6SM,	  "cortex-m1"	    },
15607163879Schristos   { bfd_mach_arm_8M_BASE, "cortex-m23"	    },
15707163879Schristos   { bfd_mach_arm_7,	  "cortex-m3"	    },
15807163879Schristos   { bfd_mach_arm_8M_MAIN, "cortex-m33"	    },
159*1424dfb3Schristos   { bfd_mach_arm_8M_MAIN, "cortex-m35p"	    },
16007163879Schristos   { bfd_mach_arm_7EM,	  "cortex-m4"	    },
16107163879Schristos   { bfd_mach_arm_7EM,	  "cortex-m7"	    },
16207163879Schristos   { bfd_mach_arm_7,	  "cortex-r4"	    },
16307163879Schristos   { bfd_mach_arm_7,	  "cortex-r4f"	    },
16407163879Schristos   { bfd_mach_arm_7,	  "cortex-r5"	    },
16507163879Schristos   { bfd_mach_arm_8R,	  "cortex-r52"	    },
16607163879Schristos   { bfd_mach_arm_7,	  "cortex-r7"	    },
16707163879Schristos   { bfd_mach_arm_7,	  "cortex-r8"	    },
16807163879Schristos   { bfd_mach_arm_4T,	  "ep9312"	    },
16907163879Schristos   { bfd_mach_arm_8,	  "exynos-m1"	    },
17007163879Schristos   { bfd_mach_arm_4,	  "fa526"	    },
17107163879Schristos   { bfd_mach_arm_5TE,	  "fa606te"	    },
17207163879Schristos   { bfd_mach_arm_5TE,	  "fa616te"	    },
17307163879Schristos   { bfd_mach_arm_4,	  "fa626"	    },
17407163879Schristos   { bfd_mach_arm_5TE,	  "fa626te"	    },
17507163879Schristos   { bfd_mach_arm_5TE,	  "fa726te"	    },
17607163879Schristos   { bfd_mach_arm_5TE,	  "fmp626"	    },
17707163879Schristos   { bfd_mach_arm_XScale,  "i80200"	    },
17807163879Schristos   { bfd_mach_arm_7,	  "marvell-pj4"	    },
17907163879Schristos   { bfd_mach_arm_7,	  "marvell-whitney" },
18007163879Schristos   { bfd_mach_arm_6K,	  "mpcore"	    },
18107163879Schristos   { bfd_mach_arm_6K,	  "mpcorenovfp"	    },
182377e23a2Schristos   { bfd_mach_arm_4,	  "sa1"		    },
183377e23a2Schristos   { bfd_mach_arm_4,	  "strongarm"	    },
18407163879Schristos   { bfd_mach_arm_4,	  "strongarm1"	    },
185377e23a2Schristos   { bfd_mach_arm_4,	  "strongarm110"    },
186377e23a2Schristos   { bfd_mach_arm_4,	  "strongarm1100"   },
18707163879Schristos   { bfd_mach_arm_4,	  "strongarm1110"   },
188377e23a2Schristos   { bfd_mach_arm_XScale,  "xscale"	    },
18907163879Schristos   { bfd_mach_arm_8,	  "xgene1"	    },
19007163879Schristos   { bfd_mach_arm_8,	  "xgene2"	    },
191377e23a2Schristos   { bfd_mach_arm_ep9312,  "ep9312"	    },
192377e23a2Schristos   { bfd_mach_arm_iWMMXt,  "iwmmxt"	    },
193c03b94e9Schristos   { bfd_mach_arm_iWMMXt2, "iwmmxt2"	    },
194c03b94e9Schristos   { bfd_mach_arm_unknown, "arm_any"	    }
195377e23a2Schristos };
196377e23a2Schristos 
197377e23a2Schristos static bfd_boolean
scan(const struct bfd_arch_info * info,const char * string)198377e23a2Schristos scan (const struct bfd_arch_info *info, const char *string)
199377e23a2Schristos {
200377e23a2Schristos   int  i;
201377e23a2Schristos 
202377e23a2Schristos   /* First test for an exact match.  */
203377e23a2Schristos   if (strcasecmp (string, info->printable_name) == 0)
204377e23a2Schristos     return TRUE;
205377e23a2Schristos 
206377e23a2Schristos   /* Next check for a processor name instead of an Architecture name.  */
207377e23a2Schristos   for (i = sizeof (processors) / sizeof (processors[0]); i--;)
208377e23a2Schristos     {
209377e23a2Schristos       if (strcasecmp (string, processors [i].name) == 0)
210377e23a2Schristos 	break;
211377e23a2Schristos     }
212377e23a2Schristos 
213377e23a2Schristos   if (i != -1 && info->mach == processors [i].mach)
214377e23a2Schristos     return TRUE;
215377e23a2Schristos 
216377e23a2Schristos   /* Finally check for the default architecture.  */
217377e23a2Schristos   if (strcasecmp (string, "arm") == 0)
218377e23a2Schristos     return info->the_default;
219377e23a2Schristos 
220377e23a2Schristos   return FALSE;
221377e23a2Schristos }
222377e23a2Schristos 
223377e23a2Schristos #define N(number, print, default, next)  \
22448596154Schristos {  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
225*1424dfb3Schristos     scan, bfd_arch_default_fill, next, 0 }
226377e23a2Schristos 
227377e23a2Schristos static const bfd_arch_info_type arch_info_struct[] =
228377e23a2Schristos {
229377e23a2Schristos   N (bfd_mach_arm_2,         "armv2",          FALSE, & arch_info_struct[1]),
230377e23a2Schristos   N (bfd_mach_arm_2a,        "armv2a",         FALSE, & arch_info_struct[2]),
231377e23a2Schristos   N (bfd_mach_arm_3,         "armv3",          FALSE, & arch_info_struct[3]),
232377e23a2Schristos   N (bfd_mach_arm_3M,        "armv3m",         FALSE, & arch_info_struct[4]),
233377e23a2Schristos   N (bfd_mach_arm_4,         "armv4",          FALSE, & arch_info_struct[5]),
234377e23a2Schristos   N (bfd_mach_arm_4T,        "armv4t",         FALSE, & arch_info_struct[6]),
235377e23a2Schristos   N (bfd_mach_arm_5,         "armv5",          FALSE, & arch_info_struct[7]),
236377e23a2Schristos   N (bfd_mach_arm_5T,        "armv5t",         FALSE, & arch_info_struct[8]),
237377e23a2Schristos   N (bfd_mach_arm_5TE,       "armv5te",        FALSE, & arch_info_struct[9]),
238377e23a2Schristos   N (bfd_mach_arm_XScale,    "xscale",         FALSE, & arch_info_struct[10]),
239377e23a2Schristos   N (bfd_mach_arm_ep9312,    "ep9312",         FALSE, & arch_info_struct[11]),
240377e23a2Schristos   N (bfd_mach_arm_iWMMXt,    "iwmmxt",         FALSE, & arch_info_struct[12]),
241c03b94e9Schristos   N (bfd_mach_arm_iWMMXt2,   "iwmmxt2",        FALSE, & arch_info_struct[13]),
24207163879Schristos   N (bfd_mach_arm_5TEJ,      "armv5tej",       FALSE, & arch_info_struct[14]),
24307163879Schristos   N (bfd_mach_arm_6,         "armv6",          FALSE, & arch_info_struct[15]),
24407163879Schristos   N (bfd_mach_arm_6KZ,       "armv6kz",        FALSE, & arch_info_struct[16]),
24507163879Schristos   N (bfd_mach_arm_6T2,       "armv6t2",        FALSE, & arch_info_struct[17]),
24607163879Schristos   N (bfd_mach_arm_6K,        "armv6k",         FALSE, & arch_info_struct[18]),
24707163879Schristos   N (bfd_mach_arm_7,         "armv7",          FALSE, & arch_info_struct[19]),
24807163879Schristos   N (bfd_mach_arm_6M,        "armv6-m",        FALSE, & arch_info_struct[20]),
24907163879Schristos   N (bfd_mach_arm_6SM,       "armv6s-m",       FALSE, & arch_info_struct[21]),
25007163879Schristos   N (bfd_mach_arm_7EM,       "armv7e-m",       FALSE, & arch_info_struct[22]),
25107163879Schristos   N (bfd_mach_arm_8,         "armv8-a",        FALSE, & arch_info_struct[23]),
25207163879Schristos   N (bfd_mach_arm_8R,        "armv8-r",        FALSE, & arch_info_struct[24]),
25307163879Schristos   N (bfd_mach_arm_8M_BASE,   "armv8-m.base",   FALSE, & arch_info_struct[25]),
25407163879Schristos   N (bfd_mach_arm_8M_MAIN,   "armv8-m.main",   FALSE, & arch_info_struct[26]),
255*1424dfb3Schristos   N (bfd_mach_arm_8_1M_MAIN, "armv8.1-m.main", FALSE, & arch_info_struct[27]),
256c03b94e9Schristos   N (bfd_mach_arm_unknown,   "arm_any",        FALSE, NULL)
257377e23a2Schristos };
258377e23a2Schristos 
259377e23a2Schristos const bfd_arch_info_type bfd_arm_arch =
260377e23a2Schristos   N (0, "arm", TRUE, & arch_info_struct[0]);
261377e23a2Schristos 
262377e23a2Schristos /* Support functions used by both the COFF and ELF versions of the ARM port.  */
263377e23a2Schristos 
264377e23a2Schristos /* Handle the merging of the 'machine' settings of input file IBFD
265377e23a2Schristos    and an output file OBFD.  These values actually represent the
266377e23a2Schristos    different possible ARM architecture variants.
267377e23a2Schristos    Returns TRUE if they were merged successfully or FALSE otherwise.  */
268377e23a2Schristos 
269377e23a2Schristos bfd_boolean
bfd_arm_merge_machines(bfd * ibfd,bfd * obfd)270377e23a2Schristos bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
271377e23a2Schristos {
272377e23a2Schristos   unsigned int in  = bfd_get_mach (ibfd);
273377e23a2Schristos   unsigned int out = bfd_get_mach (obfd);
274377e23a2Schristos 
275377e23a2Schristos   /* If the output architecture is unknown, we now have a value to set.  */
276377e23a2Schristos   if (out == bfd_mach_arm_unknown)
277377e23a2Schristos     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
278377e23a2Schristos 
279377e23a2Schristos   /* If the input architecture is unknown,
280377e23a2Schristos      then so must be the output architecture.  */
281377e23a2Schristos   else if (in == bfd_mach_arm_unknown)
282377e23a2Schristos     /* FIXME: We ought to have some way to
283377e23a2Schristos        override this on the command line.  */
284377e23a2Schristos     bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
285377e23a2Schristos 
286377e23a2Schristos   /* If they are the same then nothing needs to be done.  */
287377e23a2Schristos   else if (out == in)
288377e23a2Schristos     ;
289377e23a2Schristos 
290377e23a2Schristos   /* Otherwise the general principle that a earlier architecture can be
291377e23a2Schristos      linked with a later architecture to produce a binary that will execute
292377e23a2Schristos      on the later architecture.
293377e23a2Schristos 
294377e23a2Schristos      We fail however if we attempt to link a Cirrus EP9312 binary with an
295377e23a2Schristos      Intel XScale binary, since these architecture have co-processors which
296377e23a2Schristos      will not both be present on the same physical hardware.  */
297377e23a2Schristos   else if (in == bfd_mach_arm_ep9312
298377e23a2Schristos 	   && (out == bfd_mach_arm_XScale
299377e23a2Schristos 	       || out == bfd_mach_arm_iWMMXt
300377e23a2Schristos 	       || out == bfd_mach_arm_iWMMXt2))
301377e23a2Schristos     {
3021c468f90Schristos       /* xgettext: c-format */
303*1424dfb3Schristos       _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
304*1424dfb3Schristos 			    "whereas %pB is compiled for XScale"),
305377e23a2Schristos 			  ibfd, obfd);
306377e23a2Schristos       bfd_set_error (bfd_error_wrong_format);
307377e23a2Schristos       return FALSE;
308377e23a2Schristos     }
309377e23a2Schristos   else if (out == bfd_mach_arm_ep9312
310377e23a2Schristos 	   && (in == bfd_mach_arm_XScale
311377e23a2Schristos 	       || in == bfd_mach_arm_iWMMXt
312377e23a2Schristos 	       || in == bfd_mach_arm_iWMMXt2))
313377e23a2Schristos     {
3141c468f90Schristos       /* xgettext: c-format */
315*1424dfb3Schristos       _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
316*1424dfb3Schristos 			    "whereas %pB is compiled for XScale"),
317377e23a2Schristos 			  obfd, ibfd);
318377e23a2Schristos       bfd_set_error (bfd_error_wrong_format);
319377e23a2Schristos       return FALSE;
320377e23a2Schristos     }
321377e23a2Schristos   else if (in > out)
322377e23a2Schristos     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
323377e23a2Schristos   /* else
324377e23a2Schristos      Nothing to do.  */
325377e23a2Schristos 
326377e23a2Schristos   return TRUE;
327377e23a2Schristos }
328377e23a2Schristos 
329377e23a2Schristos typedef struct
330377e23a2Schristos {
331377e23a2Schristos   unsigned char	namesz[4];	/* Size of entry's owner string.  */
332377e23a2Schristos   unsigned char	descsz[4];	/* Size of the note descriptor.  */
333377e23a2Schristos   unsigned char	type[4];	/* Interpretation of the descriptor.  */
334377e23a2Schristos   char		name[1];	/* Start of the name+desc data.  */
335377e23a2Schristos } arm_Note;
336377e23a2Schristos 
337377e23a2Schristos static bfd_boolean
arm_check_note(bfd * abfd,bfd_byte * buffer,bfd_size_type buffer_size,const char * expected_name,char ** description_return)338377e23a2Schristos arm_check_note (bfd *abfd,
339377e23a2Schristos 		bfd_byte *buffer,
340377e23a2Schristos 		bfd_size_type buffer_size,
341377e23a2Schristos 		const char *expected_name,
342377e23a2Schristos 		char **description_return)
343377e23a2Schristos {
344377e23a2Schristos   unsigned long namesz;
345377e23a2Schristos   unsigned long descsz;
346377e23a2Schristos   unsigned long type;
347377e23a2Schristos   char *	descr;
348377e23a2Schristos 
349377e23a2Schristos   if (buffer_size < offsetof (arm_Note, name))
350377e23a2Schristos     return FALSE;
351377e23a2Schristos 
352377e23a2Schristos   /* We have to extract the values this way to allow for a
353377e23a2Schristos      host whose endian-ness is different from the target.  */
354377e23a2Schristos   namesz = bfd_get_32 (abfd, buffer);
355377e23a2Schristos   descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
356377e23a2Schristos   type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
357377e23a2Schristos   descr  = (char *) buffer + offsetof (arm_Note, name);
358377e23a2Schristos 
359377e23a2Schristos   /* Check for buffer overflow.  */
360377e23a2Schristos   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
361377e23a2Schristos     return FALSE;
362377e23a2Schristos 
363377e23a2Schristos   if (expected_name == NULL)
364377e23a2Schristos     {
365377e23a2Schristos       if (namesz != 0)
366377e23a2Schristos 	return FALSE;
367377e23a2Schristos     }
368377e23a2Schristos   else
369377e23a2Schristos     {
370377e23a2Schristos       if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
371377e23a2Schristos 	return FALSE;
372377e23a2Schristos 
373377e23a2Schristos       if (strcmp (descr, expected_name) != 0)
374377e23a2Schristos 	return FALSE;
375377e23a2Schristos 
376377e23a2Schristos       descr += (namesz + 3) & ~3;
377377e23a2Schristos     }
378377e23a2Schristos 
379377e23a2Schristos   /* FIXME: We should probably check the type as well.  */
380377e23a2Schristos   (void) type;
381377e23a2Schristos 
382377e23a2Schristos   if (description_return != NULL)
383377e23a2Schristos     * description_return = descr;
384377e23a2Schristos 
385377e23a2Schristos   return TRUE;
386377e23a2Schristos }
387377e23a2Schristos 
388377e23a2Schristos #define NOTE_ARCH_STRING	"arch: "
389377e23a2Schristos 
390377e23a2Schristos bfd_boolean
bfd_arm_update_notes(bfd * abfd,const char * note_section)391377e23a2Schristos bfd_arm_update_notes (bfd *abfd, const char *note_section)
392377e23a2Schristos {
393377e23a2Schristos   asection *	 arm_arch_section;
394377e23a2Schristos   bfd_size_type	 buffer_size;
395377e23a2Schristos   bfd_byte *	 buffer;
396377e23a2Schristos   char *	 arch_string;
397377e23a2Schristos   char *	 expected;
398377e23a2Schristos 
399377e23a2Schristos   /* Look for a note section.  If one is present check the architecture
400377e23a2Schristos      string encoded in it, and set it to the current architecture if it is
401377e23a2Schristos      different.  */
402377e23a2Schristos   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
403377e23a2Schristos 
404377e23a2Schristos   if (arm_arch_section == NULL)
405377e23a2Schristos     return TRUE;
406377e23a2Schristos 
407377e23a2Schristos   buffer_size = arm_arch_section->size;
408377e23a2Schristos   if (buffer_size == 0)
409377e23a2Schristos     return FALSE;
410377e23a2Schristos 
411377e23a2Schristos   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
412377e23a2Schristos     goto FAIL;
413377e23a2Schristos 
414377e23a2Schristos   /* Parse the note.  */
415377e23a2Schristos   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
416377e23a2Schristos     goto FAIL;
417377e23a2Schristos 
41807163879Schristos   /* Check the architecture in the note against the architecture of the bfd.
41907163879Schristos      Newer architectures versions should not be added here as build attribute
42007163879Schristos      are a better mechanism to convey ISA used.  */
421377e23a2Schristos   switch (bfd_get_mach (abfd))
422377e23a2Schristos     {
423377e23a2Schristos     default:
424377e23a2Schristos     case bfd_mach_arm_unknown: expected = "unknown"; break;
425377e23a2Schristos     case bfd_mach_arm_2:       expected = "armv2"; break;
426377e23a2Schristos     case bfd_mach_arm_2a:      expected = "armv2a"; break;
427377e23a2Schristos     case bfd_mach_arm_3:       expected = "armv3"; break;
428377e23a2Schristos     case bfd_mach_arm_3M:      expected = "armv3M"; break;
429377e23a2Schristos     case bfd_mach_arm_4:       expected = "armv4"; break;
430377e23a2Schristos     case bfd_mach_arm_4T:      expected = "armv4t"; break;
431377e23a2Schristos     case bfd_mach_arm_5:       expected = "armv5"; break;
432377e23a2Schristos     case bfd_mach_arm_5T:      expected = "armv5t"; break;
433377e23a2Schristos     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
434377e23a2Schristos     case bfd_mach_arm_XScale:  expected = "XScale"; break;
435377e23a2Schristos     case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
436377e23a2Schristos     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
437377e23a2Schristos     case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
438377e23a2Schristos     }
439377e23a2Schristos 
440377e23a2Schristos   if (strcmp (arch_string, expected) != 0)
441377e23a2Schristos     {
442377e23a2Schristos       strcpy ((char *) buffer + (offsetof (arm_Note, name)
443377e23a2Schristos 				 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
444377e23a2Schristos 	      expected);
445377e23a2Schristos 
446377e23a2Schristos       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
447377e23a2Schristos 				      (file_ptr) 0, buffer_size))
448377e23a2Schristos 	{
4491c468f90Schristos 	  _bfd_error_handler
4501c468f90Schristos 	    /* xgettext: c-format */
45107163879Schristos 	    (_("warning: unable to update contents of %s section in %pB"),
4521c468f90Schristos 	     note_section, abfd);
453377e23a2Schristos 	  goto FAIL;
454377e23a2Schristos 	}
455377e23a2Schristos     }
456377e23a2Schristos 
457377e23a2Schristos   free (buffer);
458377e23a2Schristos   return TRUE;
459377e23a2Schristos 
460377e23a2Schristos  FAIL:
461377e23a2Schristos   free (buffer);
462377e23a2Schristos   return FALSE;
463377e23a2Schristos }
464377e23a2Schristos 
465377e23a2Schristos 
466377e23a2Schristos static struct
467377e23a2Schristos {
468377e23a2Schristos   const char * string;
469377e23a2Schristos   unsigned int mach;
470377e23a2Schristos }
47107163879Schristos 
47207163879Schristos /* Newer architectures versions should not be added here as build attribute are
47307163879Schristos    a better mechanism to convey ISA used.  */
474377e23a2Schristos architectures[] =
475377e23a2Schristos {
476377e23a2Schristos   { "armv2",   bfd_mach_arm_2 },
477377e23a2Schristos   { "armv2a",  bfd_mach_arm_2a },
478377e23a2Schristos   { "armv3",   bfd_mach_arm_3 },
479377e23a2Schristos   { "armv3M",  bfd_mach_arm_3M },
480377e23a2Schristos   { "armv4",   bfd_mach_arm_4 },
481377e23a2Schristos   { "armv4t",  bfd_mach_arm_4T },
482377e23a2Schristos   { "armv5",   bfd_mach_arm_5 },
483377e23a2Schristos   { "armv5t",  bfd_mach_arm_5T },
484377e23a2Schristos   { "armv5te", bfd_mach_arm_5TE },
485377e23a2Schristos   { "XScale",  bfd_mach_arm_XScale },
486377e23a2Schristos   { "ep9312",  bfd_mach_arm_ep9312 },
487377e23a2Schristos   { "iWMMXt",  bfd_mach_arm_iWMMXt },
488c03b94e9Schristos   { "iWMMXt2", bfd_mach_arm_iWMMXt2 },
489c03b94e9Schristos   { "arm_any", bfd_mach_arm_unknown }
490377e23a2Schristos };
491377e23a2Schristos 
492377e23a2Schristos /* Extract the machine number stored in a note section.  */
493377e23a2Schristos unsigned int
bfd_arm_get_mach_from_notes(bfd * abfd,const char * note_section)494377e23a2Schristos bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
495377e23a2Schristos {
496377e23a2Schristos   asection *	 arm_arch_section;
497377e23a2Schristos   bfd_size_type	 buffer_size;
498377e23a2Schristos   bfd_byte *	 buffer;
499377e23a2Schristos   char *	 arch_string;
500377e23a2Schristos   int		 i;
501377e23a2Schristos 
502377e23a2Schristos   /* Look for a note section.  If one is present check the architecture
503377e23a2Schristos      string encoded in it, and set it to the current architecture if it is
504377e23a2Schristos      different.  */
505377e23a2Schristos   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
506377e23a2Schristos 
507377e23a2Schristos   if (arm_arch_section == NULL)
508377e23a2Schristos     return bfd_mach_arm_unknown;
509377e23a2Schristos 
510377e23a2Schristos   buffer_size = arm_arch_section->size;
511377e23a2Schristos   if (buffer_size == 0)
512377e23a2Schristos     return bfd_mach_arm_unknown;
513377e23a2Schristos 
514377e23a2Schristos   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
515377e23a2Schristos     goto FAIL;
516377e23a2Schristos 
517377e23a2Schristos   /* Parse the note.  */
518377e23a2Schristos   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
519377e23a2Schristos     goto FAIL;
520377e23a2Schristos 
521377e23a2Schristos   /* Interpret the architecture string.  */
522377e23a2Schristos   for (i = ARRAY_SIZE (architectures); i--;)
523377e23a2Schristos     if (strcmp (arch_string, architectures[i].string) == 0)
524377e23a2Schristos       {
525377e23a2Schristos 	free (buffer);
526377e23a2Schristos 	return architectures[i].mach;
527377e23a2Schristos       }
528377e23a2Schristos 
529377e23a2Schristos  FAIL:
530377e23a2Schristos   free (buffer);
531377e23a2Schristos   return bfd_mach_arm_unknown;
532377e23a2Schristos }
533377e23a2Schristos 
534377e23a2Schristos bfd_boolean
bfd_is_arm_special_symbol_name(const char * name,int type)535377e23a2Schristos bfd_is_arm_special_symbol_name (const char * name, int type)
536377e23a2Schristos {
537377e23a2Schristos   /* The ARM compiler outputs several obsolete forms.  Recognize them
538377e23a2Schristos      in addition to the standard $a, $t and $d.  We are somewhat loose
539377e23a2Schristos      in what we accept here, since the full set is not documented.  */
540377e23a2Schristos   if (!name || name[0] != '$')
541377e23a2Schristos     return FALSE;
542377e23a2Schristos   if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
543377e23a2Schristos     type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
544377e23a2Schristos   else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
545377e23a2Schristos     type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
546377e23a2Schristos   else if (name[1] >= 'a' && name[1] <= 'z')
547377e23a2Schristos     type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
548377e23a2Schristos   else
549377e23a2Schristos     return FALSE;
550377e23a2Schristos 
551377e23a2Schristos   return (type != 0 && (name[2] == 0 || name[2] == '.'));
552377e23a2Schristos }
553377e23a2Schristos 
554