This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: PR ld/12730: regression] crash when allocating in a static constructor


Hi,

When we put .ctors into .init_array, we have to reverse copy .ctors secton.
Otherwise, constructor function may not work with C++ run-time library
correctly.  OK for trunk?

Thanks.


H.J.
---
bfd/

2011-05-04  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12730
	* elflink.c (elf_link_input_bfd): Reverse copy .ctors section
	if needed.

include/

2011-05-04  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12730
	* bfdlink.h (bfd_link_info): Add reverse_copy_ctors.

ld/

2011-05-04  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12730
	* emultempl/elf32.em (gld${EMULATION_NAME}_after_parse): New.
	(ld_${EMULATION_NAME}_emulation): Replace after_parse_default
	with gld${EMULATION_NAME}_after_parse.

ld/testsuite/

2011-05-04  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12730
	* ld-elf/elf.exp (array_tests): Add pr12730".
	(array_tests_static): Add "static pr12730".

	* ld-elf/pr12730.cc: New.
	* ld-elf/pr12730.out: Likewise.

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 082355d..41aa16a 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9876,12 +9876,46 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
 	default:
 	  {
 	    /* FIXME: octets_per_byte.  */
-	    if (! (o->flags & SEC_EXCLUDE)
-		&& ! bfd_set_section_contents (output_bfd, o->output_section,
-					       contents,
-					       (file_ptr) o->output_offset,
-					       o->size))
-	      return FALSE;
+	    if (! (o->flags & SEC_EXCLUDE))
+	      {
+		bfd_size_type address_size = bed->s->arch_size / 8;
+		file_ptr offset = (file_ptr) o->output_offset;
+		bfd_size_type todo = o->size;
+		if (finfo->info->reverse_copy_ctors
+		    && todo > address_size
+		    && strcmp (o->name, ".ctors") == 0)
+		  {
+		    if ((o->size % address_size) != 0)
+		      {
+			(*_bfd_error_handler)
+			  (_("error: %B: size of section %A is not "
+			     "multiple of address size"),
+			   input_bfd, o);
+			bfd_set_error (bfd_error_on_input);
+			return FALSE;
+		      }
+
+		    do
+		      {
+			todo -= address_size;
+			if (! bfd_set_section_contents (output_bfd,
+							o->output_section,
+							contents + todo,
+							offset,
+							address_size))
+			  return FALSE;
+			if (todo == 0)
+			  break;
+			offset += address_size;
+		      }
+		    while (1);
+		  }
+		else if (! bfd_set_section_contents (output_bfd,
+						     o->output_section,
+						     contents,
+						     offset, todo))
+		  return FALSE;
+	      }
 	  }
 	  break;
 	}
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 50a1423..0139751 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -354,6 +354,9 @@ struct bfd_link_info
      --dynamic-list command line options.  */
   unsigned int dynamic: 1;
 
+  /* TRUE if BFD should reverse-copy .ctors section.  */
+  unsigned int reverse_copy_ctors: 1;
+
   /* Non-NULL if .note.gnu.build-id section should be created.  */
   char *emit_note_gnu_build_id;
 
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 17fb8bf..562cda4 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -63,6 +63,7 @@ fragment <<EOF
 
 /* Declare functions used by various EXTRA_EM_FILEs.  */
 static void gld${EMULATION_NAME}_before_parse (void);
+static void gld${EMULATION_NAME}_after_parse (void);
 static void gld${EMULATION_NAME}_after_open (void);
 static void gld${EMULATION_NAME}_before_allocation (void);
 static void gld${EMULATION_NAME}_after_allocation (void);
@@ -109,6 +110,19 @@ gld${EMULATION_NAME}_before_parse (void)
 EOF
 fi
 
+if test x"$LDEMUL_AFTER_PARSE" != xgld"$EMULATION_NAME"_after_parse; then
+fragment <<EOF
+
+static void
+gld${EMULATION_NAME}_after_parse (void)
+{
+  link_info.reverse_copy_ctors = `if test x"$ENABLE_INITFINI_ARRAY" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
+  after_parse_default ();
+}
+
+EOF
+fi
+
 if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then
 fragment <<EOF
 /* Handle the generation of DT_NEEDED tags.  */
@@ -2461,7 +2475,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
   ${LDEMUL_SYSLIB-syslib_default},
   ${LDEMUL_HLL-hll_default},
-  ${LDEMUL_AFTER_PARSE-after_parse_default},
+  ${LDEMUL_AFTER_PARSE-gld${EMULATION_NAME}_after_parse},
   ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
   ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},
   ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 73a417c..6648a01 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -81,12 +81,14 @@ set array_tests {
     {"init array" "" "" {init.c} "init" "init.out"}
     {"fini array" "" "" {fini.c} "fini" "fini.out"}
     {"init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
+    {"pr12730" "" "" {pr12730.cc} "pr12730" "pr12730.out" "" "c++"}
 }
 set array_tests_static {
     {"static preinit array" "-static" "" {preinit.c} "preinit" "preinit.out"}
     {"static init array" "-static" "" {init.c} "init" "init.out"}
     {"static fini array" "-static" "" {fini.c} "fini" "fini.out"}
     {"static init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
+    {"static pr12730" "" "" {pr12730.cc} "pr12730" "pr12730.out" "" "c++"}
 }
 
 # NetBSD ELF systems do not currently support the .*_array sections.
diff --git a/ld/testsuite/ld-elf/pr12730.cc b/ld/testsuite/ld-elf/pr12730.cc
new file mode 100644
index 0000000..69f57f9
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr12730.cc
@@ -0,0 +1,38 @@
+#include <iostream>
+
+class Hello
+{
+public:
+   Hello ()
+    {}
+
+  ~Hello ()
+    {}
+
+  void act ()
+    { std::cout << "Hello, world!" << std::endl; }
+};
+
+
+template <class T>
+struct Foo
+{
+  T* _M_allocate_single_object ()
+    {
+      return new T;
+    }
+};
+
+static void __attribute__ (( constructor )) PWLIB_StaticLoader() {
+  Foo<Hello> allocator;
+  Hello* salut = allocator._M_allocate_single_object ();
+  salut->act ();
+}
+
+
+int
+main (int /*argc*/,
+      char* /*argv*/[])
+{
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/pr12730.out b/ld/testsuite/ld-elf/pr12730.out
new file mode 100644
index 0000000..af5626b
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr12730.out
@@ -0,0 +1 @@
+Hello, world!


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]