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

H.J. Lu hjl.tools@gmail.com
Thu May 5 13:27:00 GMT 2011


On Thu, May 5, 2011 at 1:27 AM, Alan Modra <amodra@gmail.com> wrote:
> On Wed, May 04, 2011 at 10:18:32PM -0700, H.J. Lu wrote:
>> 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?
>
> What about .dtors?  You have the same problem there.  I suspect, but

You are right.  Here is the updated patch to handle .dtors sections
with the updated testcase.  OK for trunk?

> haven't verified, that .ctors.* and .dtors.* also need reversing.  If
> that is true then it would be better to do your reversing trick for
> anything going to the .init_array output section that isn't named
> .init_array* and similarly for .fini_array.
>
> You also need to reverse any dynamic relocations applying to the
> sections you are reversing.

It isn't a problem since we apply relocations on the input sections
first and copy relocated input sections to output where I reverse
copy .ctors/.dtors sections if needed.

Thanks.


-- 
H.J.
---
bfd/

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

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

include/

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

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

ld/

2011-05-05  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-05  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/init-mixed.c (ctor65535): Renamed to ...
	(ctor65535a): This.
	(ctor65535b): New.
	(ctors65535): Remove ctor65535.  Add ctor65535b and ctor65535a.
	(dtor65535): Renamed to ...
	(dtor65535a): This.
	(dtor65535b): New.
	(dtors65535): Remove dtor65535.  Add dtor65535b and dtor65535a.

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

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

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

include/

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

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

ld/

2011-05-05  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-05  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/init-mixed.c (ctor65535): Renamed to ...
	(ctor65535a): This.
	(ctor65535b): New.
	(ctors65535): Remove ctor65535.  Add ctor65535b and ctor65535a.
	(dtor65535): Renamed to ...
	(dtor65535a): This.
	(dtor65535b): New.
	(dtors65535): Remove dtor65535.  Add dtor65535b and dtor65535a.

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

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 082355d..c7027a2 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9876,12 +9876,50 @@ 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;
+		/* Check if we need to reverse-copy .ctors/.dtors
+		   sections.  */
+		if (finfo->info->reverse_copy_ctors_dtors
+		    && todo > address_size
+		    && o->name[0] == '.'
+		    && (o->name[1] == 'c' || o->name[1] == 'd')
+		    && strcmp (o->name + 2, "tors") == 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..3f230ad 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/.dtors sections.  */
+  unsigned int reverse_copy_ctors_dtors: 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..ce8c21e 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_dtors = `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/init-mixed.c b/ld/testsuite/ld-elf/init-mixed.c
index 1d0c727..2c9d434 100644
--- a/ld/testsuite/ld-elf/init-mixed.c
+++ b/ld/testsuite/ld-elf/init-mixed.c
@@ -69,17 +69,31 @@ void (*const fini_array65530[]) ()
   = { fini65530 };
 
 static void
-ctor65535 ()
+ctor65535a ()
 {
   if (count != 65530)
     abort ();
   count = 65535;
 }
+static void
+ctor65535b ()
+{
+  if (count != 65535)
+    abort ();
+  count = 65536;
+}
 void (*const ctors65535[]) ()
   __attribute__ ((section (".ctors"), aligned (sizeof (void *))))
-  = { ctor65535 };
+  = { ctor65535b, ctor65535a };
+static void
+dtor65535b ()
+{
+  if (count != 65536)
+    abort ();
+  count = 65535;
+}
 static void
-dtor65535 ()
+dtor65535a ()
 {
   if (count != 65535)
     abort ();
@@ -87,7 +101,7 @@ dtor65535 ()
 }
 void (*const dtors65535[]) ()
   __attribute__ ((section (".dtors"), aligned (sizeof (void *))))
-  = { dtor65535 };
+  = { dtor65535b, dtor65535a };
 #endif
 
 int
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!


More information about the Binutils mailing list