On Sat, Dec 8, 2012 at 9:13 AM, H.J. Lu <hjl.to...@gmail.com> wrote: > On Thu, Nov 22, 2012 at 6:45 AM, H.J. Lu <hjl.to...@gmail.com> wrote: >> 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...@intel.com> >> >> PR driver/55374 >> * gcc.c (prepend_lang_specific_driver): New function. >> (process_command): Use it. >> >> 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); > > PING. > > A simple testcase: > > [hjl@gnu-6 gcc]$ cat /tmp/bad.cc > #include <new> > > int > main () > { > int *buf = new int(30); > buf[30]=1; > return 0; > } > [hjl@gnu-6 gcc]$ ./release/usr/gcc-4.8.0/bin/g++ -fsanitize=address > /tmp/bad.cc > -static-libasan -static-libstdc++ > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libasan.a(asan_new_delete.o): > In function `operator new(unsigned long)': > /export/gnu/import/git/gcc/libsanitizer/asan/asan_new_delete.cc:41: multiple > definition of `operator new(unsigned long)' > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libstdc++.a(new_op.o):/export/gnu/import/git/gcc/libstdc++-v3/libsupc++/new_op.cc:45: > first defined here > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libasan.a(asan_new_delete.o): > In function `operator delete(void*)': > /export/gnu/import/git/gcc/libsanitizer/asan/asan_new_delete.cc:54: multiple > definition of `operator delete(void*)' > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libstdc++.a(del_op.o):/export/gnu/import/git/gcc/libstdc++-v3/libsupc++/del_op.cc:46: > first defined here > collect2: error: ld returned 1 exit status > [hjl@gnu-6 gcc]$ > > [rep[hjl@gnu-6 gcc]$ cat /tmp/bad.cc > #include <new> > > int > main () > { > int *buf = new int(30); > buf[30]=1; > return 0; > } > [hjl@gnu-6 gcc]$ ./release/usr/gcc-4.8.0/bin/g++ -fsanitize=address > /tmp/bad.cc > -static-libasan -static-libstdc++ > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libasan.a(asan_new_delete.o): > In function `operator new(unsigned long)': > /export/gnu/import/git/gcc/libsanitizer/asan/asan_new_delete.cc:41: multiple > definition of `operator new(unsigned long)' > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libstdc++.a(new_op.o):/export/gnu/import/git/gcc/libstdc++-v3/libsupc++/new_op.cc:45: > first defined here > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libasan.a(asan_new_delete.o): > In function `operator delete(void*)': > /export/gnu/import/git/gcc/libsanitizer/asan/asan_new_delete.cc:54: multiple > definition of `operator delete(void*)' > /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/../../../../lib64/libstdc++.a(del_op.o):/export/gnu/import/git/gcc/libstdc++-v3/libsupc++/del_op.cc:46: > first defined here > collect2: error: ld returned 1 exit status > [hjl@gnu-6 gcc]$
PING. -- H.J.