OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [bfd/] [cpu-arm.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.