/[gcl]/gcl/binutils/bfd/cpu-arm.c
ViewVC logotype

Diff of /gcl/binutils/bfd/cpu-arm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by camm, Fri Aug 9 05:35:01 2002 UTC revision 1.1.1.1.20.1 by camm, Fri Sep 30 02:08:56 2005 UTC
# Line 1  Line 1 
1  /* BFD support for the ARM processor  /* BFD support for the ARM processor
2     Copyright 1994, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.     Copyright 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2005
3       Free Software Foundation, Inc.
4     Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)     Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5    
6     This file is part of BFD, the Binary File Descriptor library.     This file is part of BFD, the Binary File Descriptor library.
# Line 21  Line 22 
22  #include "bfd.h"  #include "bfd.h"
23  #include "sysdep.h"  #include "sysdep.h"
24  #include "libbfd.h"  #include "libbfd.h"
25    #include "libiberty.h"
 static const bfd_arch_info_type * compatible  
   PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));  
 static boolean scan  
   PARAMS ((const struct bfd_arch_info *, const char *));  
26    
27  /* This routine is provided two arch_infos and works out which ARM  /* This routine is provided two arch_infos and works out which ARM
28     machine which would be compatible with both and returns a pointer     machine which would be compatible with both and returns a pointer
29     to its info structure.  */     to its info structure.  */
30    
31  static const bfd_arch_info_type *  static const bfd_arch_info_type *
32  compatible (a,b)  compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
      const bfd_arch_info_type * a;  
      const bfd_arch_info_type * b;  
33  {  {
34    /* If a & b are for different architecture we can do nothing.  */    /* If a & b are for different architecture we can do nothing.  */
35    if (a->arch != b->arch)    if (a->arch != b->arch)
# Line 95  processors[] = Line 90  processors[] =
90    { bfd_mach_arm_4,  "strongarm"},    { bfd_mach_arm_4,  "strongarm"},
91    { bfd_mach_arm_4,  "strongarm110" },    { bfd_mach_arm_4,  "strongarm110" },
92    { bfd_mach_arm_4,  "strongarm1100" },    { bfd_mach_arm_4,  "strongarm1100" },
93    { bfd_mach_arm_XScale, "xscale" }    { bfd_mach_arm_XScale, "xscale" },
94      { bfd_mach_arm_ep9312, "ep9312" },
95      { bfd_mach_arm_iWMMXt, "iwmmxt" }
96  };  };
97    
98  static boolean  static bfd_boolean
99  scan (info, string)  scan (const struct bfd_arch_info *info, const char *string)
      const struct bfd_arch_info * info;  
      const char * string;  
100  {  {
101    int  i;    int  i;
102    
103    /* First test for an exact match.  */    /* First test for an exact match.  */
104    if (strcasecmp (string, info->printable_name) == 0)    if (strcasecmp (string, info->printable_name) == 0)
105      return true;      return TRUE;
106    
107    /* Next check for a processor name instead of an Architecture name.  */    /* Next check for a processor name instead of an Architecture name.  */
108    for (i = sizeof (processors) / sizeof (processors[0]); i--;)    for (i = sizeof (processors) / sizeof (processors[0]); i--;)
# Line 117  scan (info, string) Line 112  scan (info, string)
112      }      }
113    
114    if (i != -1 && info->mach == processors [i].mach)    if (i != -1 && info->mach == processors [i].mach)
115      return true;      return TRUE;
116    
117    /* Finally check for the default architecture.  */    /* Finally check for the default architecture.  */
118    if (strcasecmp (string, "arm") == 0)    if (strcasecmp (string, "arm") == 0)
119      return info->the_default;      return info->the_default;
120    
121    return false;    return FALSE;
122  }  }
123    
124  #define N(number, print, default, next)  \  #define N(number, print, default, next)  \
# Line 131  scan (info, string) Line 126  scan (info, string)
126    
127  static const bfd_arch_info_type arch_info_struct[] =  static const bfd_arch_info_type arch_info_struct[] =
128  {  {
129    N (bfd_mach_arm_2,      "armv2",   false, & arch_info_struct[1]),    N (bfd_mach_arm_2,      "armv2",   FALSE, & arch_info_struct[1]),
130    N (bfd_mach_arm_2a,     "armv2a",  false, & arch_info_struct[2]),    N (bfd_mach_arm_2a,     "armv2a",  FALSE, & arch_info_struct[2]),
131    N (bfd_mach_arm_3,      "armv3",   false, & arch_info_struct[3]),    N (bfd_mach_arm_3,      "armv3",   FALSE, & arch_info_struct[3]),
132    N (bfd_mach_arm_3M,     "armv3m",  false, & arch_info_struct[4]),    N (bfd_mach_arm_3M,     "armv3m",  FALSE, & arch_info_struct[4]),
133    N (bfd_mach_arm_4,      "armv4",   false, & arch_info_struct[5]),    N (bfd_mach_arm_4,      "armv4",   FALSE, & arch_info_struct[5]),
134    N (bfd_mach_arm_4T,     "armv4t",  false, & arch_info_struct[6]),    N (bfd_mach_arm_4T,     "armv4t",  FALSE, & arch_info_struct[6]),
135    N (bfd_mach_arm_5,      "armv5",   false, & arch_info_struct[7]),    N (bfd_mach_arm_5,      "armv5",   FALSE, & arch_info_struct[7]),
136    N (bfd_mach_arm_5T,     "armv5t",  false, & arch_info_struct[8]),    N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
137    N (bfd_mach_arm_5TE,    "armv5te", false, & arch_info_struct[9]),    N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
138    N (bfd_mach_arm_XScale, "xscale",  false, NULL)    N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
139      N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
140      N (bfd_mach_arm_iWMMXt,"iwmmxt",  FALSE, NULL)
141  };  };
142    
143  const bfd_arch_info_type bfd_arm_arch =  const bfd_arch_info_type bfd_arm_arch =
144    N (0, "arm", true, & arch_info_struct[0]);    N (0, "arm", TRUE, & arch_info_struct[0]);
145    
146    /* Support functions used by both the COFF and ELF versions of the ARM port.  */
147    
148    /* Handle the merging of the 'machine' settings of input file IBFD
149       and an output file OBFD.  These values actually represent the
150       different possible ARM architecture variants.
151       Returns TRUE if they were merged successfully or FALSE otherwise.  */
152    
153    bfd_boolean
154    bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
155    {
156      unsigned int in  = bfd_get_mach (ibfd);
157      unsigned int out = bfd_get_mach (obfd);
158    
159      /* If the output architecture is unknown, we now have a value to set.  */
160      if (out == bfd_mach_arm_unknown)
161        bfd_set_arch_mach (obfd, bfd_arch_arm, in);
162    
163      /* If the input architecture is unknown,
164         then so must be the output architecture.  */
165      else if (in == bfd_mach_arm_unknown)
166        /* FIXME: We ought to have some way to
167           override this on the command line.  */
168        bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
169    
170      /* If they are the same then nothing needs to be done.  */
171      else if (out == in)
172        ;
173    
174      /* Otherwise the general principle that a earlier architecture can be
175         linked with a later architecture to produce a binary that will execute
176         on the later architecture.
177    
178         We fail however if we attempt to link a Cirrus EP9312 binary with an
179         Intel XScale binary, since these architecture have co-processors which
180         will not both be present on the same physical hardware.  */
181      else if (in == bfd_mach_arm_ep9312
182               && (out == bfd_mach_arm_XScale || out == bfd_mach_arm_iWMMXt))
183        {
184          _bfd_error_handler (_("\
185    ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
186                              ibfd, obfd);
187          bfd_set_error (bfd_error_wrong_format);
188          return FALSE;
189        }
190      else if (out == bfd_mach_arm_ep9312
191               && (in == bfd_mach_arm_XScale || in == bfd_mach_arm_iWMMXt))
192        {
193          _bfd_error_handler (_("\
194    ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
195                              obfd, ibfd);
196          bfd_set_error (bfd_error_wrong_format);
197          return FALSE;
198        }
199      else if (in > out)
200        bfd_set_arch_mach (obfd, bfd_arch_arm, in);
201      /* else
202         Nothing to do.  */
203    
204      return TRUE;
205    }
206    
207    typedef struct
208    {
209      unsigned char namesz[4];      /* Size of entry's owner string.  */
210      unsigned char descsz[4];      /* Size of the note descriptor.  */
211      unsigned char type[4];        /* Interpretation of the descriptor.  */
212      char          name[1];        /* Start of the name+desc data.  */
213    } arm_Note;
214    
215    static bfd_boolean
216    arm_check_note (bfd *abfd,
217                    bfd_byte *buffer,
218                    bfd_size_type buffer_size,
219                    const char *expected_name,
220                    char **description_return)
221    {
222      unsigned long namesz;
223      unsigned long descsz;
224      unsigned long type;
225      char *        descr;
226    
227      if (buffer_size < offsetof (arm_Note, name))
228        return FALSE;
229    
230      /* We have to extract the values this way to allow for a
231         host whose endian-ness is different from the target.  */
232      namesz = bfd_get_32 (abfd, buffer);
233      descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
234      type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
235      descr  = (char *) buffer + offsetof (arm_Note, name);
236    
237      /* Check for buffer overflow.  */
238      if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
239        return FALSE;
240    
241      if (expected_name == NULL)
242        {
243          if (namesz != 0)
244            return FALSE;
245        }
246      else
247        {
248          if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
249            return FALSE;
250          
251          if (strcmp (descr, expected_name) != 0)
252            return FALSE;
253    
254          descr += (namesz + 3) & ~3;
255        }
256    
257      /* FIXME: We should probably check the type as well.  */
258    
259      if (description_return != NULL)
260        * description_return = descr;
261    
262      return TRUE;
263    }
264    
265    #define NOTE_ARCH_STRING        "arch: "
266    
267    bfd_boolean
268    bfd_arm_update_notes (bfd *abfd, const char *note_section)
269    {
270      asection *     arm_arch_section;
271      bfd_size_type  buffer_size;
272      bfd_byte *     buffer;
273      char *         arch_string;
274      char *         expected;
275    
276      /* Look for a note section.  If one is present check the architecture
277         string encoded in it, and set it to the current architecture if it is
278         different.  */
279      arm_arch_section = bfd_get_section_by_name (abfd, note_section);
280    
281      if (arm_arch_section == NULL)
282        return TRUE;
283    
284      buffer_size = arm_arch_section->size;
285      if (buffer_size == 0)
286        return FALSE;
287    
288      if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
289        goto FAIL;
290    
291      /* Parse the note.  */
292      if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
293        goto FAIL;
294    
295      /* Check the architecture in the note against the architecture of the bfd.  */
296      switch (bfd_get_mach (abfd))
297        {
298        default:
299        case bfd_mach_arm_unknown: expected = "unknown"; break;
300        case bfd_mach_arm_2:       expected = "armv2"; break;
301        case bfd_mach_arm_2a:      expected = "armv2a"; break;
302        case bfd_mach_arm_3:       expected = "armv3"; break;
303        case bfd_mach_arm_3M:      expected = "armv3M"; break;
304        case bfd_mach_arm_4:       expected = "armv4"; break;
305        case bfd_mach_arm_4T:      expected = "armv4t"; break;
306        case bfd_mach_arm_5:       expected = "armv5"; break;
307        case bfd_mach_arm_5T:      expected = "armv5t"; break;
308        case bfd_mach_arm_5TE:     expected = "armv5te"; break;
309        case bfd_mach_arm_XScale:  expected = "XScale"; break;
310        case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
311        case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
312        }
313    
314      if (strcmp (arch_string, expected) != 0)
315        {
316          strcpy ((char *) buffer + (offsetof (arm_Note, name)
317                                     + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
318                  expected);
319    
320          if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
321                                          (file_ptr) 0, buffer_size))
322            {
323              (*_bfd_error_handler)
324                (_("warning: unable to update contents of %s section in %s"),
325                 note_section, bfd_get_filename (abfd));
326              goto FAIL;
327            }
328        }
329    
330      free (buffer);
331      return TRUE;
332    
333     FAIL:
334      if (buffer != NULL)
335        free (buffer);
336      return FALSE;
337    }
338    
339    
340    static struct
341    {
342      const char * string;
343      unsigned int mach;
344    }
345    architectures[] =
346    {
347      { "armv2",   bfd_mach_arm_2 },
348      { "armv2a",  bfd_mach_arm_2a },
349      { "armv3",   bfd_mach_arm_3 },
350      { "armv3M",  bfd_mach_arm_3M },
351      { "armv4",   bfd_mach_arm_4 },
352      { "armv4t",  bfd_mach_arm_4T },
353      { "armv5",   bfd_mach_arm_5 },
354      { "armv5t",  bfd_mach_arm_5T },
355      { "armv5te", bfd_mach_arm_5TE },
356      { "XScale",  bfd_mach_arm_XScale },
357      { "ep9312",  bfd_mach_arm_ep9312 },
358      { "iWMMXt",  bfd_mach_arm_iWMMXt }
359    };
360    
361    /* Extract the machine number stored in a note section.  */
362    unsigned int
363    bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
364    {
365      asection *     arm_arch_section;
366      bfd_size_type  buffer_size;
367      bfd_byte *     buffer;
368      char *         arch_string;
369      int            i;
370    
371      /* Look for a note section.  If one is present check the architecture
372         string encoded in it, and set it to the current architecture if it is
373         different.  */
374      arm_arch_section = bfd_get_section_by_name (abfd, note_section);
375    
376      if (arm_arch_section == NULL)
377        return bfd_mach_arm_unknown;
378    
379      buffer_size = arm_arch_section->size;
380      if (buffer_size == 0)
381        return bfd_mach_arm_unknown;
382    
383      if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
384        goto FAIL;
385    
386      /* Parse the note.  */
387      if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
388        goto FAIL;
389    
390      /* Interpret the architecture string.  */
391      for (i = ARRAY_SIZE (architectures); i--;)
392        if (strcmp (arch_string, architectures[i].string) == 0)
393          {
394            free (buffer);
395            return architectures[i].mach;
396          }
397    
398     FAIL:
399      if (buffer != NULL)
400        free (buffer);
401      return bfd_mach_arm_unknown;
402    }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.1.20.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26