[PATCH] use only one-byte nops for linker code fill on x86 NaCl targets

Roland McGrath mcgrathr@google.com
Mon Aug 26 21:59:00 GMT 2013


For x86 NaCl, no instruction may straddle a 32-byte alignment boundary.
Since the bfd_arch_info_type.fill hook doesn't know the address where
the fill will go (and hence its alignment), the only safe thing it can
do is use only the one-byte nop instruction in the fill.

I found it distressing that creating a whole new CPU variant appears
to be the only way to make the function for code fill target-specific,
but the notion of the variants and their names does not appear to have
any other actual effect.

OK for trunk?


Thanks,
Roland
-------------- next part --------------
bfd/
2013-08-26  Roland McGrath  <mcgrathr@google.com>

	* archures.c (bfd_mach_i386_nacl, bfd_mach_i386_i386_nacl): New macros.
	(bfd_mach_x86_64_nacl, bfd_mach_x64_32_nacl): New macros.
	* cpu-i386.c (bfd_arch_i386_onebyte_nop_fill): New function.
	(bfd_i386_nacl_arch): New variable.
	(bfd_x86_64_nacl_arch, bfd_x64_32_nacl_arch): New variables.
	(bfd_x64_32_arch_intel_syntax): Link them into the list.
	* bfd-in2.h: Regenerate.

ld/
2013-08-26  Roland McGrath  <mcgrathr@google.com>

	* emulparams/elf_i386_nacl.sh (ARCH): Set to i386:nacl.
	* emulparams/elf_x86_64_nacl.sh (ARCH): Set to i386:x86-64:nacl.
	* emulparams/elf32_x86_64_nacl.sh (ARCH): Set to i386:x64-32:nacl.

ld/testsuite/
2013-08-26  Roland McGrath  <mcgrathr@google.com>

	* ld-x86-64/x86-64.exp (Mixed x86_64 and i386 input test 1):
	Loosen string match to admit i386:x86-64*.
	(Mixed x86_64 and i386 input test 2): Likewise.
	* ld-x86-64/ilp32-2.d: Likewise.
	* ld-x86-64/ilp32-3.d: Likewise.
	* ld-x86-64/lp64-2.d: Likewise.
	* ld-x86-64/lp64-3.d: Likewise.
	* ld-x86-64/ia32-2.d: Likewise, and i386.* too.
	* ld-x86-64/ia32-3.d: Likewise.

--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -190,9 +190,13 @@ DESCRIPTION
 .#define bfd_mach_i386_i386		(1 << 2)
 .#define bfd_mach_x86_64		(1 << 3)
 .#define bfd_mach_x64_32		(1 << 4)
+.#define bfd_mach_i386_nacl		(1 << 5)
 .#define bfd_mach_i386_i386_intel_syntax (bfd_mach_i386_i386 | bfd_mach_i386_intel_syntax)
 .#define bfd_mach_x86_64_intel_syntax	(bfd_mach_x86_64 | bfd_mach_i386_intel_syntax)
 .#define bfd_mach_x64_32_intel_syntax	(bfd_mach_x64_32 | bfd_mach_i386_intel_syntax)
+.#define bfd_mach_i386_i386_nacl	(bfd_mach_i386_i386 | bfd_mach_i386_nacl)
+.#define bfd_mach_x86_64_nacl		(bfd_mach_x86_64 | bfd_mach_i386_nacl)
+.#define bfd_mach_x64_32_nacl		(bfd_mach_x64_32 | bfd_mach_i386_nacl)
 .  bfd_arch_l1om,   {* Intel L1OM *}
 .#define bfd_mach_l1om			(1 << 5)
 .#define bfd_mach_l1om_intel_syntax	(bfd_mach_l1om | bfd_mach_i386_intel_syntax)
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1919,9 +1919,13 @@ enum bfd_architecture
 #define bfd_mach_i386_i386             (1 << 2)
 #define bfd_mach_x86_64                (1 << 3)
 #define bfd_mach_x64_32                (1 << 4)
+#define bfd_mach_i386_nacl             (1 << 5)
 #define bfd_mach_i386_i386_intel_syntax (bfd_mach_i386_i386 | bfd_mach_i386_intel_syntax)
 #define bfd_mach_x86_64_intel_syntax   (bfd_mach_x86_64 | bfd_mach_i386_intel_syntax)
 #define bfd_mach_x64_32_intel_syntax   (bfd_mach_x64_32 | bfd_mach_i386_intel_syntax)
+#define bfd_mach_i386_i386_nacl        (bfd_mach_i386_i386 | bfd_mach_i386_nacl)
+#define bfd_mach_x86_64_nacl           (bfd_mach_x86_64 | bfd_mach_i386_nacl)
+#define bfd_mach_x64_32_nacl           (bfd_mach_x64_32 | bfd_mach_i386_nacl)
   bfd_arch_l1om,   /* Intel L1OM */
 #define bfd_mach_l1om                  (1 << 5)
 #define bfd_mach_l1om_intel_syntax     (bfd_mach_l1om | bfd_mach_i386_intel_syntax)
--- a/bfd/cpu-i386.c
+++ b/bfd/cpu-i386.c
@@ -1,6 +1,6 @@
 /* BFD support for the Intel 386 architecture.
    Copyright 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2004, 2005,
-   2007, 2009, 2010, 2011
+   2007, 2009, 2010, 2011, 2013
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -119,6 +119,71 @@ bfd_arch_i386_long_nop_fill (bfd_size_type count,
   return bfd_arch_i386_fill (count, code, TRUE);
 }
 
+/* Fill the buffer with zero, or one-byte nop instructions if CODE is TRUE.  */
+
+static void *
+bfd_arch_i386_onebyte_nop_fill (bfd_size_type count,
+				bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
+				bfd_boolean code)
+{
+  void *fill = bfd_malloc (count);
+  if (fill != NULL)
+    memset (fill, code ? 0x90 : 0, count);
+  return fill;
+}
+
+
+static const bfd_arch_info_type bfd_x64_32_nacl_arch =
+{
+  64, /* 64 bits in a word */
+  64, /* 64 bits in an address */
+  8,  /* 8 bits in a byte */
+  bfd_arch_i386,
+  bfd_mach_x64_32_nacl,
+  "i386",
+  "i386:x64-32:nacl",
+  3,
+  FALSE,
+  bfd_i386_compatible,
+  bfd_default_scan,
+  bfd_arch_i386_onebyte_nop_fill,
+  NULL
+};
+
+static const bfd_arch_info_type bfd_x86_64_nacl_arch =
+{
+  64, /* 64 bits in a word */
+  64, /* 64 bits in an address */
+  8,  /* 8 bits in a byte */
+  bfd_arch_i386,
+  bfd_mach_x86_64_nacl,
+  "i386",
+  "i386:x86-64:nacl",
+  3,
+  FALSE,
+  bfd_i386_compatible,
+  bfd_default_scan,
+  bfd_arch_i386_onebyte_nop_fill,
+  &bfd_x64_32_nacl_arch
+};
+
+const bfd_arch_info_type bfd_i386_nacl_arch =
+{
+  32,	/* 32 bits in a word */
+  32,	/* 32 bits in an address */
+  8,	/* 8 bits in a byte */
+  bfd_arch_i386,
+  bfd_mach_i386_i386_nacl,
+  "i386",
+  "i386:nacl",
+  3,
+  TRUE,
+  bfd_i386_compatible,
+  bfd_default_scan,
+  bfd_arch_i386_onebyte_nop_fill,
+  &bfd_x86_64_nacl_arch
+};
+
 static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
 {
   64, /* 64 bits in a word */
@@ -133,7 +198,7 @@ static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
   bfd_i386_compatible,
   bfd_default_scan,
   bfd_arch_i386_long_nop_fill,
-  0
+  &bfd_i386_nacl_arch
 };
 
 static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax =
--- a/ld/emulparams/elf32_x86_64_nacl.sh
+++ b/ld/emulparams/elf32_x86_64_nacl.sh
@@ -1,3 +1,4 @@
 . ${srcdir}/emulparams/elf32_x86_64.sh
 . ${srcdir}/emulparams/elf_nacl.sh
 OUTPUT_FORMAT="elf32-x86-64-nacl"
+ARCH="i386:x64-32:nacl"	# The :nacl just means one-byte nops for code fill.
--- a/ld/emulparams/elf_i386_nacl.sh
+++ b/ld/emulparams/elf_i386_nacl.sh
@@ -1,3 +1,4 @@
 . ${srcdir}/emulparams/elf_i386.sh
 . ${srcdir}/emulparams/elf_nacl.sh
 OUTPUT_FORMAT="elf32-i386-nacl"
+ARCH="i386:nacl"	# The :nacl just means one-byte nops for code fill.
--- a/ld/emulparams/elf_x86_64_nacl.sh
+++ b/ld/emulparams/elf_x86_64_nacl.sh
@@ -1,3 +1,4 @@
 . ${srcdir}/emulparams/elf_x86_64.sh
 . ${srcdir}/emulparams/elf_nacl.sh
 OUTPUT_FORMAT="elf64-x86-64-nacl"
+ARCH="i386:x86-64:nacl"	# The :nacl just means one-byte nops for code fill.
--- a/ld/testsuite/ld-x86-64/ia32-2.d
+++ b/ld/testsuite/ld-x86-64/ia32-2.d
@@ -1,4 +1,4 @@
 #source: dummy.s
 #as: --32
 #ld: -m elf_i386 tmpdir/start32.o tmpdir/foox32.o
-#error: .*i386:x64-32 architecture of input file `tmpdir/foox32.o' is incompatible with i386 output
+#error: .*i386:x64-32.* architecture of input file `tmpdir/foox32.o' is incompatible with i386.* output
--- a/ld/testsuite/ld-x86-64/ia32-3.d
+++ b/ld/testsuite/ld-x86-64/ia32-3.d
@@ -1,4 +1,4 @@
 #source: dummy.s
 #as: --32
 #ld: -m elf_i386 tmpdir/start32.o tmpdir/foo64.o
-#error: .*i386:x86-64 architecture of input file `tmpdir/foo64.o' is incompatible with i386 output
+#error: .*i386:x86-64.* architecture of input file `tmpdir/foo64.o' is incompatible with i386.* output
--- a/ld/testsuite/ld-x86-64/ilp32-2.d
+++ b/ld/testsuite/ld-x86-64/ilp32-2.d
@@ -1,4 +1,4 @@
 #source: dummy.s
 #as: --x32
 #ld: -m elf32_x86_64 tmpdir/startx32.o tmpdir/foo32.o
-#error: .*i386 architecture of input file `tmpdir/foo32.o' is incompatible with i386:x64-32 output
+#error: .*i386 architecture of input file `tmpdir/foo32.o' is incompatible with i386:x64-32.* output
--- a/ld/testsuite/ld-x86-64/ilp32-3.d
+++ b/ld/testsuite/ld-x86-64/ilp32-3.d
@@ -1,4 +1,4 @@
 #source: dummy.s
 #as: --x32
 #ld: -m elf32_x86_64 tmpdir/startx32.o tmpdir/foo64.o
-#error: .*i386:x86-64 architecture of input file `tmpdir/foo64.o' is incompatible with i386:x64-32 output
+#error: .*i386:x86-64 architecture of input file `tmpdir/foo64.o' is incompatible with i386:x64-32.* output
--- a/ld/testsuite/ld-x86-64/lp64-2.d
+++ b/ld/testsuite/ld-x86-64/lp64-2.d
@@ -1,4 +1,4 @@
 #source: dummy.s
 #as: --64
 #ld: -m elf_x86_64 tmpdir/start64.o tmpdir/foo32.o
-#error: .*i386 architecture of input file `tmpdir/foo32.o' is incompatible with i386:x86-64 output
+#error: .*i386 architecture of input file `tmpdir/foo32.o' is incompatible with i386:x86-64.* output
--- a/ld/testsuite/ld-x86-64/lp64-3.d
+++ b/ld/testsuite/ld-x86-64/lp64-3.d
@@ -1,4 +1,4 @@
 #source: dummy.s
 #as: --64
 #ld: -m elf_x86_64 tmpdir/start64.o tmpdir/foox32.o
-#error: .*i386:x64-32 architecture of input file `tmpdir/foox32.o' is incompatible with i386:x86-64 output
+#error: .*i386:x64-32 architecture of input file `tmpdir/foox32.o' is incompatible with i386:x86-64.* output
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1,5 +1,5 @@
 # Expect script for ld-x86_64 tests
-#   Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+#   Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
 #   Free Software Foundation
 #
 # This file is part of the GNU Binutils.
@@ -162,7 +162,7 @@ global ld
 set test_name "Mixed x86_64 and i386 input test 1"
 set test mixed1
 if { ![ld_simple_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}b.o"] } {
-    if [string match "*i386 architecture of input file `tmpdir/${test}b.o' is incompatible with i386:x86-64 output*" $link_output] {
+    if [string match "*i386 architecture of input file `tmpdir/${test}b.o' is incompatible with i386:x86-64* output*" $link_output] {
 	pass "$test_name"
     } {
 	fail "$test_name"
@@ -172,7 +172,7 @@ if { ![ld_simple_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}
 set test_name "Mixed x86_64 and i386 input test 2"
 set test mixed2
 if { ![ld_simple_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}b.o"] } {
-    if [string match "*i386 architecture of input file `tmpdir/${test}b.o' is incompatible with i386:x86-64 output*" $link_output] {
+    if [string match "*i386 architecture of input file `tmpdir/${test}b.o' is incompatible with i386:x86-64* output*" $link_output] {
 	pass "$test_name"
     } {
 	fail "$test_name"


More information about the Binutils mailing list