cpu-i386.c revision 1.1
1/* BFD support for the Intel 386 architecture. 2 Copyright 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2004, 2005, 3 2007, 2009, 2010, 2011, 2013 4 Free Software Foundation, Inc. 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 28extern void * bfd_arch_i386_short_nop_fill (bfd_size_type, bfd_boolean, 29 bfd_boolean); 30 31static const bfd_arch_info_type * 32bfd_i386_compatible (const bfd_arch_info_type *a, 33 const bfd_arch_info_type *b) 34{ 35 const bfd_arch_info_type *compat = bfd_default_compatible (a, b); 36 37 /* Don't allow mixing x64_32 with x86_64. */ 38 if (compat 39 && (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32)) 40 compat = NULL; 41 42 return compat; 43} 44 45/* Fill the buffer with zero or nop instruction if CODE is TRUE. Use 46 multi byte nop instructions if LONG_NOP is TRUE. */ 47 48static void * 49bfd_arch_i386_fill (bfd_size_type count, bfd_boolean code, 50 bfd_boolean long_nop) 51{ 52 /* nop */ 53 static const char nop_1[] = { 0x90 }; 54 /* xchg %ax,%ax */ 55 static const char nop_2[] = { 0x66, 0x90 }; 56 /* nopl (%[re]ax) */ 57 static const char nop_3[] = { 0x0f, 0x1f, 0x00 }; 58 /* nopl 0(%[re]ax) */ 59 static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 }; 60 /* nopl 0(%[re]ax,%[re]ax,1) */ 61 static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 }; 62 /* nopw 0(%[re]ax,%[re]ax,1) */ 63 static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 }; 64 /* nopl 0L(%[re]ax) */ 65 static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 }; 66 /* nopl 0L(%[re]ax,%[re]ax,1) */ 67 static const char nop_8[] = 68 { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}; 69 /* nopw 0L(%[re]ax,%[re]ax,1) */ 70 static const char nop_9[] = 71 { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; 72 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */ 73 static const char nop_10[] = 74 { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; 75 static const char *const nops[] = 76 { nop_1, nop_2, nop_3, nop_4, nop_5, 77 nop_6, nop_7, nop_8, nop_9, nop_10 }; 78 bfd_size_type nop_size = long_nop ? ARRAY_SIZE (nops) : 2; 79 80 void *fill = bfd_malloc (count); 81 if (fill == NULL) 82 return fill; 83 84 if (code) 85 { 86 bfd_byte *p = fill; 87 while (count >= nop_size) 88 { 89 memcpy (p, nops[nop_size - 1], nop_size); 90 p += nop_size; 91 count -= nop_size; 92 } 93 if (count != 0) 94 memcpy (p, nops[count - 1], count); 95 } 96 else 97 memset (fill, 0, count); 98 99 return fill; 100} 101 102/* Fill the buffer with zero or short nop instruction if CODE is TRUE. */ 103 104void * 105bfd_arch_i386_short_nop_fill (bfd_size_type count, 106 bfd_boolean is_bigendian ATTRIBUTE_UNUSED, 107 bfd_boolean code) 108{ 109 return bfd_arch_i386_fill (count, code, FALSE); 110} 111 112/* Fill the buffer with zero or long nop instruction if CODE is TRUE. */ 113 114static void * 115bfd_arch_i386_long_nop_fill (bfd_size_type count, 116 bfd_boolean is_bigendian ATTRIBUTE_UNUSED, 117 bfd_boolean code) 118{ 119 return bfd_arch_i386_fill (count, code, TRUE); 120} 121 122/* Fill the buffer with zero, or one-byte nop instructions if CODE is TRUE. */ 123 124static void * 125bfd_arch_i386_onebyte_nop_fill (bfd_size_type count, 126 bfd_boolean is_bigendian ATTRIBUTE_UNUSED, 127 bfd_boolean code) 128{ 129 void *fill = bfd_malloc (count); 130 if (fill != NULL) 131 memset (fill, code ? 0x90 : 0, count); 132 return fill; 133} 134 135 136static const bfd_arch_info_type bfd_x64_32_nacl_arch = 137{ 138 64, /* 64 bits in a word */ 139 64, /* 64 bits in an address */ 140 8, /* 8 bits in a byte */ 141 bfd_arch_i386, 142 bfd_mach_x64_32_nacl, 143 "i386", 144 "i386:x64-32:nacl", 145 3, 146 FALSE, 147 bfd_i386_compatible, 148 bfd_default_scan, 149 bfd_arch_i386_onebyte_nop_fill, 150 NULL 151}; 152 153static const bfd_arch_info_type bfd_x86_64_nacl_arch = 154{ 155 64, /* 64 bits in a word */ 156 64, /* 64 bits in an address */ 157 8, /* 8 bits in a byte */ 158 bfd_arch_i386, 159 bfd_mach_x86_64_nacl, 160 "i386", 161 "i386:x86-64:nacl", 162 3, 163 FALSE, 164 bfd_i386_compatible, 165 bfd_default_scan, 166 bfd_arch_i386_onebyte_nop_fill, 167 &bfd_x64_32_nacl_arch 168}; 169 170const bfd_arch_info_type bfd_i386_nacl_arch = 171{ 172 32, /* 32 bits in a word */ 173 32, /* 32 bits in an address */ 174 8, /* 8 bits in a byte */ 175 bfd_arch_i386, 176 bfd_mach_i386_i386_nacl, 177 "i386", 178 "i386:nacl", 179 3, 180 TRUE, 181 bfd_i386_compatible, 182 bfd_default_scan, 183 bfd_arch_i386_onebyte_nop_fill, 184 &bfd_x86_64_nacl_arch 185}; 186 187static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax = 188{ 189 64, /* 64 bits in a word */ 190 64, /* 64 bits in an address */ 191 8, /* 8 bits in a byte */ 192 bfd_arch_i386, 193 bfd_mach_x64_32_intel_syntax, 194 "i386:intel", 195 "i386:x64-32:intel", 196 3, 197 FALSE, 198 bfd_i386_compatible, 199 bfd_default_scan, 200 bfd_arch_i386_long_nop_fill, 201 &bfd_i386_nacl_arch 202}; 203 204static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax = 205{ 206 64, /* 64 bits in a word */ 207 64, /* 64 bits in an address */ 208 8, /* 8 bits in a byte */ 209 bfd_arch_i386, 210 bfd_mach_x86_64_intel_syntax, 211 "i386:intel", 212 "i386:x86-64:intel", 213 3, 214 FALSE, 215 bfd_i386_compatible, 216 bfd_default_scan, 217 bfd_arch_i386_long_nop_fill, 218 &bfd_x64_32_arch_intel_syntax, 219}; 220 221static const bfd_arch_info_type bfd_i386_arch_intel_syntax = 222{ 223 32, /* 32 bits in a word */ 224 32, /* 32 bits in an address */ 225 8, /* 8 bits in a byte */ 226 bfd_arch_i386, 227 bfd_mach_i386_i386_intel_syntax, 228 "i386:intel", 229 "i386:intel", 230 3, 231 TRUE, 232 bfd_i386_compatible, 233 bfd_default_scan, 234 bfd_arch_i386_short_nop_fill, 235 &bfd_x86_64_arch_intel_syntax 236}; 237 238static const bfd_arch_info_type i8086_arch = 239{ 240 32, /* 32 bits in a word */ 241 32, /* 32 bits in an address (well, not really) */ 242 8, /* 8 bits in a byte */ 243 bfd_arch_i386, 244 bfd_mach_i386_i8086, 245 "i8086", 246 "i8086", 247 3, 248 FALSE, 249 bfd_i386_compatible, 250 bfd_default_scan, 251 bfd_arch_i386_short_nop_fill, 252 &bfd_i386_arch_intel_syntax 253}; 254 255static const bfd_arch_info_type bfd_x64_32_arch = 256{ 257 64, /* 64 bits in a word */ 258 64, /* 64 bits in an address */ 259 8, /* 8 bits in a byte */ 260 bfd_arch_i386, 261 bfd_mach_x64_32, 262 "i386", 263 "i386:x64-32", 264 3, 265 FALSE, 266 bfd_i386_compatible, 267 bfd_default_scan, 268 bfd_arch_i386_long_nop_fill, 269 &i8086_arch 270}; 271 272static const bfd_arch_info_type bfd_x86_64_arch = 273{ 274 64, /* 64 bits in a word */ 275 64, /* 64 bits in an address */ 276 8, /* 8 bits in a byte */ 277 bfd_arch_i386, 278 bfd_mach_x86_64, 279 "i386", 280 "i386:x86-64", 281 3, 282 FALSE, 283 bfd_i386_compatible, 284 bfd_default_scan, 285 bfd_arch_i386_long_nop_fill, 286 &bfd_x64_32_arch 287}; 288 289const bfd_arch_info_type bfd_i386_arch = 290{ 291 32, /* 32 bits in a word */ 292 32, /* 32 bits in an address */ 293 8, /* 8 bits in a byte */ 294 bfd_arch_i386, 295 bfd_mach_i386_i386, 296 "i386", 297 "i386", 298 3, 299 TRUE, 300 bfd_i386_compatible, 301 bfd_default_scan, 302 bfd_arch_i386_short_nop_fill, 303 &bfd_x86_64_arch 304}; 305