Patchwork PATCH: PR driver/55374: [asan] Wrong linking order of libasan and libstdc++

login
register
mail settings
Submitter H.J. Lu
Date Nov. 22, 2012, 2:45 p.m.
Message ID <20121122144540.GA23841@gmail.com>
Download mbox | patch
Permalink /patch/201055/
State New
Headers show

Comments

H.J. Lu - Nov. 22, 2012, 2:45 p.m.
Hi,

libasan should come first before any language-specific
adjustment/addition.  Otherwise, we got

g++ -fsanitize=address -static-libasan ...

/usr/local/bin/ld: error:
/export/build/gnu/gcc-asan/build-x86_64-linux/prev-x86_64-unknown-linux-gnu/libsanitizer/asan/.libs/libasan.a(asan_new_delete.o):
multiple definition of 'operator delete(void*)'
/usr/local/bin/ld:
/export/build/gnu/gcc-asan/build-x86_64-linux/prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.a(del_op.o):
previous definition here

This patch adds prepend_lang_specific_driver to prepend command line before
language-specific adjustment/addition of flags.  OK to install?

Thanks.


H.J.
---
2012-11-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/55374
	* gcc.c (prepend_lang_specific_driver): New function.
	(process_command): Use it.

Patch

diff --git a/gcc/gcc.c b/gcc/gcc.c
index 0f8bcea..41474aa 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -3604,6 +3604,80 @@  set_option_handlers (struct cl_option_handlers *handlers)
   handlers->handlers[2].mask = CL_TARGET;
 }
 
+/* Prepend command line before language-specific adjustment/addition of
+   flags.  */
+
+void
+prepend_lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+			      unsigned int *in_decoded_options_count,
+			      int *in_added_libraries)
+{
+  unsigned int i, argc;
+
+  /* The new argument list will be contained in this.  */
+  struct cl_decoded_option *new_decoded_options;
+
+  /* The argument list.  */
+  struct cl_decoded_option *decoded_options;
+
+  bool add_libasan = false;
+  bool static_libasan = false;
+
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
+
+  for (i = 1; i < argc; i++)
+    switch (decoded_options[i].opt_index)
+      {
+      case OPT_fsanitize_address:
+	add_libasan = true;
+	break;
+      case OPT_static_libasan:
+	static_libasan = true;
+	break;
+      }
+
+  if (add_libasan)
+    {
+      /* Add -lasan before language-specific adjustment/addition.  */
+      unsigned int added_argc;
+
+      added_argc = 1;
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (static_libasan)
+	added_argc += 2;
+#endif
+
+      new_decoded_options = XNEWVEC (struct cl_decoded_option,
+				     argc + added_argc);
+
+      i = 0;
+      do
+	{
+	  new_decoded_options[i] = decoded_options[i];
+	  i++;
+	}
+      while (i < argc);
+
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (static_libasan)
+	generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER,
+			 &new_decoded_options[i++]);
+#endif
+      generate_option (OPT_l, "asan", 1, CL_DRIVER,
+		       &new_decoded_options[i++]);
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (static_libasan)
+	generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER,
+			 &new_decoded_options[i++]);
+#endif
+
+      *in_decoded_options_count = i;
+      *in_decoded_options = new_decoded_options;
+      *in_added_libraries = 1;
+    }
+}
+
 /* Create the vector `switches' and its contents.
    Store its length in `n_switches'.  */
 
@@ -3695,6 +3769,11 @@  process_command (unsigned int decoded_options_count,
      or an automatically created GCC_EXEC_PREFIX from
      decoded_options[0].arg.  */
 
+  /* Prepend command line before language-specific adjustment/addition of
+     flags.  */
+  prepend_lang_specific_driver (&decoded_options, &decoded_options_count,
+				&added_libraries);
+
   /* Do language-specific adjustment/addition of flags.  */
   lang_specific_driver (&decoded_options, &decoded_options_count,
 			&added_libraries);