1 1.1 christos /* BFD support for the ARM processor 2 1.11 christos Copyright (C) 1994-2024 Free Software Foundation, Inc. 3 1.1 christos Contributed by Richard Earnshaw (rwe (at) pegasus.esprit.ec.org) 4 1.1 christos 5 1.1 christos This file is part of BFD, the Binary File Descriptor library. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program; if not, write to the Free Software 19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 1.1 christos MA 02110-1301, USA. */ 21 1.1 christos 22 1.1 christos #include "sysdep.h" 23 1.1 christos #include "bfd.h" 24 1.1 christos #include "libbfd.h" 25 1.1 christos #include "libiberty.h" 26 1.9 christos #include "cpu-arm.h" 27 1.1 christos 28 1.1 christos /* This routine is provided two arch_infos and works out which ARM 29 1.1 christos machine which would be compatible with both and returns a pointer 30 1.1 christos to its info structure. */ 31 1.1 christos 32 1.1 christos static const bfd_arch_info_type * 33 1.1 christos compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) 34 1.1 christos { 35 1.1 christos /* If a & b are for different architecture we can do nothing. */ 36 1.1 christos if (a->arch != b->arch) 37 1.1 christos return NULL; 38 1.1 christos 39 1.1 christos /* If a & b are for the same machine then all is well. */ 40 1.1 christos if (a->mach == b->mach) 41 1.1 christos return a; 42 1.1 christos 43 1.1 christos /* Otherwise if either a or b is the 'default' machine 44 1.1 christos then it can be polymorphed into the other. */ 45 1.1 christos if (a->the_default) 46 1.1 christos return b; 47 1.1 christos 48 1.1 christos if (b->the_default) 49 1.1 christos return a; 50 1.1 christos 51 1.1 christos /* So far all newer ARM architecture cores are 52 1.1 christos supersets of previous cores. */ 53 1.1 christos if (a->mach < b->mach) 54 1.1 christos return b; 55 1.1 christos else if (a->mach > b->mach) 56 1.1 christos return a; 57 1.1 christos 58 1.1 christos /* Never reached! */ 59 1.1 christos return NULL; 60 1.1 christos } 61 1.1 christos 62 1.1 christos static struct 63 1.1 christos { 64 1.1 christos unsigned int mach; 65 1.1 christos char * name; 66 1.1 christos } 67 1.1 christos processors[] = 68 1.1 christos { 69 1.8 christos { bfd_mach_arm_2, "arm2" }, 70 1.8 christos { bfd_mach_arm_2a, "arm250" }, 71 1.8 christos { bfd_mach_arm_2a, "arm3" }, 72 1.8 christos { bfd_mach_arm_3, "arm6" }, 73 1.8 christos { bfd_mach_arm_3, "arm60" }, 74 1.8 christos { bfd_mach_arm_3, "arm600" }, 75 1.8 christos { bfd_mach_arm_3, "arm610" }, 76 1.8 christos { bfd_mach_arm_3, "arm620" }, 77 1.8 christos { bfd_mach_arm_3, "arm7" }, 78 1.8 christos { bfd_mach_arm_3, "arm70" }, 79 1.8 christos { bfd_mach_arm_3, "arm700" }, 80 1.8 christos { bfd_mach_arm_3, "arm700i" }, 81 1.8 christos { bfd_mach_arm_3, "arm710" }, 82 1.8 christos { bfd_mach_arm_3, "arm7100" }, 83 1.8 christos { bfd_mach_arm_3, "arm710c" }, 84 1.8 christos { bfd_mach_arm_4T, "arm710t" }, 85 1.8 christos { bfd_mach_arm_3, "arm720" }, 86 1.8 christos { bfd_mach_arm_4T, "arm720t" }, 87 1.8 christos { bfd_mach_arm_4T, "arm740t" }, 88 1.8 christos { bfd_mach_arm_3, "arm7500" }, 89 1.8 christos { bfd_mach_arm_3, "arm7500fe" }, 90 1.8 christos { bfd_mach_arm_3, "arm7d" }, 91 1.8 christos { bfd_mach_arm_3, "arm7di" }, 92 1.8 christos { bfd_mach_arm_3M, "arm7dm" }, 93 1.8 christos { bfd_mach_arm_3M, "arm7dmi" }, 94 1.8 christos { bfd_mach_arm_4T, "arm7t" }, 95 1.8 christos { bfd_mach_arm_4T, "arm7tdmi" }, 96 1.8 christos { bfd_mach_arm_4T, "arm7tdmi-s" }, 97 1.8 christos { bfd_mach_arm_3M, "arm7m" }, 98 1.8 christos { bfd_mach_arm_4, "arm8" }, 99 1.8 christos { bfd_mach_arm_4, "arm810" }, 100 1.8 christos { bfd_mach_arm_4, "arm9" }, 101 1.8 christos { bfd_mach_arm_4T, "arm920" }, 102 1.8 christos { bfd_mach_arm_4T, "arm920t" }, 103 1.8 christos { bfd_mach_arm_4T, "arm922t" }, 104 1.8 christos { bfd_mach_arm_5TEJ, "arm926ej" }, 105 1.8 christos { bfd_mach_arm_5TEJ, "arm926ejs" }, 106 1.8 christos { bfd_mach_arm_5TEJ, "arm926ej-s" }, 107 1.8 christos { bfd_mach_arm_4T, "arm940t" }, 108 1.8 christos { bfd_mach_arm_5TE, "arm946e" }, 109 1.8 christos { bfd_mach_arm_5TE, "arm946e-r0" }, 110 1.8 christos { bfd_mach_arm_5TE, "arm946e-s" }, 111 1.8 christos { bfd_mach_arm_5TE, "arm966e" }, 112 1.8 christos { bfd_mach_arm_5TE, "arm966e-r0" }, 113 1.8 christos { bfd_mach_arm_5TE, "arm966e-s" }, 114 1.8 christos { bfd_mach_arm_5TE, "arm968e-s" }, 115 1.8 christos { bfd_mach_arm_5TE, "arm9e" }, 116 1.8 christos { bfd_mach_arm_5TE, "arm9e-r0" }, 117 1.8 christos { bfd_mach_arm_4T, "arm9tdmi" }, 118 1.8 christos { bfd_mach_arm_5TE, "arm1020" }, 119 1.8 christos { bfd_mach_arm_5T, "arm1020t" }, 120 1.8 christos { bfd_mach_arm_5TE, "arm1020e" }, 121 1.8 christos { bfd_mach_arm_5TE, "arm1022e" }, 122 1.8 christos { bfd_mach_arm_5TEJ, "arm1026ejs" }, 123 1.8 christos { bfd_mach_arm_5TEJ, "arm1026ej-s" }, 124 1.8 christos { bfd_mach_arm_5TE, "arm10e" }, 125 1.8 christos { bfd_mach_arm_5T, "arm10t" }, 126 1.8 christos { bfd_mach_arm_5T, "arm10tdmi" }, 127 1.8 christos { bfd_mach_arm_6, "arm1136j-s" }, 128 1.8 christos { bfd_mach_arm_6, "arm1136js" }, 129 1.8 christos { bfd_mach_arm_6, "arm1136jf-s" }, 130 1.8 christos { bfd_mach_arm_6, "arm1136jfs" }, 131 1.8 christos { bfd_mach_arm_6KZ, "arm1176jz-s" }, 132 1.8 christos { bfd_mach_arm_6KZ, "arm1176jzf-s" }, 133 1.8 christos { bfd_mach_arm_6T2, "arm1156t2-s" }, 134 1.8 christos { bfd_mach_arm_6T2, "arm1156t2f-s" }, 135 1.8 christos { bfd_mach_arm_7, "cortex-a5" }, 136 1.8 christos { bfd_mach_arm_7, "cortex-a7" }, 137 1.8 christos { bfd_mach_arm_7, "cortex-a8" }, 138 1.8 christos { bfd_mach_arm_7, "cortex-a9" }, 139 1.8 christos { bfd_mach_arm_7, "cortex-a12" }, 140 1.8 christos { bfd_mach_arm_7, "cortex-a15" }, 141 1.8 christos { bfd_mach_arm_7, "cortex-a17" }, 142 1.8 christos { bfd_mach_arm_8, "cortex-a32" }, 143 1.8 christos { bfd_mach_arm_8, "cortex-a35" }, 144 1.8 christos { bfd_mach_arm_8, "cortex-a53" }, 145 1.8 christos { bfd_mach_arm_8, "cortex-a55" }, 146 1.8 christos { bfd_mach_arm_8, "cortex-a57" }, 147 1.8 christos { bfd_mach_arm_8, "cortex-a72" }, 148 1.8 christos { bfd_mach_arm_8, "cortex-a73" }, 149 1.8 christos { bfd_mach_arm_8, "cortex-a75" }, 150 1.8 christos { bfd_mach_arm_8, "cortex-a76" }, 151 1.9 christos { bfd_mach_arm_8, "cortex-a76ae" }, 152 1.9 christos { bfd_mach_arm_8, "cortex-a77" }, 153 1.10 christos { bfd_mach_arm_8, "cortex-a78" }, 154 1.10 christos { bfd_mach_arm_8, "cortex-a78ae" }, 155 1.10 christos { bfd_mach_arm_8, "cortex-a78c" }, 156 1.8 christos { bfd_mach_arm_6SM, "cortex-m0" }, 157 1.8 christos { bfd_mach_arm_6SM, "cortex-m0plus" }, 158 1.8 christos { bfd_mach_arm_6SM, "cortex-m1" }, 159 1.8 christos { bfd_mach_arm_8M_BASE, "cortex-m23" }, 160 1.8 christos { bfd_mach_arm_7, "cortex-m3" }, 161 1.8 christos { bfd_mach_arm_8M_MAIN, "cortex-m33" }, 162 1.9 christos { bfd_mach_arm_8M_MAIN, "cortex-m35p" }, 163 1.8 christos { bfd_mach_arm_7EM, "cortex-m4" }, 164 1.8 christos { bfd_mach_arm_7EM, "cortex-m7" }, 165 1.8 christos { bfd_mach_arm_7, "cortex-r4" }, 166 1.8 christos { bfd_mach_arm_7, "cortex-r4f" }, 167 1.8 christos { bfd_mach_arm_7, "cortex-r5" }, 168 1.8 christos { bfd_mach_arm_8R, "cortex-r52" }, 169 1.10 christos { bfd_mach_arm_8R, "cortex-r52plus" }, 170 1.8 christos { bfd_mach_arm_7, "cortex-r7" }, 171 1.8 christos { bfd_mach_arm_7, "cortex-r8" }, 172 1.10 christos { bfd_mach_arm_8, "cortex-x1" }, 173 1.10 christos { bfd_mach_arm_8, "cortex-x1c" }, 174 1.8 christos { bfd_mach_arm_4T, "ep9312" }, 175 1.8 christos { bfd_mach_arm_8, "exynos-m1" }, 176 1.8 christos { bfd_mach_arm_4, "fa526" }, 177 1.8 christos { bfd_mach_arm_5TE, "fa606te" }, 178 1.8 christos { bfd_mach_arm_5TE, "fa616te" }, 179 1.8 christos { bfd_mach_arm_4, "fa626" }, 180 1.8 christos { bfd_mach_arm_5TE, "fa626te" }, 181 1.8 christos { bfd_mach_arm_5TE, "fa726te" }, 182 1.8 christos { bfd_mach_arm_5TE, "fmp626" }, 183 1.8 christos { bfd_mach_arm_XScale, "i80200" }, 184 1.8 christos { bfd_mach_arm_7, "marvell-pj4" }, 185 1.8 christos { bfd_mach_arm_7, "marvell-whitney" }, 186 1.8 christos { bfd_mach_arm_6K, "mpcore" }, 187 1.8 christos { bfd_mach_arm_6K, "mpcorenovfp" }, 188 1.8 christos { bfd_mach_arm_4, "sa1" }, 189 1.8 christos { bfd_mach_arm_4, "strongarm" }, 190 1.8 christos { bfd_mach_arm_4, "strongarm1" }, 191 1.8 christos { bfd_mach_arm_4, "strongarm110" }, 192 1.8 christos { bfd_mach_arm_4, "strongarm1100" }, 193 1.8 christos { bfd_mach_arm_4, "strongarm1110" }, 194 1.8 christos { bfd_mach_arm_XScale, "xscale" }, 195 1.8 christos { bfd_mach_arm_8, "xgene1" }, 196 1.8 christos { bfd_mach_arm_8, "xgene2" }, 197 1.10 christos { bfd_mach_arm_9, "cortex-a710" }, 198 1.8 christos { bfd_mach_arm_iWMMXt, "iwmmxt" }, 199 1.8 christos { bfd_mach_arm_iWMMXt2, "iwmmxt2" }, 200 1.8 christos { bfd_mach_arm_unknown, "arm_any" } 201 1.1 christos }; 202 1.1 christos 203 1.10 christos static bool 204 1.1 christos scan (const struct bfd_arch_info *info, const char *string) 205 1.1 christos { 206 1.1 christos int i; 207 1.1 christos 208 1.1 christos /* First test for an exact match. */ 209 1.1 christos if (strcasecmp (string, info->printable_name) == 0) 210 1.10 christos return true; 211 1.10 christos 212 1.10 christos /* If there is a prefix of "arm:" then skip it. */ 213 1.10 christos const char * colon; 214 1.10 christos if ((colon = strchr (string, ':')) != NULL) 215 1.10 christos { 216 1.10 christos if (strncasecmp (string, "arm", colon - string) != 0) 217 1.10 christos return false; 218 1.10 christos string = colon + 1; 219 1.10 christos } 220 1.1 christos 221 1.1 christos /* Next check for a processor name instead of an Architecture name. */ 222 1.1 christos for (i = sizeof (processors) / sizeof (processors[0]); i--;) 223 1.1 christos { 224 1.1 christos if (strcasecmp (string, processors [i].name) == 0) 225 1.1 christos break; 226 1.1 christos } 227 1.1 christos 228 1.1 christos if (i != -1 && info->mach == processors [i].mach) 229 1.10 christos return true; 230 1.1 christos 231 1.1 christos /* Finally check for the default architecture. */ 232 1.1 christos if (strcasecmp (string, "arm") == 0) 233 1.1 christos return info->the_default; 234 1.1 christos 235 1.10 christos return false; 236 1.1 christos } 237 1.1 christos 238 1.1 christos #define N(number, print, default, next) \ 239 1.1 christos { 32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \ 240 1.9 christos scan, bfd_arch_default_fill, next, 0 } 241 1.1 christos 242 1.1 christos static const bfd_arch_info_type arch_info_struct[] = 243 1.1 christos { 244 1.10 christos N (bfd_mach_arm_2, "armv2", false, & arch_info_struct[1]), 245 1.10 christos N (bfd_mach_arm_2a, "armv2a", false, & arch_info_struct[2]), 246 1.10 christos N (bfd_mach_arm_3, "armv3", false, & arch_info_struct[3]), 247 1.10 christos N (bfd_mach_arm_3M, "armv3m", false, & arch_info_struct[4]), 248 1.10 christos N (bfd_mach_arm_4, "armv4", false, & arch_info_struct[5]), 249 1.10 christos N (bfd_mach_arm_4T, "armv4t", false, & arch_info_struct[6]), 250 1.10 christos N (bfd_mach_arm_5, "armv5", false, & arch_info_struct[7]), 251 1.10 christos N (bfd_mach_arm_5T, "armv5t", false, & arch_info_struct[8]), 252 1.10 christos N (bfd_mach_arm_5TE, "armv5te", false, & arch_info_struct[9]), 253 1.10 christos N (bfd_mach_arm_XScale, "xscale", false, & arch_info_struct[10]), 254 1.11 christos N (bfd_mach_arm_iWMMXt, "iwmmxt", false, & arch_info_struct[11]), 255 1.11 christos N (bfd_mach_arm_iWMMXt2, "iwmmxt2", false, & arch_info_struct[12]), 256 1.11 christos N (bfd_mach_arm_5TEJ, "armv5tej", false, & arch_info_struct[13]), 257 1.11 christos N (bfd_mach_arm_6, "armv6", false, & arch_info_struct[14]), 258 1.11 christos N (bfd_mach_arm_6KZ, "armv6kz", false, & arch_info_struct[15]), 259 1.11 christos N (bfd_mach_arm_6T2, "armv6t2", false, & arch_info_struct[16]), 260 1.11 christos N (bfd_mach_arm_6K, "armv6k", false, & arch_info_struct[17]), 261 1.11 christos N (bfd_mach_arm_7, "armv7", false, & arch_info_struct[18]), 262 1.11 christos N (bfd_mach_arm_6M, "armv6-m", false, & arch_info_struct[19]), 263 1.11 christos N (bfd_mach_arm_6SM, "armv6s-m", false, & arch_info_struct[20]), 264 1.11 christos N (bfd_mach_arm_7EM, "armv7e-m", false, & arch_info_struct[21]), 265 1.11 christos N (bfd_mach_arm_8, "armv8-a", false, & arch_info_struct[22]), 266 1.11 christos N (bfd_mach_arm_8R, "armv8-r", false, & arch_info_struct[23]), 267 1.11 christos N (bfd_mach_arm_8M_BASE, "armv8-m.base", false, & arch_info_struct[24]), 268 1.11 christos N (bfd_mach_arm_8M_MAIN, "armv8-m.main", false, & arch_info_struct[25]), 269 1.11 christos N (bfd_mach_arm_8_1M_MAIN, "armv8.1-m.main", false, & arch_info_struct[26]), 270 1.11 christos N (bfd_mach_arm_9, "armv9-a", false, & arch_info_struct[27]), 271 1.10 christos N (bfd_mach_arm_unknown, "arm_any", false, NULL) 272 1.1 christos }; 273 1.1 christos 274 1.1 christos const bfd_arch_info_type bfd_arm_arch = 275 1.10 christos N (0, "arm", true, & arch_info_struct[0]); 276 1.1 christos 277 1.1 christos /* Support functions used by both the COFF and ELF versions of the ARM port. */ 278 1.1 christos 279 1.1 christos /* Handle the merging of the 'machine' settings of input file IBFD 280 1.1 christos and an output file OBFD. These values actually represent the 281 1.1 christos different possible ARM architecture variants. 282 1.1 christos Returns TRUE if they were merged successfully or FALSE otherwise. */ 283 1.1 christos 284 1.10 christos bool 285 1.1 christos bfd_arm_merge_machines (bfd *ibfd, bfd *obfd) 286 1.1 christos { 287 1.1 christos unsigned int in = bfd_get_mach (ibfd); 288 1.1 christos unsigned int out = bfd_get_mach (obfd); 289 1.1 christos 290 1.1 christos /* If the output architecture is unknown, we now have a value to set. */ 291 1.1 christos if (out == bfd_mach_arm_unknown) 292 1.1 christos bfd_set_arch_mach (obfd, bfd_arch_arm, in); 293 1.1 christos 294 1.1 christos /* If the input architecture is unknown, 295 1.1 christos then so must be the output architecture. */ 296 1.1 christos else if (in == bfd_mach_arm_unknown) 297 1.1 christos /* FIXME: We ought to have some way to 298 1.1 christos override this on the command line. */ 299 1.1 christos bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown); 300 1.1 christos 301 1.1 christos /* If they are the same then nothing needs to be done. */ 302 1.1 christos else if (out == in) 303 1.1 christos ; 304 1.1 christos 305 1.1 christos /* Otherwise the general principle that a earlier architecture can be 306 1.1 christos linked with a later architecture to produce a binary that will execute 307 1.11 christos on the later architecture. */ 308 1.1 christos else if (in > out) 309 1.1 christos bfd_set_arch_mach (obfd, bfd_arch_arm, in); 310 1.1 christos /* else 311 1.1 christos Nothing to do. */ 312 1.1 christos 313 1.10 christos return true; 314 1.1 christos } 315 1.1 christos 316 1.1 christos typedef struct 317 1.1 christos { 318 1.1 christos unsigned char namesz[4]; /* Size of entry's owner string. */ 319 1.1 christos unsigned char descsz[4]; /* Size of the note descriptor. */ 320 1.1 christos unsigned char type[4]; /* Interpretation of the descriptor. */ 321 1.1 christos char name[1]; /* Start of the name+desc data. */ 322 1.1 christos } arm_Note; 323 1.1 christos 324 1.10 christos static bool 325 1.1 christos arm_check_note (bfd *abfd, 326 1.1 christos bfd_byte *buffer, 327 1.1 christos bfd_size_type buffer_size, 328 1.1 christos const char *expected_name, 329 1.1 christos char **description_return) 330 1.1 christos { 331 1.1 christos unsigned long namesz; 332 1.1 christos unsigned long descsz; 333 1.1 christos unsigned long type; 334 1.8 christos char * descr; 335 1.1 christos 336 1.1 christos if (buffer_size < offsetof (arm_Note, name)) 337 1.10 christos return false; 338 1.1 christos 339 1.1 christos /* We have to extract the values this way to allow for a 340 1.1 christos host whose endian-ness is different from the target. */ 341 1.1 christos namesz = bfd_get_32 (abfd, buffer); 342 1.1 christos descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz)); 343 1.1 christos type = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type)); 344 1.1 christos descr = (char *) buffer + offsetof (arm_Note, name); 345 1.1 christos 346 1.1 christos /* Check for buffer overflow. */ 347 1.1 christos if (namesz + descsz + offsetof (arm_Note, name) > buffer_size) 348 1.10 christos return false; 349 1.1 christos 350 1.1 christos if (expected_name == NULL) 351 1.1 christos { 352 1.1 christos if (namesz != 0) 353 1.10 christos return false; 354 1.1 christos } 355 1.1 christos else 356 1.1 christos { 357 1.1 christos if (namesz != ((strlen (expected_name) + 1 + 3) & ~3)) 358 1.10 christos return false; 359 1.1 christos 360 1.1 christos if (strcmp (descr, expected_name) != 0) 361 1.10 christos return false; 362 1.1 christos 363 1.1 christos descr += (namesz + 3) & ~3; 364 1.1 christos } 365 1.1 christos 366 1.1 christos /* FIXME: We should probably check the type as well. */ 367 1.1 christos (void) type; 368 1.1 christos 369 1.1 christos if (description_return != NULL) 370 1.1 christos * description_return = descr; 371 1.1 christos 372 1.10 christos return true; 373 1.1 christos } 374 1.1 christos 375 1.8 christos #define NOTE_ARCH_STRING "arch: " 376 1.1 christos 377 1.10 christos bool 378 1.1 christos bfd_arm_update_notes (bfd *abfd, const char *note_section) 379 1.1 christos { 380 1.8 christos asection * arm_arch_section; 381 1.8 christos bfd_size_type buffer_size; 382 1.8 christos bfd_byte * buffer; 383 1.8 christos char * arch_string; 384 1.8 christos char * expected; 385 1.1 christos 386 1.1 christos /* Look for a note section. If one is present check the architecture 387 1.1 christos string encoded in it, and set it to the current architecture if it is 388 1.1 christos different. */ 389 1.1 christos arm_arch_section = bfd_get_section_by_name (abfd, note_section); 390 1.1 christos 391 1.11 christos if (arm_arch_section == NULL 392 1.11 christos || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0) 393 1.10 christos return true; 394 1.1 christos 395 1.1 christos buffer_size = arm_arch_section->size; 396 1.1 christos if (buffer_size == 0) 397 1.10 christos return false; 398 1.1 christos 399 1.1 christos if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer)) 400 1.1 christos goto FAIL; 401 1.1 christos 402 1.1 christos /* Parse the note. */ 403 1.1 christos if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string)) 404 1.1 christos goto FAIL; 405 1.1 christos 406 1.8 christos /* Check the architecture in the note against the architecture of the bfd. 407 1.8 christos Newer architectures versions should not be added here as build attribute 408 1.8 christos are a better mechanism to convey ISA used. */ 409 1.1 christos switch (bfd_get_mach (abfd)) 410 1.1 christos { 411 1.1 christos default: 412 1.1 christos case bfd_mach_arm_unknown: expected = "unknown"; break; 413 1.1 christos case bfd_mach_arm_2: expected = "armv2"; break; 414 1.1 christos case bfd_mach_arm_2a: expected = "armv2a"; break; 415 1.1 christos case bfd_mach_arm_3: expected = "armv3"; break; 416 1.1 christos case bfd_mach_arm_3M: expected = "armv3M"; break; 417 1.1 christos case bfd_mach_arm_4: expected = "armv4"; break; 418 1.1 christos case bfd_mach_arm_4T: expected = "armv4t"; break; 419 1.1 christos case bfd_mach_arm_5: expected = "armv5"; break; 420 1.1 christos case bfd_mach_arm_5T: expected = "armv5t"; break; 421 1.1 christos case bfd_mach_arm_5TE: expected = "armv5te"; break; 422 1.1 christos case bfd_mach_arm_XScale: expected = "XScale"; break; 423 1.1 christos case bfd_mach_arm_iWMMXt: expected = "iWMMXt"; break; 424 1.1 christos case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break; 425 1.1 christos } 426 1.1 christos 427 1.1 christos if (strcmp (arch_string, expected) != 0) 428 1.1 christos { 429 1.1 christos strcpy ((char *) buffer + (offsetof (arm_Note, name) 430 1.1 christos + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)), 431 1.1 christos expected); 432 1.1 christos 433 1.1 christos if (! bfd_set_section_contents (abfd, arm_arch_section, buffer, 434 1.1 christos (file_ptr) 0, buffer_size)) 435 1.1 christos { 436 1.7 christos _bfd_error_handler 437 1.7 christos /* xgettext: c-format */ 438 1.8 christos (_("warning: unable to update contents of %s section in %pB"), 439 1.7 christos note_section, abfd); 440 1.1 christos goto FAIL; 441 1.1 christos } 442 1.1 christos } 443 1.1 christos 444 1.1 christos free (buffer); 445 1.10 christos return true; 446 1.1 christos 447 1.1 christos FAIL: 448 1.9 christos free (buffer); 449 1.10 christos return false; 450 1.1 christos } 451 1.1 christos 452 1.1 christos 453 1.1 christos static struct 454 1.1 christos { 455 1.1 christos const char * string; 456 1.1 christos unsigned int mach; 457 1.1 christos } 458 1.8 christos 459 1.8 christos /* Newer architectures versions should not be added here as build attribute are 460 1.8 christos a better mechanism to convey ISA used. */ 461 1.1 christos architectures[] = 462 1.1 christos { 463 1.1 christos { "armv2", bfd_mach_arm_2 }, 464 1.1 christos { "armv2a", bfd_mach_arm_2a }, 465 1.1 christos { "armv3", bfd_mach_arm_3 }, 466 1.1 christos { "armv3M", bfd_mach_arm_3M }, 467 1.1 christos { "armv4", bfd_mach_arm_4 }, 468 1.1 christos { "armv4t", bfd_mach_arm_4T }, 469 1.1 christos { "armv5", bfd_mach_arm_5 }, 470 1.1 christos { "armv5t", bfd_mach_arm_5T }, 471 1.1 christos { "armv5te", bfd_mach_arm_5TE }, 472 1.1 christos { "XScale", bfd_mach_arm_XScale }, 473 1.11 christos /* Maverick extensions have been dropped, so treat this as Armv4T. */ 474 1.11 christos { "ep9312", bfd_mach_arm_4T }, 475 1.1 christos { "iWMMXt", bfd_mach_arm_iWMMXt }, 476 1.6 christos { "iWMMXt2", bfd_mach_arm_iWMMXt2 }, 477 1.6 christos { "arm_any", bfd_mach_arm_unknown } 478 1.1 christos }; 479 1.1 christos 480 1.1 christos /* Extract the machine number stored in a note section. */ 481 1.1 christos unsigned int 482 1.1 christos bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section) 483 1.1 christos { 484 1.8 christos asection * arm_arch_section; 485 1.8 christos bfd_size_type buffer_size; 486 1.8 christos bfd_byte * buffer; 487 1.8 christos char * arch_string; 488 1.8 christos int i; 489 1.1 christos 490 1.1 christos /* Look for a note section. If one is present check the architecture 491 1.1 christos string encoded in it, and set it to the current architecture if it is 492 1.1 christos different. */ 493 1.1 christos arm_arch_section = bfd_get_section_by_name (abfd, note_section); 494 1.1 christos 495 1.11 christos if (arm_arch_section == NULL 496 1.11 christos || (arm_arch_section->flags & SEC_HAS_CONTENTS) == 0) 497 1.1 christos return bfd_mach_arm_unknown; 498 1.1 christos 499 1.1 christos buffer_size = arm_arch_section->size; 500 1.1 christos if (buffer_size == 0) 501 1.1 christos return bfd_mach_arm_unknown; 502 1.1 christos 503 1.1 christos if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer)) 504 1.1 christos goto FAIL; 505 1.1 christos 506 1.1 christos /* Parse the note. */ 507 1.1 christos if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string)) 508 1.1 christos goto FAIL; 509 1.1 christos 510 1.1 christos /* Interpret the architecture string. */ 511 1.1 christos for (i = ARRAY_SIZE (architectures); i--;) 512 1.1 christos if (strcmp (arch_string, architectures[i].string) == 0) 513 1.1 christos { 514 1.1 christos free (buffer); 515 1.1 christos return architectures[i].mach; 516 1.1 christos } 517 1.1 christos 518 1.1 christos FAIL: 519 1.9 christos free (buffer); 520 1.1 christos return bfd_mach_arm_unknown; 521 1.1 christos } 522 1.1 christos 523 1.10 christos bool 524 1.1 christos bfd_is_arm_special_symbol_name (const char * name, int type) 525 1.1 christos { 526 1.1 christos /* The ARM compiler outputs several obsolete forms. Recognize them 527 1.1 christos in addition to the standard $a, $t and $d. We are somewhat loose 528 1.1 christos in what we accept here, since the full set is not documented. */ 529 1.1 christos if (!name || name[0] != '$') 530 1.10 christos return false; 531 1.1 christos if (name[1] == 'a' || name[1] == 't' || name[1] == 'd') 532 1.1 christos type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP; 533 1.1 christos else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p') 534 1.1 christos type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG; 535 1.1 christos else if (name[1] >= 'a' && name[1] <= 'z') 536 1.1 christos type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER; 537 1.1 christos else 538 1.10 christos return false; 539 1.1 christos 540 1.1 christos return (type != 0 && (name[2] == 0 || name[2] == '.')); 541 1.1 christos } 542 1.1 christos 543