OSDN Git Service

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