From 137f139972a89259b9d8521e13ecb76fd2cef433 Mon Sep 17 00:00:00 2001
From: Maxim Ostapenko <m.ostapenko@samsung.com>
Date: Fri, 28 Oct 2016 10:22:03 +0300
Subject: [PATCH 7/7] Add support for ASan odr_indicator.
config/
* bootstrap-asan.mk: Replace LSAN_OPTIONS=detect_leaks=0 with
ASAN_OPTIONS=detect_leaks=0:use_odr_indicator=1.
gcc/
* asan.c (asan_global_struct): Refactor.
(create_odr_indicator): New function.
(asan_needs_odr_indicator_p): Likewise.
(is_odr_indicator): Likewise.
(asan_add_global): Introduce odr_indicator_ptr. Pass it into global's
constructor.
(asan_protect_global): Do not protect odr indicators.
gcc/testsuite/
* c-c++-common/asan/no-redundant-odr-indicators-1.c: New test.
---
config/ChangeLog | 5 ++
config/bootstrap-asan.mk | 2 +-
gcc/ChangeLog | 10 +++
gcc/asan.c | 76 +++++++++++++++++++---
gcc/testsuite/ChangeLog | 4 ++
.../asan/no-redundant-odr-indicators-1.c | 17 +++++
6 files changed, 105 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/asan/no-redundant-odr-indicators-1.c
@@ -1,3 +1,8 @@
+2016-11-07 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * bootstrap-asan.mk: Replace LSAN_OPTIONS=detect_leaks=0 with
+ ASAN_OPTIONS=detect_leaks=0:use_odr_indicator=1.
+
2016-06-21 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
* elf.m4: Remove interix support.
@@ -1,7 +1,7 @@
# This option enables -fsanitize=address for stage2 and stage3.
# Suppress LeakSanitizer in bootstrap.
-export LSAN_OPTIONS="detect_leaks=0"
+export ASAN_OPTIONS=detect_leaks=0:use_odr_indicator=1
STAGE2_CFLAGS += -fsanitize=address
STAGE3_CFLAGS += -fsanitize=address
@@ -1,5 +1,15 @@
2016-11-07 Maxim Ostapenko <m.ostapenko@samsung.com>
+ * asan.c (asan_global_struct): Refactor.
+ (create_odr_indicator): New function.
+ (asan_needs_odr_indicator_p): Likewise.
+ (is_odr_indicator): Likewise.
+ (asan_add_global): Introduce odr_indicator_ptr. Pass it into global's
+ constructor.
+ (asan_protect_global): Do not protect odr indicators.
+
+2016-11-07 Maxim Ostapenko <m.ostapenko@samsung.com>
+
* asan.h (asan_intercepted_p): Handle BUILT_IN_STRCSPN,
BUILT_IN_STRPBRK, BUILT_IN_STRSPN and BUILT_IN_STRSTR.
@@ -1329,6 +1329,16 @@ asan_needs_local_alias (tree decl)
return DECL_WEAK (decl) || !targetm.binds_local_p (decl);
}
+/* Return true if DECL, a global var, is an artificial ODR indicator symbol
+ therefore doesn't need protection. */
+
+static bool
+is_odr_indicator (tree decl)
+{
+ const char *sym_name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ return strstr(sym_name, "_.__odr_asan_") == sym_name;
+}
+
/* Return true if DECL is a VAR_DECL that should be protected
by Address Sanitizer, by appending a red zone with protected
shadow memory after it and aligning it to at least
@@ -1377,7 +1387,8 @@ asan_protect_global (tree decl)
|| ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
|| !valid_constant_size_p (DECL_SIZE_UNIT (decl))
|| DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE
- || TREE_TYPE (decl) == ubsan_get_source_location_type ())
+ || TREE_TYPE (decl) == ubsan_get_source_location_type ()
+ || is_odr_indicator (decl))
return false;
rtl = DECL_RTL (decl);
@@ -2197,14 +2208,15 @@ asan_dynamic_init_call (bool after_p)
static tree
asan_global_struct (void)
{
- static const char *field_names[8]
+ static const char *field_names[]
= { "__beg", "__size", "__size_with_redzone",
- "__name", "__module_name", "__has_dynamic_init", "__location", "__odr_indicator"};
- tree fields[8], ret;
- int i;
+ "__name", "__module_name", "__has_dynamic_init", "__location",
+ "__odr_indicator"};
+ tree fields[ARRAY_SIZE (field_names)], ret;
+ unsigned i;
ret = make_node (RECORD_TYPE);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < ARRAY_SIZE (field_names); i++)
{
fields[i]
= build_decl (UNKNOWN_LOCATION, FIELD_DECL,
@@ -2226,6 +2238,52 @@ asan_global_struct (void)
return ret;
}
+/* Create and return odr indicator symbol for DECL.
+ TYPE is __asan_global struct type as returned by asan_global_struct. */
+
+static tree
+create_odr_indicator (tree decl, tree type)
+{
+ char sym_name[100], tmp_name[100];
+ static int lasan_odr_ind_cnt = 0;
+ tree uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
+
+ snprintf (tmp_name, sizeof (tmp_name), "__odr_asan_%s_",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ ASM_GENERATE_INTERNAL_LABEL (sym_name, tmp_name, ++lasan_odr_ind_cnt);
+ char *asterisk = sym_name;
+ while ((asterisk = strchr (asterisk, '*')))
+ *asterisk = '_';
+ tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (sym_name),
+ char_type_node);
+ TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (decl);
+ TREE_READONLY (var) = 0;
+ TREE_THIS_VOLATILE (var) = 1;
+ DECL_GIMPLE_REG_P (var) = DECL_GIMPLE_REG_P (decl);
+ DECL_ARTIFICIAL (var) = 1;
+ DECL_IGNORED_P (var) = DECL_IGNORED_P (decl);
+ TREE_STATIC (var) = 1;
+ TREE_PUBLIC (var) = 1;
+ DECL_VISIBILITY (var) = DECL_VISIBILITY (decl);
+ TREE_USED (var) = 1;
+ tree ctor = build_constructor_va (TREE_TYPE (var), 1, NULL_TREE,
+ build_int_cst (unsigned_type_node, 0));
+ TREE_CONSTANT (ctor) = 1;
+ TREE_STATIC (ctor) = 1;
+ DECL_INITIAL (var) = ctor;
+ varpool_node::finalize_decl (var);
+ return fold_convert (uptr, build_fold_addr_expr (var));
+}
+
+/* Return true if DECL, a global var, might be overridden and needs
+ an additional odr indicator symbol. */
+
+static bool
+asan_needs_odr_indicator_p (tree decl)
+{
+ return !DECL_ARTIFICIAL (decl) && !DECL_WEAK (decl) && TREE_PUBLIC (decl);
+}
+
/* Append description of a single global DECL into vector V.
TYPE is __asan_global struct type as returned by asan_global_struct. */
@@ -2266,6 +2324,9 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl));
}
+ tree odr_indicator_ptr = asan_needs_odr_indicator_p (decl)
+ ? create_odr_indicator (decl, type)
+ : build_int_cst (uptr, 0);
CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
fold_convert (const_ptr_type_node,
build_fold_addr_expr (refdecl)));
@@ -2313,8 +2374,7 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
else
locptr = build_int_cst (uptr, 0);
CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
- /* TODO: support ODR indicators. */
- CONSTRUCTOR_APPEND_ELT(vinner, NULL_TREE, build_int_cst (uptr, 0));
+ CONSTRUCTOR_APPEND_ELT(vinner, NULL_TREE, odr_indicator_ptr);
init = build_constructor (type, vinner);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
}
@@ -1,5 +1,9 @@
2016-11-07 Maxim Ostapenko <m.ostapenko@samsung.com>
+ * c-c++-common/asan/no-redundant-odr-indicators-1.c: New test.
+
+2016-11-07 Maxim Ostapenko <m.ostapenko@samsung.com>
+
* c-c++-common/asan/default_options.h: New file.
* c-c++-common/asan/strcasestr-1.c: New test.
* c-c++-common/asan/strcasestr-2.c: Likewise.
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+/* Local variables should not have odr indicators. */
+static int a = 2;
+/* Thread local variables should not have odr indicators. */
+__thread int b = 3;
+/* Externally visible variables should have odr indicators. */
+int c = 1;
+
+int main () {
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not ".*odr_asan_a.*" } } */
+/* { dg-final { scan-assembler-not ".*odr_asan_b.*" } } */
+/* { dg-final { scan-assembler ".*odr_asan_c.*" } } */
--
1.9.1