Subversion Repositories Kolibri OS

Rev

Rev 5197 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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