~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to bfd/cpu-arm.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
26
static const bfd_arch_info_type * compatible
 
27
  PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
 
28
static bfd_boolean scan
 
29
  PARAMS ((const struct bfd_arch_info *, const char *));
 
30
static 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
 
 
37
static const bfd_arch_info_type *
 
38
compatible (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
 
 
69
static struct
 
70
{
 
71
  unsigned int mach;
 
72
  char *       name;
 
73
}
 
74
processors[] =
 
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
 
 
106
static bfd_boolean
 
107
scan (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
 
 
137
static 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
 
 
153
const 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 mergeing 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
 
 
163
bfd_boolean
 
164
bfd_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 architecure 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 architecure 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 (_("\
 
197
ERROR: %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 (_("\
 
207
ERROR: %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
 
 
221
typedef 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
 
 
229
static bfd_boolean
 
230
arm_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
 
 
282
bfd_boolean
 
283
bfd_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
 
 
359
static struct
 
360
{
 
361
  const char * string;
 
362
  unsigned int mach;
 
363
}
 
364
architectures[] =
 
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.  */
 
381
unsigned int
 
382
bfd_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
}