(root)/
binutils-2.41/
bfd/
cpu-arm.c
       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  {
      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_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  {
     207    int  i;
     208  
     209    /* First test for an exact match.  */
     210    if (strcasecmp (string, info->printable_name) == 0)
     211      return true;
     212  
     213    /* If there is a prefix of "arm:" then skip it.  */
     214    const char * colon;
     215    if ((colon = strchr (string, ':')) != NULL)
     216      {
     217        if (strncasecmp (string, "arm", colon - string) != 0)
     218  	return false;
     219        string = colon + 1;
     220      }
     221  
     222    /* Next check for a processor name instead of an Architecture name.  */
     223    for (i = sizeof (processors) / sizeof (processors[0]); i--;)
     224      {
     225        if (strcasecmp (string, processors [i].name) == 0)
     226  	break;
     227      }
     228  
     229    if (i != -1 && info->mach == processors [i].mach)
     230      return true;
     231  
     232    /* Finally check for the default architecture.  */
     233    if (strcasecmp (string, "arm") == 0)
     234      return info->the_default;
     235  
     236    return false;
     237  }
     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  {
     289    unsigned int in  = bfd_get_mach (ibfd);
     290    unsigned int out = bfd_get_mach (obfd);
     291  
     292    /* If the output architecture is unknown, we now have a value to set.  */
     293    if (out == bfd_mach_arm_unknown)
     294      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    else if (in == bfd_mach_arm_unknown)
     299      /* FIXME: We ought to have some way to
     300         override this on the command line.  */
     301      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    else if (out == in)
     305      ;
     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    else if (in == bfd_mach_arm_ep9312
     315  	   && (out == bfd_mach_arm_XScale
     316  	       || out == bfd_mach_arm_iWMMXt
     317  	       || out == bfd_mach_arm_iWMMXt2))
     318      {
     319        /* xgettext: c-format */
     320        _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
     321  			    "whereas %pB is compiled for XScale"),
     322  			  ibfd, obfd);
     323        bfd_set_error (bfd_error_wrong_format);
     324        return false;
     325      }
     326    else if (out == bfd_mach_arm_ep9312
     327  	   && (in == bfd_mach_arm_XScale
     328  	       || in == bfd_mach_arm_iWMMXt
     329  	       || in == bfd_mach_arm_iWMMXt2))
     330      {
     331        /* xgettext: c-format */
     332        _bfd_error_handler (_("error: %pB is compiled for the EP9312, "
     333  			    "whereas %pB is compiled for XScale"),
     334  			  obfd, ibfd);
     335        bfd_set_error (bfd_error_wrong_format);
     336        return false;
     337      }
     338    else if (in > out)
     339      bfd_set_arch_mach (obfd, bfd_arch_arm, in);
     340    /* else
     341       Nothing to do.  */
     342  
     343    return true;
     344  }
     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  {
     361    unsigned long namesz;
     362    unsigned long descsz;
     363    unsigned long type;
     364    char *	descr;
     365  
     366    if (buffer_size < offsetof (arm_Note, name))
     367      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    namesz = bfd_get_32 (abfd, buffer);
     372    descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
     373    type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
     374    descr  = (char *) buffer + offsetof (arm_Note, name);
     375  
     376    /* Check for buffer overflow.  */
     377    if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
     378      return false;
     379  
     380    if (expected_name == NULL)
     381      {
     382        if (namesz != 0)
     383  	return false;
     384      }
     385    else
     386      {
     387        if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
     388  	return false;
     389  
     390        if (strcmp (descr, expected_name) != 0)
     391  	return false;
     392  
     393        descr += (namesz + 3) & ~3;
     394      }
     395  
     396    /* FIXME: We should probably check the type as well.  */
     397    (void) type;
     398  
     399    if (description_return != NULL)
     400      * description_return = descr;
     401  
     402    return true;
     403  }
     404  
     405  #define NOTE_ARCH_STRING	"arch: "
     406  
     407  bool
     408  bfd_arm_update_notes (bfd *abfd, const char *note_section)
     409  {
     410    asection *	 arm_arch_section;
     411    bfd_size_type	 buffer_size;
     412    bfd_byte *	 buffer;
     413    char *	 arch_string;
     414    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    arm_arch_section = bfd_get_section_by_name (abfd, note_section);
     420  
     421    if (arm_arch_section == NULL
     422        || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0)
     423      return true;
     424  
     425    buffer_size = arm_arch_section->size;
     426    if (buffer_size == 0)
     427      return false;
     428  
     429    if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
     430      goto FAIL;
     431  
     432    /* Parse the note.  */
     433    if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
     434      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    switch (bfd_get_mach (abfd))
     440      {
     441      default:
     442      case bfd_mach_arm_unknown: expected = "unknown"; break;
     443      case bfd_mach_arm_2:       expected = "armv2"; break;
     444      case bfd_mach_arm_2a:      expected = "armv2a"; break;
     445      case bfd_mach_arm_3:       expected = "armv3"; break;
     446      case bfd_mach_arm_3M:      expected = "armv3M"; break;
     447      case bfd_mach_arm_4:       expected = "armv4"; break;
     448      case bfd_mach_arm_4T:      expected = "armv4t"; break;
     449      case bfd_mach_arm_5:       expected = "armv5"; break;
     450      case bfd_mach_arm_5T:      expected = "armv5t"; break;
     451      case bfd_mach_arm_5TE:     expected = "armv5te"; break;
     452      case bfd_mach_arm_XScale:  expected = "XScale"; break;
     453      case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
     454      case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
     455      case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
     456      }
     457  
     458    if (strcmp (arch_string, expected) != 0)
     459      {
     460        strcpy ((char *) buffer + (offsetof (arm_Note, name)
     461  				 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
     462  	      expected);
     463  
     464        if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
     465  				      (file_ptr) 0, buffer_size))
     466  	{
     467  	  _bfd_error_handler
     468  	    /* xgettext: c-format */
     469  	    (_("warning: unable to update contents of %s section in %pB"),
     470  	     note_section, abfd);
     471  	  goto FAIL;
     472  	}
     473      }
     474  
     475    free (buffer);
     476    return true;
     477  
     478   FAIL:
     479    free (buffer);
     480    return false;
     481  }
     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  {
     514    asection *	 arm_arch_section;
     515    bfd_size_type	 buffer_size;
     516    bfd_byte *	 buffer;
     517    char *	 arch_string;
     518    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    arm_arch_section = bfd_get_section_by_name (abfd, note_section);
     524  
     525    if (arm_arch_section == NULL
     526        || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0)
     527      return bfd_mach_arm_unknown;
     528  
     529    buffer_size = arm_arch_section->size;
     530    if (buffer_size == 0)
     531      return bfd_mach_arm_unknown;
     532  
     533    if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
     534      goto FAIL;
     535  
     536    /* Parse the note.  */
     537    if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
     538      goto FAIL;
     539  
     540    /* Interpret the architecture string.  */
     541    for (i = ARRAY_SIZE (architectures); i--;)
     542      if (strcmp (arch_string, architectures[i].string) == 0)
     543        {
     544  	free (buffer);
     545  	return architectures[i].mach;
     546        }
     547  
     548   FAIL:
     549    free (buffer);
     550    return bfd_mach_arm_unknown;
     551  }
     552  
     553  bool
     554  bfd_is_arm_special_symbol_name (const char * name, int type)
     555  {
     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    if (!name || name[0] != '$')
     560      return false;
     561    if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
     562      type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
     563    else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
     564      type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
     565    else if (name[1] >= 'a' && name[1] <= 'z')
     566      type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
     567    else
     568      return false;
     569  
     570    return (type != 0 && (name[2] == 0 || name[2] == '.'));
     571  }
     572