PATCH: PR ld/12730: regression] crash when allocating in a static constructor
H.J. Lu
hongjiu.lu@intel.com
Thu May 5 05:19:00 GMT 2011
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!
More information about the Binutils
mailing list