cpu-arm.c revision 130562
1/* BFD support for the ARM processor
2   Copyright 1994, 1997, 1999, 2000, 2002, 2003 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24#include "libiberty.h"
25
26static const bfd_arch_info_type * compatible
27  PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
28static bfd_boolean scan
29  PARAMS ((const struct bfd_arch_info *, const char *));
30static bfd_boolean arm_check_note
31  PARAMS ((bfd *, char *, bfd_size_type, const char *, char **));
32
33/* This routine is provided two arch_infos and works out which ARM
34   machine which would be compatible with both and returns a pointer
35   to its info structure.  */
36
37static const bfd_arch_info_type *
38compatible (a,b)
39     const bfd_arch_info_type * a;
40     const bfd_arch_info_type * b;
41{
42  /* If a & b are for different architecture we can do nothing.  */
43  if (a->arch != b->arch)
44      return NULL;
45
46  /* If a & b are for the same machine then all is well.  */
47  if (a->mach == b->mach)
48    return a;
49
50  /* Otherwise if either a or b is the 'default' machine
51     then it can be polymorphed into the other.  */
52  if (a->the_default)
53    return b;
54
55  if (b->the_default)
56    return a;
57
58  /* So far all newer ARM architecture cores are
59     supersets of previous cores.  */
60  if (a->mach < b->mach)
61    return b;
62  else if (a->mach > b->mach)
63    return a;
64
65  /* Never reached!  */
66  return NULL;
67}
68
69static struct
70{
71  unsigned int mach;
72  char *       name;
73}
74processors[] =
75{
76  { bfd_mach_arm_2,  "arm2"     },
77  { bfd_mach_arm_2a, "arm250"   },
78  { bfd_mach_arm_2a, "arm3"     },
79  { bfd_mach_arm_3,  "arm6"     },
80  { bfd_mach_arm_3,  "arm60"    },
81  { bfd_mach_arm_3,  "arm600"   },
82  { bfd_mach_arm_3,  "arm610"   },
83  { bfd_mach_arm_3,  "arm7"     },
84  { bfd_mach_arm_3,  "arm710"   },
85  { bfd_mach_arm_3,  "arm7500"  },
86  { bfd_mach_arm_3,  "arm7d"    },
87  { bfd_mach_arm_3,  "arm7di"   },
88  { bfd_mach_arm_3M, "arm7dm"   },
89  { bfd_mach_arm_3M, "arm7dmi"  },
90  { bfd_mach_arm_4T, "arm7tdmi" },
91  { bfd_mach_arm_4,  "arm8"     },
92  { bfd_mach_arm_4,  "arm810"   },
93  { bfd_mach_arm_4,  "arm9"     },
94  { bfd_mach_arm_4,  "arm920"   },
95  { bfd_mach_arm_4T, "arm920t"  },
96  { bfd_mach_arm_4T, "arm9tdmi" },
97  { bfd_mach_arm_4,  "sa1"      },
98  { bfd_mach_arm_4,  "strongarm"},
99  { bfd_mach_arm_4,  "strongarm110" },
100  { bfd_mach_arm_4,  "strongarm1100" },
101  { bfd_mach_arm_XScale, "xscale" },
102  { bfd_mach_arm_ep9312, "ep9312" },
103  { bfd_mach_arm_iWMMXt, "iwmmxt" }
104};
105
106static bfd_boolean
107scan (info, string)
108     const struct bfd_arch_info * info;
109     const char * string;
110{
111  int  i;
112
113  /* First test for an exact match.  */
114  if (strcasecmp (string, info->printable_name) == 0)
115    return TRUE;
116
117  /* Next check for a processor name instead of an Architecture name.  */
118  for (i = sizeof (processors) / sizeof (processors[0]); i--;)
119    {
120      if (strcasecmp (string, processors [i].name) == 0)
121	break;
122    }
123
124  if (i != -1 && info->mach == processors [i].mach)
125    return TRUE;
126
127  /* Finally check for the default architecture.  */
128  if (strcasecmp (string, "arm") == 0)
129    return info->the_default;
130
131  return FALSE;
132}
133
134#define N(number, print, default, next)  \
135{  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }
136
137static const bfd_arch_info_type arch_info_struct[] =
138{
139  N (bfd_mach_arm_2,      "armv2",   FALSE, & arch_info_struct[1]),
140  N (bfd_mach_arm_2a,     "armv2a",  FALSE, & arch_info_struct[2]),
141  N (bfd_mach_arm_3,      "armv3",   FALSE, & arch_info_struct[3]),
142  N (bfd_mach_arm_3M,     "armv3m",  FALSE, & arch_info_struct[4]),
143  N (bfd_mach_arm_4,      "armv4",   FALSE, & arch_info_struct[5]),
144  N (bfd_mach_arm_4T,     "armv4t",  FALSE, & arch_info_struct[6]),
145  N (bfd_mach_arm_5,      "armv5",   FALSE, & arch_info_struct[7]),
146  N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
147  N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
148  N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
149  N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
150  N (bfd_mach_arm_iWMMXt,"iwmmxt",  FALSE, NULL)
151};
152
153const bfd_arch_info_type bfd_arm_arch =
154  N (0, "arm", TRUE, & arch_info_struct[0]);
155
156/* Support functions used by both the COFF and ELF versions of the ARM port.  */
157
158/* Handle the merging of the 'machine' settings of input file IBFD
159   and an output file OBFD.  These values actually represent the
160   different possible ARM architecture variants.
161   Returns TRUE if they were merged successfully or FALSE otherwise.  */
162
163bfd_boolean
164bfd_arm_merge_machines (ibfd, obfd)
165     bfd * ibfd;
166     bfd * obfd;
167{
168  unsigned int in  = bfd_get_mach (ibfd);
169  unsigned int out = bfd_get_mach (obfd);
170
171  /* If the output architecture is unknown, we now have a value to set.  */
172  if (out == bfd_mach_arm_unknown)
173    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
174
175  /* If the input architecture is unknown,
176     then so must be the output architecture.  */
177  else if (in == bfd_mach_arm_unknown)
178    /* FIXME: We ought to have some way to
179       override this on the command line.  */
180    bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
181
182  /* If they are the same then nothing needs to be done.  */
183  else if (out == in)
184    ;
185
186  /* Otherwise the general principle that a earlier architecture can be
187     linked with a later architecture to produce a binary that will execute
188     on the later architecture.
189
190     We fail however if we attempt to link a Cirrus EP9312 binary with an
191     Intel XScale binary, since these architecture have co-processors which
192     will not both be present on the same physical hardware.  */
193  else if (in == bfd_mach_arm_ep9312
194	   && (out == bfd_mach_arm_XScale || out == bfd_mach_arm_iWMMXt))
195    {
196      _bfd_error_handler (_("\
197ERROR: %s is compiled for the EP9312, whereas %s is compiled for XScale"),
198			  bfd_archive_filename (ibfd),
199			  bfd_get_filename (obfd));
200      bfd_set_error (bfd_error_wrong_format);
201      return FALSE;
202    }
203  else if (out == bfd_mach_arm_ep9312
204	   && (in == bfd_mach_arm_XScale || in == bfd_mach_arm_iWMMXt))
205    {
206      _bfd_error_handler (_("\
207ERROR: %s is compiled for the EP9312, whereas %s is compiled for XScale"),
208			  bfd_archive_filename (obfd),
209			  bfd_get_filename (ibfd));
210      bfd_set_error (bfd_error_wrong_format);
211      return FALSE;
212    }
213  else if (in > out)
214    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
215  /* else
216     Nothing to do.  */
217
218  return TRUE;
219}
220
221typedef struct
222{
223  unsigned char	namesz[4];	/* Size of entry's owner string.  */
224  unsigned char	descsz[4];	/* Size of the note descriptor.  */
225  unsigned char	type[4];	/* Interpretation of the descriptor.  */
226  char		name[1];	/* Start of the name+desc data.  */
227} arm_Note;
228
229static bfd_boolean
230arm_check_note (abfd, buffer, buffer_size, expected_name, description_return)
231     bfd *           abfd;
232     char *          buffer;
233     bfd_size_type   buffer_size;
234     const char *    expected_name;
235     char **         description_return;
236{
237  unsigned long namesz;
238  unsigned long descsz;
239  unsigned long type;
240  char *        descr;
241
242  if (buffer_size < offsetof (arm_Note, name))
243    return FALSE;
244
245  /* We have to extract the values this way to allow for a
246     host whose endian-ness is different from the target.  */
247  namesz = bfd_get_32 (abfd, buffer);
248  descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
249  type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
250  descr  = buffer + offsetof (arm_Note, name);
251
252  /* Check for buffer overflow.  */
253  if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
254    return FALSE;
255
256  if (expected_name == NULL)
257    {
258      if (namesz != 0)
259	return FALSE;
260    }
261  else
262    {
263      if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
264	return FALSE;
265
266      if (strcmp (descr, expected_name) != 0)
267	return FALSE;
268
269      descr += (namesz + 3) & ~3;
270    }
271
272  /* FIXME: We should probably check the type as well.  */
273
274  if (description_return != NULL)
275    * description_return = descr;
276
277  return TRUE;
278}
279
280#define NOTE_ARCH_STRING 	"arch: "
281
282bfd_boolean
283bfd_arm_update_notes (abfd, note_section)
284     bfd * abfd;
285     const char * note_section;
286{
287  asection *     arm_arch_section;
288  bfd_size_type  buffer_size;
289  char *         buffer;
290  char *         arch_string;
291  char *         expected;
292
293  /* Look for a note section.  If one is present check the architecture
294     string encoded in it, and set it to the current architecture if it is
295     different.  */
296  arm_arch_section = bfd_get_section_by_name (abfd, note_section);
297
298  if (arm_arch_section == NULL)
299    return TRUE;
300
301  buffer_size = arm_arch_section->_raw_size;
302  if (buffer_size == 0)
303    return FALSE;
304
305  buffer = bfd_malloc (buffer_size);
306  if (buffer == NULL)
307    return FALSE;
308
309  if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
310				  (file_ptr) 0, buffer_size))
311    goto FAIL;
312
313  /* Parse the note.  */
314  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
315    goto FAIL;
316
317  /* Check the architecture in the note against the architecture of the bfd.  */
318  switch (bfd_get_mach (abfd))
319    {
320    default:
321    case bfd_mach_arm_unknown: expected = "unknown"; break;
322    case bfd_mach_arm_2:       expected = "armv2"; break;
323    case bfd_mach_arm_2a:      expected = "armv2a"; break;
324    case bfd_mach_arm_3:       expected = "armv3"; break;
325    case bfd_mach_arm_3M:      expected = "armv3M"; break;
326    case bfd_mach_arm_4:       expected = "armv4"; break;
327    case bfd_mach_arm_4T:      expected = "armv4t"; break;
328    case bfd_mach_arm_5:       expected = "armv5"; break;
329    case bfd_mach_arm_5T:      expected = "armv5t"; break;
330    case bfd_mach_arm_5TE:     expected = "armv5te"; break;
331    case bfd_mach_arm_XScale:  expected = "XScale"; break;
332    case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
333    case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
334    }
335
336  if (strcmp (arch_string, expected) != 0)
337    {
338      strcpy (buffer + offsetof (arm_Note, name) + ((strlen (NOTE_ARCH_STRING) + 3) & ~3), expected);
339
340      if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
341				      (file_ptr) 0, buffer_size))
342	{
343	  (*_bfd_error_handler)
344	    (_("warning: unable to update contents of %s section in %s"),
345	     note_section, bfd_get_filename (abfd));
346	  goto FAIL;
347	}
348    }
349
350  free (buffer);
351  return TRUE;
352
353 FAIL:
354  free (buffer);
355  return FALSE;
356}
357
358
359static struct
360{
361  const char * string;
362  unsigned int mach;
363}
364architectures[] =
365{
366  { "armv2",   bfd_mach_arm_2 },
367  { "armv2a",  bfd_mach_arm_2a },
368  { "armv3",   bfd_mach_arm_3 },
369  { "armv3M",  bfd_mach_arm_3M },
370  { "armv4",   bfd_mach_arm_4 },
371  { "armv4t",  bfd_mach_arm_4T },
372  { "armv5",   bfd_mach_arm_5 },
373  { "armv5t",  bfd_mach_arm_5T },
374  { "armv5te", bfd_mach_arm_5TE },
375  { "XScale",  bfd_mach_arm_XScale },
376  { "ep9312",  bfd_mach_arm_ep9312 },
377  { "iWMMXt",  bfd_mach_arm_iWMMXt }
378};
379
380/* Extract the machine number stored in a note section.  */
381unsigned int
382bfd_arm_get_mach_from_notes (abfd, note_section)
383     bfd * abfd;
384     const char * note_section;
385{
386  asection *     arm_arch_section;
387  bfd_size_type  buffer_size;
388  char *         buffer;
389  char *         arch_string;
390  int            i;
391
392  /* Look for a note section.  If one is present check the architecture
393     string encoded in it, and set it to the current architecture if it is
394     different.  */
395  arm_arch_section = bfd_get_section_by_name (abfd, note_section);
396
397  if (arm_arch_section == NULL)
398    return bfd_mach_arm_unknown;
399
400  buffer_size = arm_arch_section->_raw_size;
401  if (buffer_size == 0)
402    return bfd_mach_arm_unknown;
403
404  buffer = bfd_malloc (buffer_size);
405  if (buffer == NULL)
406    return bfd_mach_arm_unknown;
407
408  if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
409				  (file_ptr) 0, buffer_size))
410    goto FAIL;
411
412  /* Parse the note.  */
413  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
414    goto FAIL;
415
416  /* Interpret the architecture string.  */
417  for (i = ARRAY_SIZE (architectures); i--;)
418    if (strcmp (arch_string, architectures[i].string) == 0)
419      {
420	free (buffer);
421	return architectures[i].mach;
422      }
423
424 FAIL:
425  free (buffer);
426  return bfd_mach_arm_unknown;
427}
428