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