On Fri, Sep 12, 2025 at 8:31 PM H.J. Lu <[email protected]> wrote:
>
> Since IFUNC resolvers run early before the sanitizer run-time libraries
> have a chance to set up the sanitizer infrastructure, disable sanitizer
> in IFUNC resolver when the sanitizer infrastructure initialization is
> needed.
>
> gcc/
>
>         PR sanitizer/110442
>         * asan.h (sanitize_flags_p): Return false if the function is
>         called by IFUNC resolver.
>         (sanitize_coverage_p): Likewise.
>         * cgraph.cc (called_by_ifunc_resolver_p): New.
>         * internal-fn.cc (expand_TSAN_FUNC_EXIT): Return in function
>         called by IFUNC resolver.
>         * tree.h (called_by_ifunc_resolver_p): Likewise.
>
> gcc/testsuite/
>
>         PR sanitizer/110442
>         * gcc.dg/asan/ifunc-1.c: New test.
>         * gcc.dg/tsan/ifunc-1.c: Likewise.
>         * gcc.dg/ubsan/ifunc-shift-1.c: Likewise.
>
> Signed-off-by: H.J. Lu <[email protected]>
> ---
>  gcc/asan.h                                 |  9 ++++-
>  gcc/cgraph.cc                              |  9 +++++
>  gcc/internal-fn.cc                         |  6 ++-
>  gcc/testsuite/gcc.dg/asan/ifunc-1.c        | 37 ++++++++++++++++++
>  gcc/testsuite/gcc.dg/tsan/ifunc-1.c        | 38 +++++++++++++++++++
>  gcc/testsuite/gcc.dg/ubsan/ifunc-shift-1.c | 44 ++++++++++++++++++++++
>  gcc/tree.h                                 |  5 +++
>  7 files changed, 144 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/asan/ifunc-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/tsan/ifunc-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/ubsan/ifunc-shift-1.c
>
> diff --git a/gcc/asan.h b/gcc/asan.h
> index a24562f67a2..999ed0dd818 100644
> --- a/gcc/asan.h
> +++ b/gcc/asan.h
> @@ -251,6 +251,10 @@ sanitize_flags_p (sanitize_code_type flag,
>
>    if (fn != NULL_TREE)
>      {
> +      if (TREE_CODE (fn) == FUNCTION_DECL
> +         && called_by_ifunc_resolver_p (fn))
> +       return false;
> +
>        tree value = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (fn));
>        if (value)
>         result_flags &= ~tree_to_uhwi (TREE_VALUE (value));
> @@ -266,8 +270,9 @@ sanitize_coverage_p (const_tree fn = 
> current_function_decl)
>  {
>    return (flag_sanitize_coverage
>           && (fn == NULL_TREE
> -             || lookup_attribute ("no_sanitize_coverage",
> -                                  DECL_ATTRIBUTES (fn)) == NULL_TREE));
> +             || (!called_by_ifunc_resolver_p (fn)
> +                 && !lookup_attribute ("no_sanitize_coverage",
> +                                       DECL_ATTRIBUTES (fn)))));
>  }
>
>  #endif /* TREE_ASAN */
> diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
> index 32071a84bac..820c57695c2 100644
> --- a/gcc/cgraph.cc
> +++ b/gcc/cgraph.cc
> @@ -4494,6 +4494,15 @@ cgraph_node::former_thunk_p (void)
>    return true;
>  }
>
> +/* Return true if FN is called by an IFUNC resolver.  */
> +
> +bool
> +called_by_ifunc_resolver_p (const_tree fn)
> +{
> +  struct cgraph_node *c_node = cgraph_node::get (fn);
> +  return c_node && c_node->called_by_ifunc_resolver;
> +}
> +
>  /* A stashed copy of "symtab" for use by selftest::symbol_table_test.
>     This needs to be a global so that it can be a GC root, and thus
>     prevent the stashed copy from being garbage-collected if the GC runs
> diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
> index bf2fac81807..f4cc0ce745d 100644
> --- a/gcc/internal-fn.cc
> +++ b/gcc/internal-fn.cc
> @@ -877,12 +877,14 @@ expand_ASAN_POISON_USE (internal_fn, gcall *)
>    gcc_unreachable ();
>  }
>
> -/* This should get expanded in the tsan pass.  */
> +/* This should get expanded in the tsan pass unless it is in a function
> +   called by IFUNC resolver.  */
>
>  static void
>  expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
>  {
> -  gcc_unreachable ();
> +  if (!called_by_ifunc_resolver_p (current_function_decl))
> +    gcc_unreachable ();
>  }
>
>  /* This should get expanded in the lower pass.  */
> diff --git a/gcc/testsuite/gcc.dg/asan/ifunc-1.c 
> b/gcc/testsuite/gcc.dg/asan/ifunc-1.c
> new file mode 100644
> index 00000000000..3e944c4fb67
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/asan/ifunc-1.c
> @@ -0,0 +1,37 @@
> +/* PR sanitizer/110442 */
> +/* Don't use dg-require-ifunc to avoid marking this test as UNSUPPORTED
> +   due to ICE caused by compiler bug during IFUNC check.  */
> +/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
> +
> +#include <stdio.h>
> +
> +void
> +f1 (void)
> +{
> +  puts ("f1");
> +}
> +
> +void
> +f2 (void)
> +{
> +  puts ("f2");
> +}
> +
> +void *
> +resolve (void)
> +{
> +  __builtin_cpu_init ();
> +  if (__builtin_cpu_supports ("f16c"))
> +    return f1;
> +  else
> +    return f2;
> +}
> +
> +void f (void) __attribute__ ((ifunc ("resolve")));
> +
> +int
> +main (void)
> +{
> +  f ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/tsan/ifunc-1.c 
> b/gcc/testsuite/gcc.dg/tsan/ifunc-1.c
> new file mode 100644
> index 00000000000..da477e33983
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tsan/ifunc-1.c
> @@ -0,0 +1,38 @@
> +/* PR sanitizer/110442 */
> +/* Don't use dg-require-ifunc to avoid marking this test as UNSUPPORTED
> +   due to ICE caused by compiler bug during IFUNC check.  */
> +/* { dg-do run { target { x86_64-*-linux* } } } */
> +/* { dg-options "-fsanitize=thread" } */
> +
> +#include <stdio.h>
> +
> +void
> +f1 (void)
> +{
> +  puts ("f1");
> +}
> +
> +void
> +f2 (void)
> +{
> +  puts ("f2");
> +}
> +
> +void *
> +resolve (void)
> +{
> +  __builtin_cpu_init ();
> +  if (__builtin_cpu_supports ("f16c"))
> +    return f1;
> +  else
> +    return f2;
> +}
> +
> +void f (void) __attribute__ ((ifunc ("resolve")));
> +
> +int
> +main (void)
> +{
> +  f ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/ubsan/ifunc-shift-1.c 
> b/gcc/testsuite/gcc.dg/ubsan/ifunc-shift-1.c
> new file mode 100644
> index 00000000000..973097cf098
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/ubsan/ifunc-shift-1.c
> @@ -0,0 +1,44 @@
> +/* PR sanitizer/110442 */
> +/* Don't use dg-require-ifunc to avoid marking this test as UNSUPPORTED
> +   due to ICE caused by compiler bug during IFUNC check.  */
> +/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
> +/* { dg-options "-fsanitize=shift-exponent -Wno-shift-count-overflow" } */
> +
> +#include <stdio.h>
> +
> +int n = 30;
> +
> +void
> +f1 (void)
> +{
> +  puts ("f1");
> +}
> +
> +void
> +f2 (void)
> +{
> +  puts ("f2");
> +}
> +
> +void *
> +resolve (void)
> +{
> +  if ((n << 32) != 0)
> +    return f1;
> +  __builtin_cpu_init ();
> +  if (__builtin_cpu_supports ("f16c"))
> +    return f1;
> +  else
> +    return f2;
> +}
> +
> +void f (void) __attribute__ ((ifunc ("resolve")));
> +
> +int
> +main (void)
> +{
> +  f ();
> +  return 0;
> +}
> +
> +/* { dg-output "shift exponent 32 is too large for 32-bit type 
> 'int'\[^\n\r]*(\n|\r\n|\r)" } */
> diff --git a/gcc/tree.h b/gcc/tree.h
> index ce8c778087f..706e704b2e2 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -7113,4 +7113,9 @@ extern auto_vec<string_slice> get_clone_versions (const 
> tree, int * = NULL);
>     directly.  */
>  extern auto_vec<string_slice> get_clone_attr_versions (const tree, int *);
>
> +/* In cgraph.cc */
> +
> +/* Return true if the function is called by an IFUNC resolver.  */
> +extern bool called_by_ifunc_resolver_p (const_tree);
> +
>  #endif  /* GCC_TREE_H  */
> --
> 2.51.0
>

PING^1.

-- 
H.J.

Reply via email to