Home | History | Annotate | Line # | Download | only in bfd
      1 /* BFD support for the ARM processor
      2    Copyright (C) 1994-2026 Free Software Foundation, Inc.
      3    Contributed by Richard Earnshaw (rwe (at) 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 {
     35   /* If a & b are for different architecture we can do nothing.  */
     36   if (a->arch != b->arch)
     37       return NULL;
     38 
     39   /* If a & b are for the same machine then all is well.  */
     40   if (a->mach == b->mach)
     41     return a;
     42 
     43   /* Otherwise if either a or b is the 'default' machine
     44      then it can be polymorphed into the other.  */
     45   if (a->the_default)
     46     return b;
     47 
     48   if (b->the_default)
     49     return a;
     50 
     51   /* So far all newer ARM architecture cores are
     52      supersets of previous cores.  */
     53   if (a->mach < b->mach)
     54     return b;
     55   else if (a->mach > b->mach)
     56     return a;
     57 
     58   /* Never reached!  */
     59   return NULL;
     60 }
     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 {
    206   int  i;
    207 
    208   /* First test for an exact match.  */
    209   if (strcasecmp (string, info->printable_name) == 0)
    210     return true;
    211 
    212   /* If there is a prefix of "arm:" then skip it.  */
    213   const char * colon;
    214   if ((colon = strchr (string, ':')) != NULL)
    215     {
    216       if (strncasecmp (string, "arm", colon - string) != 0)
    217 	return false;
    218       string = colon + 1;
    219     }
    220 
    221   /* Next check for a processor name instead of an Architecture name.  */
    222   for (i = sizeof (processors) / sizeof (processors[0]); i--;)
    223     {
    224       if (strcasecmp (string, processors [i].name) == 0)
    225 	break;
    226     }
    227 
    228   if (i != -1 && info->mach == processors [i].mach)
    229     return true;
    230 
    231   /* Finally check for the default architecture.  */
    232   if (strcasecmp (string, "arm") == 0)
    233     return info->the_default;
    234 
    235   return false;
    236 }
    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 {
    287   unsigned int in  = bfd_get_mach (ibfd);
    288   unsigned int out = bfd_get_mach (obfd);
    289 
    290   /* If the output architecture is unknown, we now have a value to set.  */
    291   if (out == bfd_mach_arm_unknown)
    292     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   else if (in == bfd_mach_arm_unknown)
    297     /* FIXME: We ought to have some way to
    298        override this on the command line.  */
    299     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   else if (out == in)
    303     ;
    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   else if (in > out)
    309     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
    310   /* else
    311      Nothing to do.  */
    312 
    313   return true;
    314 }
    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 {
    331   unsigned long namesz;
    332   unsigned long descsz;
    333   unsigned long type;
    334   char *	descr;
    335 
    336   if (buffer_size < offsetof (arm_Note, name))
    337     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   namesz = bfd_get_32 (abfd, buffer);
    342   descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
    343   type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
    344   descr  = (char *) buffer + offsetof (arm_Note, name);
    345 
    346   /* Check for buffer overflow.  */
    347   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
    348     return false;
    349 
    350   if (expected_name == NULL)
    351     {
    352       if (namesz != 0)
    353 	return false;
    354     }
    355   else
    356     {
    357       if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
    358 	return false;
    359 
    360       if (strcmp (descr, expected_name) != 0)
    361 	return false;
    362 
    363       descr += (namesz + 3) & ~3;
    364     }
    365 
    366   /* FIXME: We should probably check the type as well.  */
    367   (void) type;
    368 
    369   if (description_return != NULL)
    370     * description_return = descr;
    371 
    372   return true;
    373 }
    374 
    375 #define NOTE_ARCH_STRING	"arch: "
    376 
    377 bool
    378 bfd_arm_update_notes (bfd *abfd, const char *note_section)
    379 {
    380   asection *	 arm_arch_section;
    381   bfd_size_type	 buffer_size;
    382   bfd_byte *	 buffer;
    383   char *	 arch_string;
    384   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   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
    390 
    391   if (arm_arch_section == NULL
    392       || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0)
    393     return true;
    394 
    395   buffer_size = arm_arch_section->size;
    396   if (buffer_size == 0)
    397     return false;
    398 
    399   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
    400     goto FAIL;
    401 
    402   /* Parse the note.  */
    403   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
    404     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   switch (bfd_get_mach (abfd))
    410     {
    411     default:
    412     case bfd_mach_arm_unknown: expected = "unknown"; break;
    413     case bfd_mach_arm_2:       expected = "armv2"; break;
    414     case bfd_mach_arm_2a:      expected = "armv2a"; break;
    415     case bfd_mach_arm_3:       expected = "armv3"; break;
    416     case bfd_mach_arm_3M:      expected = "armv3M"; break;
    417     case bfd_mach_arm_4:       expected = "armv4"; break;
    418     case bfd_mach_arm_4T:      expected = "armv4t"; break;
    419     case bfd_mach_arm_5:       expected = "armv5"; break;
    420     case bfd_mach_arm_5T:      expected = "armv5t"; break;
    421     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
    422     case bfd_mach_arm_XScale:  expected = "XScale"; break;
    423     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
    424     case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
    425     }
    426 
    427   if (strcmp (arch_string, expected) != 0)
    428     {
    429       strcpy ((char *) buffer + (offsetof (arm_Note, name)
    430 				 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
    431 	      expected);
    432 
    433       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
    434 				      (file_ptr) 0, buffer_size))
    435 	{
    436 	  _bfd_error_handler
    437 	    /* xgettext: c-format */
    438 	    (_("warning: unable to update contents of %s section in %pB"),
    439 	     note_section, abfd);
    440 	  goto FAIL;
    441 	}
    442     }
    443 
    444   free (buffer);
    445   return true;
    446 
    447  FAIL:
    448   free (buffer);
    449   return false;
    450 }
    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 {
    484   asection *	 arm_arch_section;
    485   bfd_size_type	 buffer_size;
    486   bfd_byte *	 buffer;
    487   char *	 arch_string;
    488   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   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
    494 
    495   if (arm_arch_section == NULL
    496       || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0)
    497     return bfd_mach_arm_unknown;
    498 
    499   buffer_size = arm_arch_section->size;
    500   if (buffer_size == 0)
    501     return bfd_mach_arm_unknown;
    502 
    503   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
    504     goto FAIL;
    505 
    506   /* Parse the note.  */
    507   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
    508     goto FAIL;
    509 
    510   /* Interpret the architecture string.  */
    511   for (i = ARRAY_SIZE (architectures); i--;)
    512     if (strcmp (arch_string, architectures[i].string) == 0)
    513       {
    514 	free (buffer);
    515 	return architectures[i].mach;
    516       }
    517 
    518  FAIL:
    519   free (buffer);
    520   return bfd_mach_arm_unknown;
    521 }
    522 
    523 bool
    524 bfd_is_arm_special_symbol_name (const char * name, int type)
    525 {
    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   if (!name || name[0] != '$')
    530     return false;
    531   if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
    532     type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
    533   else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
    534     type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
    535   else if (name[1] >= 'a' && name[1] <= 'z')
    536     type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
    537   else
    538     return false;
    539 
    540   return (type != 0 && (name[2] == 0 || name[2] == '.'));
    541 }
    542 
    543