Back to index

cell-binutils  2.17cvs20070401
cpu-arm.c
Go to the documentation of this file.
00001 /* BFD support for the ARM processor
00002    Copyright 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2005
00003    Free Software Foundation, Inc.
00004    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "libbfd.h"
00025 #include "libiberty.h"
00026 
00027 /* This routine is provided two arch_infos and works out which ARM
00028    machine which would be compatible with both and returns a pointer
00029    to its info structure.  */
00030 
00031 static const bfd_arch_info_type *
00032 compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
00033 {
00034   /* If a & b are for different architecture we can do nothing.  */
00035   if (a->arch != b->arch)
00036       return NULL;
00037 
00038   /* If a & b are for the same machine then all is well.  */
00039   if (a->mach == b->mach)
00040     return a;
00041 
00042   /* Otherwise if either a or b is the 'default' machine
00043      then it can be polymorphed into the other.  */
00044   if (a->the_default)
00045     return b;
00046 
00047   if (b->the_default)
00048     return a;
00049 
00050   /* So far all newer ARM architecture cores are
00051      supersets of previous cores.  */
00052   if (a->mach < b->mach)
00053     return b;
00054   else if (a->mach > b->mach)
00055     return a;
00056 
00057   /* Never reached!  */
00058   return NULL;
00059 }
00060 
00061 static struct
00062 {
00063   unsigned int mach;
00064   char *       name;
00065 }
00066 processors[] =
00067 {
00068   { bfd_mach_arm_2,  "arm2"     },
00069   { bfd_mach_arm_2a, "arm250"   },
00070   { bfd_mach_arm_2a, "arm3"     },
00071   { bfd_mach_arm_3,  "arm6"     },
00072   { bfd_mach_arm_3,  "arm60"    },
00073   { bfd_mach_arm_3,  "arm600"   },
00074   { bfd_mach_arm_3,  "arm610"   },
00075   { bfd_mach_arm_3,  "arm7"     },
00076   { bfd_mach_arm_3,  "arm710"   },
00077   { bfd_mach_arm_3,  "arm7500"  },
00078   { bfd_mach_arm_3,  "arm7d"    },
00079   { bfd_mach_arm_3,  "arm7di"   },
00080   { bfd_mach_arm_3M, "arm7dm"   },
00081   { bfd_mach_arm_3M, "arm7dmi"  },
00082   { bfd_mach_arm_4T, "arm7tdmi" },
00083   { bfd_mach_arm_4,  "arm8"     },
00084   { bfd_mach_arm_4,  "arm810"   },
00085   { bfd_mach_arm_4,  "arm9"     },
00086   { bfd_mach_arm_4,  "arm920"   },
00087   { bfd_mach_arm_4T, "arm920t"  },
00088   { bfd_mach_arm_4T, "arm9tdmi" },
00089   { bfd_mach_arm_4,  "sa1"      },
00090   { bfd_mach_arm_4,  "strongarm"},
00091   { bfd_mach_arm_4,  "strongarm110" },
00092   { bfd_mach_arm_4,  "strongarm1100" },
00093   { bfd_mach_arm_XScale, "xscale" },
00094   { bfd_mach_arm_ep9312, "ep9312" },
00095   { bfd_mach_arm_iWMMXt, "iwmmxt" },
00096   { bfd_mach_arm_iWMMXt2, "iwmmxt2" }
00097 };
00098 
00099 static bfd_boolean
00100 scan (const struct bfd_arch_info *info, const char *string)
00101 {
00102   int  i;
00103 
00104   /* First test for an exact match.  */
00105   if (strcasecmp (string, info->printable_name) == 0)
00106     return TRUE;
00107 
00108   /* Next check for a processor name instead of an Architecture name.  */
00109   for (i = sizeof (processors) / sizeof (processors[0]); i--;)
00110     {
00111       if (strcasecmp (string, processors [i].name) == 0)
00112        break;
00113     }
00114 
00115   if (i != -1 && info->mach == processors [i].mach)
00116     return TRUE;
00117 
00118   /* Finally check for the default architecture.  */
00119   if (strcasecmp (string, "arm") == 0)
00120     return info->the_default;
00121 
00122   return FALSE;
00123 }
00124 
00125 #define N(number, print, default, next)  \
00126 {  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }
00127 
00128 static const bfd_arch_info_type arch_info_struct[] =
00129 {
00130   N (bfd_mach_arm_2,      "armv2",   FALSE, & arch_info_struct[1]),
00131   N (bfd_mach_arm_2a,     "armv2a",  FALSE, & arch_info_struct[2]),
00132   N (bfd_mach_arm_3,      "armv3",   FALSE, & arch_info_struct[3]),
00133   N (bfd_mach_arm_3M,     "armv3m",  FALSE, & arch_info_struct[4]),
00134   N (bfd_mach_arm_4,      "armv4",   FALSE, & arch_info_struct[5]),
00135   N (bfd_mach_arm_4T,     "armv4t",  FALSE, & arch_info_struct[6]),
00136   N (bfd_mach_arm_5,      "armv5",   FALSE, & arch_info_struct[7]),
00137   N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
00138   N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
00139   N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
00140   N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
00141   N (bfd_mach_arm_iWMMXt, "iwmmxt",  FALSE, & arch_info_struct[12]),
00142   N (bfd_mach_arm_iWMMXt2, "iwmmxt2", FALSE, NULL)
00143 };
00144 
00145 const bfd_arch_info_type bfd_arm_arch =
00146   N (0, "arm", TRUE, & arch_info_struct[0]);
00147 
00148 /* Support functions used by both the COFF and ELF versions of the ARM port.  */
00149 
00150 /* Handle the merging of the 'machine' settings of input file IBFD
00151    and an output file OBFD.  These values actually represent the
00152    different possible ARM architecture variants.
00153    Returns TRUE if they were merged successfully or FALSE otherwise.  */
00154 
00155 bfd_boolean
00156 bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
00157 {
00158   unsigned int in  = bfd_get_mach (ibfd);
00159   unsigned int out = bfd_get_mach (obfd);
00160 
00161   /* If the output architecture is unknown, we now have a value to set.  */
00162   if (out == bfd_mach_arm_unknown)
00163     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
00164 
00165   /* If the input architecture is unknown,
00166      then so must be the output architecture.  */
00167   else if (in == bfd_mach_arm_unknown)
00168     /* FIXME: We ought to have some way to
00169        override this on the command line.  */
00170     bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
00171 
00172   /* If they are the same then nothing needs to be done.  */
00173   else if (out == in)
00174     ;
00175 
00176   /* Otherwise the general principle that a earlier architecture can be
00177      linked with a later architecture to produce a binary that will execute
00178      on the later architecture.
00179 
00180      We fail however if we attempt to link a Cirrus EP9312 binary with an
00181      Intel XScale binary, since these architecture have co-processors which
00182      will not both be present on the same physical hardware.  */
00183   else if (in == bfd_mach_arm_ep9312
00184           && (out == bfd_mach_arm_XScale
00185               || out == bfd_mach_arm_iWMMXt
00186               || out == bfd_mach_arm_iWMMXt2))
00187     {
00188       _bfd_error_handler (_("\
00189 ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
00190                        ibfd, obfd);
00191       bfd_set_error (bfd_error_wrong_format);
00192       return FALSE;
00193     }
00194   else if (out == bfd_mach_arm_ep9312
00195           && (in == bfd_mach_arm_XScale
00196               || in == bfd_mach_arm_iWMMXt
00197               || in == bfd_mach_arm_iWMMXt2))
00198     {
00199       _bfd_error_handler (_("\
00200 ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
00201                        obfd, ibfd);
00202       bfd_set_error (bfd_error_wrong_format);
00203       return FALSE;
00204     }
00205   else if (in > out)
00206     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
00207   /* else
00208      Nothing to do.  */
00209 
00210   return TRUE;
00211 }
00212 
00213 typedef struct
00214 {
00215   unsigned char      namesz[4];    /* Size of entry's owner string.  */
00216   unsigned char      descsz[4];    /* Size of the note descriptor.  */
00217   unsigned char      type[4];      /* Interpretation of the descriptor.  */
00218   char        name[1];      /* Start of the name+desc data.  */
00219 } arm_Note;
00220 
00221 static bfd_boolean
00222 arm_check_note (bfd *abfd,
00223               bfd_byte *buffer,
00224               bfd_size_type buffer_size,
00225               const char *expected_name,
00226               char **description_return)
00227 {
00228   unsigned long namesz;
00229   unsigned long descsz;
00230   unsigned long type;
00231   char *        descr;
00232 
00233   if (buffer_size < offsetof (arm_Note, name))
00234     return FALSE;
00235 
00236   /* We have to extract the values this way to allow for a
00237      host whose endian-ness is different from the target.  */
00238   namesz = bfd_get_32 (abfd, buffer);
00239   descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
00240   type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
00241   descr  = (char *) buffer + offsetof (arm_Note, name);
00242 
00243   /* Check for buffer overflow.  */
00244   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
00245     return FALSE;
00246 
00247   if (expected_name == NULL)
00248     {
00249       if (namesz != 0)
00250        return FALSE;
00251     }
00252   else
00253     { 
00254       if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
00255        return FALSE;
00256       
00257       if (strcmp (descr, expected_name) != 0)
00258        return FALSE;
00259 
00260       descr += (namesz + 3) & ~3;
00261     }
00262 
00263   /* FIXME: We should probably check the type as well.  */
00264 
00265   if (description_return != NULL)
00266     * description_return = descr;
00267 
00268   return TRUE;
00269 }
00270 
00271 #define NOTE_ARCH_STRING    "arch: "
00272 
00273 bfd_boolean
00274 bfd_arm_update_notes (bfd *abfd, const char *note_section)
00275 {
00276   asection *     arm_arch_section;
00277   bfd_size_type  buffer_size;
00278   bfd_byte *     buffer;
00279   char *         arch_string;
00280   char *         expected;
00281 
00282   /* Look for a note section.  If one is present check the architecture
00283      string encoded in it, and set it to the current architecture if it is
00284      different.  */
00285   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
00286 
00287   if (arm_arch_section == NULL)
00288     return TRUE;
00289 
00290   buffer_size = arm_arch_section->size;
00291   if (buffer_size == 0)
00292     return FALSE;
00293 
00294   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
00295     goto FAIL;
00296 
00297   /* Parse the note.  */
00298   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
00299     goto FAIL;
00300 
00301   /* Check the architecture in the note against the architecture of the bfd.  */
00302   switch (bfd_get_mach (abfd))
00303     {
00304     default:
00305     case bfd_mach_arm_unknown: expected = "unknown"; break;
00306     case bfd_mach_arm_2:       expected = "armv2"; break;
00307     case bfd_mach_arm_2a:      expected = "armv2a"; break;
00308     case bfd_mach_arm_3:       expected = "armv3"; break;
00309     case bfd_mach_arm_3M:      expected = "armv3M"; break;
00310     case bfd_mach_arm_4:       expected = "armv4"; break;
00311     case bfd_mach_arm_4T:      expected = "armv4t"; break;
00312     case bfd_mach_arm_5:       expected = "armv5"; break;
00313     case bfd_mach_arm_5T:      expected = "armv5t"; break;
00314     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
00315     case bfd_mach_arm_XScale:  expected = "XScale"; break;
00316     case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
00317     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
00318     case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
00319     }
00320 
00321   if (strcmp (arch_string, expected) != 0)
00322     {
00323       strcpy ((char *) buffer + (offsetof (arm_Note, name)
00324                              + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
00325              expected);
00326 
00327       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
00328                                   (file_ptr) 0, buffer_size))
00329        {
00330          (*_bfd_error_handler)
00331            (_("warning: unable to update contents of %s section in %s"),
00332             note_section, bfd_get_filename (abfd));
00333          goto FAIL;
00334        }
00335     }
00336 
00337   free (buffer);
00338   return TRUE;
00339 
00340  FAIL:
00341   if (buffer != NULL)
00342     free (buffer);
00343   return FALSE;
00344 }
00345 
00346 
00347 static struct
00348 {
00349   const char * string;
00350   unsigned int mach;
00351 }
00352 architectures[] =
00353 {
00354   { "armv2",   bfd_mach_arm_2 },
00355   { "armv2a",  bfd_mach_arm_2a },
00356   { "armv3",   bfd_mach_arm_3 },
00357   { "armv3M",  bfd_mach_arm_3M },
00358   { "armv4",   bfd_mach_arm_4 },
00359   { "armv4t",  bfd_mach_arm_4T },
00360   { "armv5",   bfd_mach_arm_5 },
00361   { "armv5t",  bfd_mach_arm_5T },
00362   { "armv5te", bfd_mach_arm_5TE },
00363   { "XScale",  bfd_mach_arm_XScale },
00364   { "ep9312",  bfd_mach_arm_ep9312 },
00365   { "iWMMXt",  bfd_mach_arm_iWMMXt },
00366   { "iWMMXt2", bfd_mach_arm_iWMMXt2 }
00367 };
00368 
00369 /* Extract the machine number stored in a note section.  */
00370 unsigned int
00371 bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
00372 {
00373   asection *     arm_arch_section;
00374   bfd_size_type  buffer_size;
00375   bfd_byte *     buffer;
00376   char *         arch_string;
00377   int            i;
00378 
00379   /* Look for a note section.  If one is present check the architecture
00380      string encoded in it, and set it to the current architecture if it is
00381      different.  */
00382   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
00383 
00384   if (arm_arch_section == NULL)
00385     return bfd_mach_arm_unknown;
00386 
00387   buffer_size = arm_arch_section->size;
00388   if (buffer_size == 0)
00389     return bfd_mach_arm_unknown;
00390 
00391   if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
00392     goto FAIL;
00393 
00394   /* Parse the note.  */
00395   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
00396     goto FAIL;
00397 
00398   /* Interpret the architecture string.  */
00399   for (i = ARRAY_SIZE (architectures); i--;)
00400     if (strcmp (arch_string, architectures[i].string) == 0)
00401       {
00402        free (buffer);
00403        return architectures[i].mach;
00404       }
00405 
00406  FAIL:
00407   if (buffer != NULL)
00408     free (buffer);
00409   return bfd_mach_arm_unknown;
00410 }
00411 
00412 bfd_boolean
00413 bfd_is_arm_special_symbol_name (const char * name, int type)
00414 {
00415   /* The ARM compiler outputs several obsolete forms.  Recognize them
00416      in addition to the standard $a, $t and $d.  We are somewhat loose
00417      in what we accept here, since the full set is not documented.  */
00418   if (!name || name[0] != '$')
00419     return FALSE;
00420   if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
00421     type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
00422   else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
00423     type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
00424   else if (name[1] >= 'a' && name[1] <= 'z')
00425     type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
00426   else
00427     return FALSE;
00428 
00429   return (type != 0 && (name[2] == 0 || name[2] == '.'));
00430 }
00431