00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "libiberty.h"
00030
00031
00032
00033
00034
00035 static const bfd_arch_info_type *
00036 compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
00037 {
00038
00039 if (a->arch != b->arch)
00040 return NULL;
00041
00042
00043 if (a->mach == b->mach)
00044 return a;
00045
00046
00047
00048 if (a->the_default)
00049 return b;
00050
00051 if (b->the_default)
00052 return a;
00053
00054
00055
00056 if (a->mach < b->mach)
00057 return b;
00058 else if (a->mach > b->mach)
00059 return a;
00060
00061
00062 return NULL;
00063 }
00064
00065 static struct
00066 {
00067 unsigned int mach;
00068 char * name;
00069 }
00070 processors[] =
00071 {
00072 { bfd_mach_arm_2, "arm2" },
00073 { bfd_mach_arm_2a, "arm250" },
00074 { bfd_mach_arm_2a, "arm3" },
00075 { bfd_mach_arm_3, "arm6" },
00076 { bfd_mach_arm_3, "arm60" },
00077 { bfd_mach_arm_3, "arm600" },
00078 { bfd_mach_arm_3, "arm610" },
00079 { bfd_mach_arm_3, "arm7" },
00080 { bfd_mach_arm_3, "arm710" },
00081 { bfd_mach_arm_3, "arm7500" },
00082 { bfd_mach_arm_3, "arm7d" },
00083 { bfd_mach_arm_3, "arm7di" },
00084 { bfd_mach_arm_3M, "arm7dm" },
00085 { bfd_mach_arm_3M, "arm7dmi" },
00086 { bfd_mach_arm_4T, "arm7tdmi" },
00087 { bfd_mach_arm_4, "arm8" },
00088 { bfd_mach_arm_4, "arm810" },
00089 { bfd_mach_arm_4, "arm9" },
00090 { bfd_mach_arm_4, "arm920" },
00091 { bfd_mach_arm_4T, "arm920t" },
00092 { bfd_mach_arm_4T, "arm9tdmi" },
00093 { bfd_mach_arm_4, "sa1" },
00094 { bfd_mach_arm_4, "strongarm"},
00095 { bfd_mach_arm_4, "strongarm110" },
00096 { bfd_mach_arm_4, "strongarm1100" },
00097 { bfd_mach_arm_XScale, "xscale" },
00098 { bfd_mach_arm_ep9312, "ep9312" },
00099 { bfd_mach_arm_iWMMXt, "iwmmxt" }
00100 };
00101
00102 static bfd_boolean
00103 scan (const struct bfd_arch_info *info, const char *string)
00104 {
00105 int i;
00106
00107
00108 if (strcasecmp (string, info->printable_name) == 0)
00109 return TRUE;
00110
00111
00112 for (i = sizeof (processors) / sizeof (processors[0]); i--;)
00113 {
00114 if (strcasecmp (string, processors [i].name) == 0)
00115 break;
00116 }
00117
00118 if (i != -1 && info->mach == processors [i].mach)
00119 return TRUE;
00120
00121
00122 if (strcasecmp (string, "arm") == 0)
00123 return info->the_default;
00124
00125 return FALSE;
00126 }
00127
00128 #define N(number, print, default, next) \
00129 { 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }
00130
00131 static const bfd_arch_info_type arch_info_struct[] =
00132 {
00133 N (bfd_mach_arm_2, "armv2", FALSE, & arch_info_struct[1]),
00134 N (bfd_mach_arm_2a, "armv2a", FALSE, & arch_info_struct[2]),
00135 N (bfd_mach_arm_3, "armv3", FALSE, & arch_info_struct[3]),
00136 N (bfd_mach_arm_3M, "armv3m", FALSE, & arch_info_struct[4]),
00137 N (bfd_mach_arm_4, "armv4", FALSE, & arch_info_struct[5]),
00138 N (bfd_mach_arm_4T, "armv4t", FALSE, & arch_info_struct[6]),
00139 N (bfd_mach_arm_5, "armv5", FALSE, & arch_info_struct[7]),
00140 N (bfd_mach_arm_5T, "armv5t", FALSE, & arch_info_struct[8]),
00141 N (bfd_mach_arm_5TE, "armv5te", FALSE, & arch_info_struct[9]),
00142 N (bfd_mach_arm_XScale, "xscale", FALSE, & arch_info_struct[10]),
00143 N (bfd_mach_arm_ep9312, "ep9312", FALSE, & arch_info_struct[11]),
00144 N (bfd_mach_arm_iWMMXt,"iwmmxt", FALSE, NULL)
00145 };
00146
00147 const bfd_arch_info_type bfd_arm_arch =
00148 N (0, "arm", TRUE, & arch_info_struct[0]);
00149
00150
00151
00152
00153
00154
00155
00156
00157 bfd_boolean
00158 bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
00159 {
00160 unsigned int in = bfd_get_mach (ibfd);
00161 unsigned int out = bfd_get_mach (obfd);
00162
00163
00164 if (out == bfd_mach_arm_unknown)
00165 bfd_set_arch_mach (obfd, bfd_arch_arm, in);
00166
00167
00168
00169 else if (in == bfd_mach_arm_unknown)
00170
00171
00172 bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
00173
00174
00175 else if (out == in)
00176 ;
00177
00178
00179
00180
00181
00182
00183
00184
00185 else if (in == bfd_mach_arm_ep9312
00186 && (out == bfd_mach_arm_XScale || out == bfd_mach_arm_iWMMXt))
00187 {
00188 _bfd_error_handler (_("\
00189 ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
00190 ibfd, obfd);
00191 bfd_set_error (bfd_error_wrong_format);
00192 return FALSE;
00193 }
00194 else if (out == bfd_mach_arm_ep9312
00195 && (in == bfd_mach_arm_XScale || in == bfd_mach_arm_iWMMXt))
00196 {
00197 _bfd_error_handler (_("\
00198 ERROR: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
00199 obfd, ibfd);
00200 bfd_set_error (bfd_error_wrong_format);
00201 return FALSE;
00202 }
00203 else if (in > out)
00204 bfd_set_arch_mach (obfd, bfd_arch_arm, in);
00205
00206
00207
00208 return TRUE;
00209 }
00210
00211 typedef struct
00212 {
00213 unsigned char namesz[4];
00214 unsigned char descsz[4];
00215 unsigned char type[4];
00216 char name[1];
00217 } arm_Note;
00218
00219 static bfd_boolean
00220 arm_check_note (bfd *abfd,
00221 bfd_byte *buffer,
00222 bfd_size_type buffer_size,
00223 const char *expected_name,
00224 char **description_return)
00225 {
00226 unsigned long namesz;
00227 unsigned long descsz;
00228 unsigned long type;
00229 char * descr;
00230
00231 if (buffer_size < offsetof (arm_Note, name))
00232 return FALSE;
00233
00234
00235
00236 namesz = bfd_get_32 (abfd, buffer);
00237 descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
00238 type = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
00239 descr = (char *) buffer + offsetof (arm_Note, name);
00240
00241
00242 if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
00243 return FALSE;
00244
00245 if (expected_name == NULL)
00246 {
00247 if (namesz != 0)
00248 return FALSE;
00249 }
00250 else
00251 {
00252 if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
00253 return FALSE;
00254
00255 if (strcmp (descr, expected_name) != 0)
00256 return FALSE;
00257
00258 descr += (namesz + 3) & ~3;
00259 }
00260
00261
00262
00263 if (description_return != NULL)
00264 * description_return = descr;
00265
00266 return TRUE;
00267 }
00268
00269 #define NOTE_ARCH_STRING "arch: "
00270
00271 bfd_boolean
00272 bfd_arm_update_notes (bfd *abfd, const char *note_section)
00273 {
00274 asection * arm_arch_section;
00275 bfd_size_type buffer_size;
00276 bfd_byte * buffer;
00277 char * arch_string;
00278 char * expected;
00279
00280
00281
00282
00283 arm_arch_section = bfd_get_section_by_name (abfd, note_section);
00284
00285 if (arm_arch_section == NULL)
00286 return TRUE;
00287
00288 buffer_size = arm_arch_section->size;
00289 if (buffer_size == 0)
00290 return FALSE;
00291
00292 if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
00293 goto FAIL;
00294
00295
00296 if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
00297 goto FAIL;
00298
00299
00300 switch (bfd_get_mach (abfd))
00301 {
00302 default:
00303 case bfd_mach_arm_unknown: expected = "unknown"; break;
00304 case bfd_mach_arm_2: expected = "armv2"; break;
00305 case bfd_mach_arm_2a: expected = "armv2a"; break;
00306 case bfd_mach_arm_3: expected = "armv3"; break;
00307 case bfd_mach_arm_3M: expected = "armv3M"; break;
00308 case bfd_mach_arm_4: expected = "armv4"; break;
00309 case bfd_mach_arm_4T: expected = "armv4t"; break;
00310 case bfd_mach_arm_5: expected = "armv5"; break;
00311 case bfd_mach_arm_5T: expected = "armv5t"; break;
00312 case bfd_mach_arm_5TE: expected = "armv5te"; break;
00313 case bfd_mach_arm_XScale: expected = "XScale"; break;
00314 case bfd_mach_arm_ep9312: expected = "ep9312"; break;
00315 case bfd_mach_arm_iWMMXt: expected = "iWMMXt"; break;
00316 }
00317
00318 if (strcmp (arch_string, expected) != 0)
00319 {
00320 strcpy ((char *) buffer + (offsetof (arm_Note, name)
00321 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
00322 expected);
00323
00324 if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
00325 (file_ptr) 0, buffer_size))
00326 {
00327 (*_bfd_error_handler)
00328 (_("warning: unable to update contents of %s section in %s"),
00329 note_section, bfd_get_filename (abfd));
00330 goto FAIL;
00331 }
00332 }
00333
00334 free (buffer);
00335 return TRUE;
00336
00337 FAIL:
00338 if (buffer != NULL)
00339 free (buffer);
00340 return FALSE;
00341 }
00342
00343
00344 static struct
00345 {
00346 const char * string;
00347 unsigned int mach;
00348 }
00349 architectures[] =
00350 {
00351 { "armv2", bfd_mach_arm_2 },
00352 { "armv2a", bfd_mach_arm_2a },
00353 { "armv3", bfd_mach_arm_3 },
00354 { "armv3M", bfd_mach_arm_3M },
00355 { "armv4", bfd_mach_arm_4 },
00356 { "armv4t", bfd_mach_arm_4T },
00357 { "armv5", bfd_mach_arm_5 },
00358 { "armv5t", bfd_mach_arm_5T },
00359 { "armv5te", bfd_mach_arm_5TE },
00360 { "XScale", bfd_mach_arm_XScale },
00361 { "ep9312", bfd_mach_arm_ep9312 },
00362 { "iWMMXt", bfd_mach_arm_iWMMXt }
00363 };
00364
00365
00366 unsigned int
00367 bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
00368 {
00369 asection * arm_arch_section;
00370 bfd_size_type buffer_size;
00371 bfd_byte * buffer;
00372 char * arch_string;
00373 int i;
00374
00375
00376
00377
00378 arm_arch_section = bfd_get_section_by_name (abfd, note_section);
00379
00380 if (arm_arch_section == NULL)
00381 return bfd_mach_arm_unknown;
00382
00383 buffer_size = arm_arch_section->size;
00384 if (buffer_size == 0)
00385 return bfd_mach_arm_unknown;
00386
00387 if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
00388 goto FAIL;
00389
00390
00391 if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
00392 goto FAIL;
00393
00394
00395 for (i = ARRAY_SIZE (architectures); i--;)
00396 if (strcmp (arch_string, architectures[i].string) == 0)
00397 {
00398 free (buffer);
00399 return architectures[i].mach;
00400 }
00401
00402 FAIL:
00403 if (buffer != NULL)
00404 free (buffer);
00405 return bfd_mach_arm_unknown;
00406 }