cpu-i386.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /* BFD support for the Intel 386 architecture.
  2. Copyright (C) 1992-2015 Free Software Foundation, Inc.
  3. This file is part of BFD, the Binary File Descriptor library.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "bfd.h"
  18. #include "libbfd.h"
  19. #include "libiberty.h"
  20. extern void * bfd_arch_i386_short_nop_fill (bfd_size_type, bfd_boolean,
  21. bfd_boolean);
  22. static const bfd_arch_info_type *
  23. bfd_i386_compatible (const bfd_arch_info_type *a,
  24. const bfd_arch_info_type *b)
  25. {
  26. const bfd_arch_info_type *compat = bfd_default_compatible (a, b);
  27. /* Don't allow mixing x64_32 with x86_64. */
  28. if (compat
  29. && (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32))
  30. compat = NULL;
  31. return compat;
  32. }
  33. /* Fill the buffer with zero or nop instruction if CODE is TRUE. Use
  34. multi byte nop instructions if LONG_NOP is TRUE. */
  35. static void *
  36. bfd_arch_i386_fill (bfd_size_type count, bfd_boolean code,
  37. bfd_boolean long_nop)
  38. {
  39. /* nop */
  40. static const char nop_1[] = { 0x90 };
  41. /* xchg %ax,%ax */
  42. static const char nop_2[] = { 0x66, 0x90 };
  43. /* nopl (%[re]ax) */
  44. static const char nop_3[] = { 0x0f, 0x1f, 0x00 };
  45. /* nopl 0(%[re]ax) */
  46. static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 };
  47. /* nopl 0(%[re]ax,%[re]ax,1) */
  48. static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
  49. /* nopw 0(%[re]ax,%[re]ax,1) */
  50. static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
  51. /* nopl 0L(%[re]ax) */
  52. static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 };
  53. /* nopl 0L(%[re]ax,%[re]ax,1) */
  54. static const char nop_8[] =
  55. { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
  56. /* nopw 0L(%[re]ax,%[re]ax,1) */
  57. static const char nop_9[] =
  58. { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
  59. /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
  60. static const char nop_10[] =
  61. { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
  62. static const char *const nops[] =
  63. { nop_1, nop_2, nop_3, nop_4, nop_5,
  64. nop_6, nop_7, nop_8, nop_9, nop_10 };
  65. bfd_size_type nop_size = long_nop ? ARRAY_SIZE (nops) : 2;
  66. void *fill = bfd_malloc (count);
  67. if (fill == NULL)
  68. return fill;
  69. if (code)
  70. {
  71. bfd_byte *p = fill;
  72. while (count >= nop_size)
  73. {
  74. memcpy (p, nops[nop_size - 1], nop_size);
  75. p += nop_size;
  76. count -= nop_size;
  77. }
  78. if (count != 0)
  79. memcpy (p, nops[count - 1], count);
  80. }
  81. else
  82. memset (fill, 0, count);
  83. return fill;
  84. }
  85. /* Fill the buffer with zero or short nop instruction if CODE is TRUE. */
  86. void *
  87. bfd_arch_i386_short_nop_fill (bfd_size_type count,
  88. bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
  89. bfd_boolean code)
  90. {
  91. return bfd_arch_i386_fill (count, code, FALSE);
  92. }
  93. /* Fill the buffer with zero or long nop instruction if CODE is TRUE. */
  94. static void *
  95. bfd_arch_i386_long_nop_fill (bfd_size_type count,
  96. bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
  97. bfd_boolean code)
  98. {
  99. return bfd_arch_i386_fill (count, code, TRUE);
  100. }
  101. /* Fill the buffer with zero, or one-byte nop instructions if CODE is TRUE. */
  102. static void *
  103. bfd_arch_i386_onebyte_nop_fill (bfd_size_type count,
  104. bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
  105. bfd_boolean code)
  106. {
  107. void *fill = bfd_malloc (count);
  108. if (fill != NULL)
  109. memset (fill, code ? 0x90 : 0, count);
  110. return fill;
  111. }
  112. static const bfd_arch_info_type bfd_x64_32_nacl_arch =
  113. {
  114. 64, /* 64 bits in a word */
  115. 64, /* 64 bits in an address */
  116. 8, /* 8 bits in a byte */
  117. bfd_arch_i386,
  118. bfd_mach_x64_32_nacl,
  119. "i386",
  120. "i386:x64-32:nacl",
  121. 3,
  122. FALSE,
  123. bfd_i386_compatible,
  124. bfd_default_scan,
  125. bfd_arch_i386_onebyte_nop_fill,
  126. NULL
  127. };
  128. static const bfd_arch_info_type bfd_x86_64_nacl_arch =
  129. {
  130. 64, /* 64 bits in a word */
  131. 64, /* 64 bits in an address */
  132. 8, /* 8 bits in a byte */
  133. bfd_arch_i386,
  134. bfd_mach_x86_64_nacl,
  135. "i386",
  136. "i386:x86-64:nacl",
  137. 3,
  138. FALSE,
  139. bfd_i386_compatible,
  140. bfd_default_scan,
  141. bfd_arch_i386_onebyte_nop_fill,
  142. &bfd_x64_32_nacl_arch
  143. };
  144. const bfd_arch_info_type bfd_i386_nacl_arch =
  145. {
  146. 32, /* 32 bits in a word */
  147. 32, /* 32 bits in an address */
  148. 8, /* 8 bits in a byte */
  149. bfd_arch_i386,
  150. bfd_mach_i386_i386_nacl,
  151. "i386",
  152. "i386:nacl",
  153. 3,
  154. TRUE,
  155. bfd_i386_compatible,
  156. bfd_default_scan,
  157. bfd_arch_i386_onebyte_nop_fill,
  158. &bfd_x86_64_nacl_arch
  159. };
  160. static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
  161. {
  162. 64, /* 64 bits in a word */
  163. 64, /* 64 bits in an address */
  164. 8, /* 8 bits in a byte */
  165. bfd_arch_i386,
  166. bfd_mach_x64_32_intel_syntax,
  167. "i386:intel",
  168. "i386:x64-32:intel",
  169. 3,
  170. FALSE,
  171. bfd_i386_compatible,
  172. bfd_default_scan,
  173. bfd_arch_i386_long_nop_fill,
  174. &bfd_i386_nacl_arch
  175. };
  176. static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax =
  177. {
  178. 64, /* 64 bits in a word */
  179. 64, /* 64 bits in an address */
  180. 8, /* 8 bits in a byte */
  181. bfd_arch_i386,
  182. bfd_mach_x86_64_intel_syntax,
  183. "i386:intel",
  184. "i386:x86-64:intel",
  185. 3,
  186. FALSE,
  187. bfd_i386_compatible,
  188. bfd_default_scan,
  189. bfd_arch_i386_long_nop_fill,
  190. &bfd_x64_32_arch_intel_syntax,
  191. };
  192. static const bfd_arch_info_type bfd_i386_arch_intel_syntax =
  193. {
  194. 32, /* 32 bits in a word */
  195. 32, /* 32 bits in an address */
  196. 8, /* 8 bits in a byte */
  197. bfd_arch_i386,
  198. bfd_mach_i386_i386_intel_syntax,
  199. "i386:intel",
  200. "i386:intel",
  201. 3,
  202. TRUE,
  203. bfd_i386_compatible,
  204. bfd_default_scan,
  205. bfd_arch_i386_short_nop_fill,
  206. &bfd_x86_64_arch_intel_syntax
  207. };
  208. static const bfd_arch_info_type i8086_arch =
  209. {
  210. 32, /* 32 bits in a word */
  211. 32, /* 32 bits in an address (well, not really) */
  212. 8, /* 8 bits in a byte */
  213. bfd_arch_i386,
  214. bfd_mach_i386_i8086,
  215. "i8086",
  216. "i8086",
  217. 3,
  218. FALSE,
  219. bfd_i386_compatible,
  220. bfd_default_scan,
  221. bfd_arch_i386_short_nop_fill,
  222. &bfd_i386_arch_intel_syntax
  223. };
  224. static const bfd_arch_info_type bfd_x64_32_arch =
  225. {
  226. 64, /* 64 bits in a word */
  227. 64, /* 64 bits in an address */
  228. 8, /* 8 bits in a byte */
  229. bfd_arch_i386,
  230. bfd_mach_x64_32,
  231. "i386",
  232. "i386:x64-32",
  233. 3,
  234. FALSE,
  235. bfd_i386_compatible,
  236. bfd_default_scan,
  237. bfd_arch_i386_long_nop_fill,
  238. &i8086_arch
  239. };
  240. static const bfd_arch_info_type bfd_x86_64_arch =
  241. {
  242. 64, /* 64 bits in a word */
  243. 64, /* 64 bits in an address */
  244. 8, /* 8 bits in a byte */
  245. bfd_arch_i386,
  246. bfd_mach_x86_64,
  247. "i386",
  248. "i386:x86-64",
  249. 3,
  250. FALSE,
  251. bfd_i386_compatible,
  252. bfd_default_scan,
  253. bfd_arch_i386_long_nop_fill,
  254. &bfd_x64_32_arch
  255. };
  256. const bfd_arch_info_type bfd_i386_arch =
  257. {
  258. 32, /* 32 bits in a word */
  259. 32, /* 32 bits in an address */
  260. 8, /* 8 bits in a byte */
  261. bfd_arch_i386,
  262. bfd_mach_i386_i386,
  263. "i386",
  264. "i386",
  265. 3,
  266. TRUE,
  267. bfd_i386_compatible,
  268. bfd_default_scan,
  269. bfd_arch_i386_short_nop_fill,
  270. &bfd_x86_64_arch
  271. };