Hi all,

Attached patch fixes PR lto/61048 - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61048

The reason of failure was that the builtin information structure was not initialized properly at the link stage. The failed assertion was caused by missing builtin declaration ( BUILT_IN_ASAN_AFTER_DYNAMIC_INIT), which was requested from this structure. As usual this information should be initialized in function lto_define_builtins, which is called from LTO lang hook function lto_init. But in the given testcase the initialization did not happen, since the declaration is initialized only if the following condition holds:

(flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
| SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))

But if the user compiles (without linking) file in LTO mode with -fsanitize=address option, and then tries to link the executable from *.o file, but does not specify option -fsanitize=address, variable flag_sanitize will be 0 and sanitizer builtins info will not be initialized, and ICE will happen.

Commands to reproduce the problem:
g++ test.cpp -c -o test.o -fsanitize=address -flto
g++ test.o -o test -Wl,-flto # At this stage flag_sanitize is 0, and sanitizer builtins are not defined.

The simplest way to fix this seems to add initialization of sanitizer builtins using function initialize_sanitizer_builtins - and this helps to avoid ICE:

diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index bc53632..f5ca849 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-inline.h"
 #include "params.h"
 #include "ipa-utils.h"
+#include "asan.h"


/* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */ @@ -1856,6 +1857,9 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, data_in = lto_data_in_create (decl_data, (const char *) data + string_offset,
                                header->string_size, resolutions);

+  /* Initialize sanitizer builtins if necessary.  */
+  initialize_sanitizer_builtins();
+
   /* We do not uniquify the pre-loaded cache entries, those are middle-end
      internal types that should not be merged.  */

----
But this approach means that asan-specific functions must be called from lto.

The suggested patch proposes another approach: add definitions of builtins during the final stage, when they are requested from builtin_info structure. I have tried to do it by adding lto-specific lang-hook, so that to reuse existing code for builtins initialization (currently builtins are initialized in lto_init hook). In the attached patch such hook is added, and it is used in streamer_get_builtin_tree.

It seems that the discussed issue can happen not only for flag -fsanitize, but also for all options that cause the definition of builtins, so the proposed patch is independent from sanitizers.

The patch was bootstrapped and regtested on x86_64-unknown-linux-gnu.

Ok for trunk?

Best regards,
Ilya Palachev



>From 926a8b84a52f3120c3f71cd28e0d782c719b7791 Mon Sep 17 00:00:00 2001
From: Ilya Palachev <i.palac...@samsung.com>
Date: Tue, 14 Oct 2014 19:22:32 +0400
Subject: [PATCH] Define missed builtins on demand

gcc/

2014-10-14  Ilya Palachev  <i.palac...@samsung.com>

	* langhooks.h (define_builtin_on_demand): New function.
	* langhooks-def.h (LANG_HOOKS_DEFINE_BUILTIN_ON_DEMAND): New
	macro.
	* lto/lto-lang.c (lto_define_builtin_on_demand): New function.
	* tree-streamer-in.c (streamer_get_builtin_tree): Use
	define_builtin_on_demand in case when the declaration of builtin
	is missing.

gcc/testsuite/

2014-10-14  Ilya Palachev  <i.palac...@samsung.com>

	* g++.dg/lto/pr61048_0.C: New test from bugzilla.
---
 gcc/langhooks-def.h                  |  4 +++-
 gcc/langhooks.h                      |  3 +++
 gcc/lto/lto-lang.c                   | 16 ++++++++++++++++
 gcc/testsuite/g++.dg/lto/pr61048_0.C | 10 ++++++++++
 gcc/tree-streamer-in.c               |  4 ++++
 5 files changed, 36 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/lto/pr61048_0.C

diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index e5ae3e3..2ddccbc 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -254,11 +254,13 @@ extern void lhd_end_section (void);
 #define LANG_HOOKS_BEGIN_SECTION lhd_begin_section
 #define LANG_HOOKS_APPEND_DATA lhd_append_data
 #define LANG_HOOKS_END_SECTION lhd_end_section
+#define LANG_HOOKS_DEFINE_BUILTIN_ON_DEMAND 0
 
 #define LANG_HOOKS_LTO { \
   LANG_HOOKS_BEGIN_SECTION, \
   LANG_HOOKS_APPEND_DATA, \
-  LANG_HOOKS_END_SECTION \
+  LANG_HOOKS_END_SECTION, \
+  LANG_HOOKS_DEFINE_BUILTIN_ON_DEMAND \
 }
 
 /* The whole thing.  The structure is defined in langhooks.h.  */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 32e76f9..a0cbe5f 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -255,6 +255,9 @@ struct lang_hooks_for_lto
 
   /* End the previously begun LTO section.  */
   void (*end_section) (void);
+
+  /* Define builtin on demand.  */
+  void (*define_builtin_on_demand) (enum built_in_function fcode);
 };
 
 /* Language-specific hooks.  See langhooks-def.h for defaults.  */
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 9e8524a..4d458b2 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -697,6 +697,19 @@ lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
 #undef DEF_BUILTIN
 }
 
+static void
+lto_define_builtin_on_demand(enum built_in_function fcode)
+{
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,\
+		    NONANSI_P, ATTRS, IMPLICIT, COND)			\
+    if (NAME && (ENUM == fcode))					\
+      def_builtin_1 (ENUM, NAME, CLASS, builtin_types[(int) TYPE],	\
+		     builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P,	\
+		     NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT);
+#include "builtins.def"
+#undef DEF_BUILTIN
+}
+
 static GTY(()) tree registered_builtin_types;
 
 /* Language hooks.  */
@@ -1308,6 +1321,9 @@ static void lto_init_ts (void)
 #undef LANG_HOOKS_INIT_TS
 #define LANG_HOOKS_INIT_TS lto_init_ts
 
+#undef LANG_HOOKS_DEFINE_BUILTIN_ON_DEMAND
+#define LANG_HOOKS_DEFINE_BUILTIN_ON_DEMAND lto_define_builtin_on_demand
+
 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /* Language hooks that are not part of lang_hooks.  */
diff --git a/gcc/testsuite/g++.dg/lto/pr61048_0.C b/gcc/testsuite/g++.dg/lto/pr61048_0.C
new file mode 100644
index 0000000..e5f4961
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr61048_0.C
@@ -0,0 +1,10 @@
+// { dg-lto-do link }
+// { dg-lto-options {{-fsanitize=address -flto}} }
+
+#include <iostream>
+int main()
+{
+  int *i = reinterpret_cast<int*>(0xC1000000);
+  std::cout << *i << std::endl;
+}
+
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 01a55bf..6387f33 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "streamer-hooks.h"
 #include "lto-streamer.h"
 #include "builtins.h"
+#include "langhooks.h"
 
 /* Read a STRING_CST from the string table in DATA_IN using input
    block IB.  */
@@ -1115,6 +1116,9 @@ streamer_get_builtin_tree (struct lto_input_block *ib, struct data_in *data_in)
       if (fcode >= END_BUILTINS)
 	fatal_error ("machine independent builtin code out of range");
       result = builtin_decl_explicit (fcode);
+      if (!result)
+        lang_hooks.lto.define_builtin_on_demand(fcode);
+      result = builtin_decl_explicit (fcode);
       gcc_assert (result);
     }
   else if (fclass == BUILT_IN_MD)
-- 
2.1.1

Reply via email to