Index: bfd/cpu-i386.c |
diff --git a/bfd/cpu-i386.c b/bfd/cpu-i386.c |
index f98c0e50529a74432ee797db0e9c4e11939310b3..4cb59ed8981527ac94896d8054184c97bf96f9ad 100644 |
--- a/bfd/cpu-i386.c |
+++ b/bfd/cpu-i386.c |
@@ -23,6 +23,10 @@ |
#include "sysdep.h" |
#include "bfd.h" |
#include "libbfd.h" |
+#include "libiberty.h" |
+ |
+extern void * bfd_arch_i386_short_nop_fill (bfd_size_type, bfd_boolean, |
+ bfd_boolean); |
static const bfd_arch_info_type * |
bfd_i386_compatible (const bfd_arch_info_type *a, |
@@ -38,6 +42,83 @@ bfd_i386_compatible (const bfd_arch_info_type *a, |
return compat; |
} |
+/* Fill the buffer with zero or nop instruction if CODE is TRUE. Use |
+ multi byte nop instructions if LONG_NOP is TRUE. */ |
+ |
+static void * |
+bfd_arch_i386_fill (bfd_size_type count, bfd_boolean code, |
+ bfd_boolean long_nop) |
+{ |
+ /* nop */ |
+ static const char nop_1[] = { 0x90 }; |
+ /* xchg %ax,%ax */ |
+ static const char nop_2[] = { 0x66, 0x90 }; |
+ /* nopl (%[re]ax) */ |
+ static const char nop_3[] = { 0x0f, 0x1f, 0x00 }; |
+ /* nopl 0(%[re]ax) */ |
+ static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 }; |
+ /* nopl 0(%[re]ax,%[re]ax,1) */ |
+ static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 }; |
+ /* nopw 0(%[re]ax,%[re]ax,1) */ |
+ static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 }; |
+ /* nopl 0L(%[re]ax) */ |
+ static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 }; |
+ /* nopl 0L(%[re]ax,%[re]ax,1) */ |
+ static const char nop_8[] = |
+ { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}; |
+ /* nopw 0L(%[re]ax,%[re]ax,1) */ |
+ static const char nop_9[] = |
+ { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
+ /* nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
+ static const char nop_10[] = |
+ { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
+ static const char *const nops[] = |
+ { nop_1, nop_2, nop_3, nop_4, nop_5, |
+ nop_6, nop_7, nop_8, nop_9, nop_10 }; |
+ bfd_size_type nop_size = long_nop ? ARRAY_SIZE (nops) : 2; |
+ |
+ void *fill = bfd_malloc (count); |
+ if (fill == NULL) |
+ return fill; |
+ |
+ if (code) |
+ { |
+ bfd_byte *p = fill; |
+ while (count >= nop_size) |
+ { |
+ memcpy (p, nops[nop_size - 1], nop_size); |
+ p += nop_size; |
+ count -= nop_size; |
+ } |
+ if (count != 0) |
+ memcpy (p, nops[count - 1], count); |
+ } |
+ else |
+ memset (fill, 0, count); |
+ |
+ return fill; |
+} |
+ |
+/* Fill the buffer with zero or short nop instruction if CODE is TRUE. */ |
+ |
+void * |
+bfd_arch_i386_short_nop_fill (bfd_size_type count, |
+ bfd_boolean is_bigendian ATTRIBUTE_UNUSED, |
+ bfd_boolean code) |
+{ |
+ return bfd_arch_i386_fill (count, code, FALSE); |
+} |
+ |
+/* Fill the buffer with zero or long nop instruction if CODE is TRUE. */ |
+ |
+static void * |
+bfd_arch_i386_long_nop_fill (bfd_size_type count, |
+ bfd_boolean is_bigendian ATTRIBUTE_UNUSED, |
+ bfd_boolean code) |
+{ |
+ return bfd_arch_i386_fill (count, code, TRUE); |
+} |
+ |
static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax = |
{ |
64, /* 64 bits in a word */ |
@@ -51,6 +132,7 @@ static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax = |
FALSE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_long_nop_fill, |
0 |
}; |
@@ -67,6 +149,7 @@ static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax = |
FALSE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_long_nop_fill, |
&bfd_x64_32_arch_intel_syntax, |
}; |
@@ -83,6 +166,7 @@ static const bfd_arch_info_type bfd_i386_arch_intel_syntax = |
TRUE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_short_nop_fill, |
&bfd_x86_64_arch_intel_syntax |
}; |
@@ -99,6 +183,7 @@ static const bfd_arch_info_type i8086_arch = |
FALSE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_short_nop_fill, |
&bfd_i386_arch_intel_syntax |
}; |
@@ -115,6 +200,7 @@ static const bfd_arch_info_type bfd_x64_32_arch = |
FALSE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_long_nop_fill, |
&i8086_arch |
}; |
@@ -131,6 +217,7 @@ static const bfd_arch_info_type bfd_x86_64_arch = |
FALSE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_long_nop_fill, |
&bfd_x64_32_arch |
}; |
@@ -147,5 +234,6 @@ const bfd_arch_info_type bfd_i386_arch = |
TRUE, |
bfd_i386_compatible, |
bfd_default_scan, |
+ bfd_arch_i386_short_nop_fill, |
&bfd_x86_64_arch |
}; |