This flag can't be used at the same time as any of the other sanitizers.
We add an equivalent flag to -static-libasan in -static-libhwasan to
ensure static linking.
gcc/ChangeLog:
2019-09-06 Matthew Malcomson <[email protected]>
* common.opt (static-libhwasan): New cli option.
* config/gnu-user.h (LIBHWASAN_EARLY_SPEC): hwasan equivalent of
asan command line flags.
* flag-types.h (enum sanitize_code): SANITIZE_HWADDRESS member.
* gcc.c (STATIC_LIBHWASAN_LIBS): New macro.
(LIBHWASAN_SPEC): New macro.
(LIBHWASAN_EARLY_SPEC): New macro.
(SANITIZER_EARLY_SPEC): Update to include hwasan.
(SANITIZER_SPEC): Update to include hwasan.
(sanitize_spec_function): Use hwasan.
* opts.c (finish_options): Add conflict between hwasan and tsan,
also between hwasan and asan.
(sanitizer_opts): New option structure for -fsanitize=hwaddress.
############### Attachment also inlined for ease of reply ###############
diff --git a/gcc/common.opt b/gcc/common.opt
index
d342c4f3749a39df086236162636f14f91bcd8a0..527aada305097b54c927fd094e3ab82220459c2c
100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3273,6 +3273,9 @@ Driver
static-libasan
Driver
+static-libhwasan
+Driver
+
static-libtsan
Driver
diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index
055a4f0afeca4a6339fd156db1bf1daf1aae0994..1e4b921afb62f22892aee0ca37e96983112a8134
100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -129,14 +129,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively.
If not, see
/* Link -lasan early on the command line. For -static-libasan, don't link
it for -shared link, the executable should be compiled with -static-libasan
in that case, and for executable link with --{,no-}whole-archive around
- it to force everything into the executable. And similarly for -ltsan
- and -llsan. */
+ it to force everything into the executable. And similarly for -ltsan,
+ -lhwasan, and -llsan. */
#if defined(HAVE_LD_STATIC_DYNAMIC)
#undef LIBASAN_EARLY_SPEC
#define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \
"%{static-libasan:%{!shared:" \
LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \
LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}"
+#undef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC "%{static-libhwasan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -lhwasan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-libhwasan:-lhwasan}"
#undef LIBTSAN_EARLY_SPEC
#define LIBTSAN_EARLY_SPEC "%{!shared:libtsan_preinit%O%s} " \
"%{static-libtsan:%{!shared:" \
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index
a2103282d469db31ad157a87572068d943061c8c..fcc3dd45862b1b64b38a13702f7840ba461aea20
100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -256,6 +256,7 @@ enum sanitize_code {
SANITIZE_BUILTIN = 1UL << 25,
SANITIZE_POINTER_COMPARE = 1UL << 26,
SANITIZE_POINTER_SUBTRACT = 1UL << 27,
+ SANITIZE_HWADDRESS = 1UL << 28,
SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
| SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
diff --git a/gcc/gcc.c b/gcc/gcc.c
index
7ebdf1f225b49769af3047c852ad3b72d6912fc0..c3d939af1a0fac87a8de95dff3960f2175aecf6d
100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -708,6 +708,24 @@ proper position among the other output files. */
#define LIBASAN_EARLY_SPEC ""
#endif
+#ifndef LIBHWASAN_SPEC
+#define STATIC_LIBHWASAN_LIBS \
+ " %{static-libhwasan|static:%:include(libsanitizer.spec)%(link_libhwasan)}"
+#ifdef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_SPEC STATIC_LIBHWASAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBHWASAN_SPEC "%{static-libhwasan:" LD_STATIC_OPTION \
+ "} -lhwasan %{static-libhwasan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBHWASAN_LIBS
+#else
+#define LIBHWASAN_SPEC "-lhwasan" STATIC_LIBHWASAN_LIBS
+#endif
+#endif
+
+#ifndef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC ""
+#endif
+
#ifndef LIBTSAN_SPEC
#define STATIC_LIBTSAN_LIBS \
" %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}"
@@ -982,6 +1000,7 @@ proper position among the other output files. */
#ifndef SANITIZER_EARLY_SPEC
#define SANITIZER_EARLY_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC
"} \
+ %{%:sanitize(hwaddress):" LIBHWASAN_EARLY_SPEC "} \
%{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
%{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}"
#endif
@@ -991,6 +1010,8 @@ proper position among the other output files. */
#define SANITIZER_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=address}}\
+ %{%:sanitize(hwaddress):" LIBHWASAN_SPEC "\
+ %{static:%ecannot specify -static with -fsanitize=hwaddress}}\
%{%:sanitize(thread):" LIBTSAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=thread}}\
%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
@@ -9387,6 +9408,8 @@ sanitize_spec_function (int argc, const char **argv)
if (strcmp (argv[0], "address") == 0)
return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "hwaddress") == 0)
+ return (flag_sanitize & SANITIZE_HWADDRESS) ? "" : NULL;
if (strcmp (argv[0], "kernel-address") == 0)
return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL;
if (strcmp (argv[0], "thread") == 0)
diff --git a/gcc/opts.c b/gcc/opts.c
index
879ab17c3620ca6e002b46f4f833ed2b4c0f5432..aedb1db6c00a139f575a341559006d9c3871d233
100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1174,6 +1174,20 @@ finish_options (struct gcc_options *opts, struct
gcc_options *opts_set,
error_at (loc,
"%<-fsanitize=leak%> is incompatible with %<-fsanitize=thread%>");
+ /* HWASan and ASan conflict with each other. */
+ if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
+ && (opts->x_flag_sanitize & SANITIZE_HWADDRESS))
+ error_at (loc,
+ "%<-fsanitize=hwaddress%> is incompatible with both"
+ "%<-fsanitize=address%> and %<-fsanitize=kernel-address%>");
+
+ /* And with TSan. */
+ if ((opts->x_flag_sanitize & SANITIZE_HWADDRESS)
+ && (opts->x_flag_sanitize & SANITIZE_THREAD))
+ error_at (loc,
+ "%<-fsanitize=hwaddress%> is incompatible with "
+ "%<-fsanitize=thread%>");
+
/* Check error recovery for -fsanitize-recover option. */
for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
@@ -1193,7 +1207,8 @@ finish_options (struct gcc_options *opts, struct
gcc_options *opts_set,
/* Enable -fsanitize-address-use-after-scope if address sanitizer is
enabled. */
- if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+ if (((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+ || (opts->x_flag_sanitize & SANITIZE_HWADDRESS))
&& !opts_set->x_flag_sanitize_address_use_after_scope)
opts->x_flag_sanitize_address_use_after_scope = true;
@@ -1752,6 +1767,8 @@ const struct sanitizer_opts_s sanitizer_opts[] =
#define SANITIZER_OPT(name, flags, recover) \
{ #name, flags, sizeof #name - 1, recover }
SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true),
+ // TODO Look into this properly
+ SANITIZER_OPT (hwaddress, (SANITIZE_HWADDRESS), false),
SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
true),
SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true),
diff --git a/gcc/common.opt b/gcc/common.opt
index
d342c4f3749a39df086236162636f14f91bcd8a0..527aada305097b54c927fd094e3ab82220459c2c
100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3273,6 +3273,9 @@ Driver
static-libasan
Driver
+static-libhwasan
+Driver
+
static-libtsan
Driver
diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index
055a4f0afeca4a6339fd156db1bf1daf1aae0994..1e4b921afb62f22892aee0ca37e96983112a8134
100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -129,14 +129,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively.
If not, see
/* Link -lasan early on the command line. For -static-libasan, don't link
it for -shared link, the executable should be compiled with -static-libasan
in that case, and for executable link with --{,no-}whole-archive around
- it to force everything into the executable. And similarly for -ltsan
- and -llsan. */
+ it to force everything into the executable. And similarly for -ltsan,
+ -lhwasan, and -llsan. */
#if defined(HAVE_LD_STATIC_DYNAMIC)
#undef LIBASAN_EARLY_SPEC
#define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \
"%{static-libasan:%{!shared:" \
LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \
LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}"
+#undef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC "%{static-libhwasan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -lhwasan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-libhwasan:-lhwasan}"
#undef LIBTSAN_EARLY_SPEC
#define LIBTSAN_EARLY_SPEC "%{!shared:libtsan_preinit%O%s} " \
"%{static-libtsan:%{!shared:" \
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index
a2103282d469db31ad157a87572068d943061c8c..fcc3dd45862b1b64b38a13702f7840ba461aea20
100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -256,6 +256,7 @@ enum sanitize_code {
SANITIZE_BUILTIN = 1UL << 25,
SANITIZE_POINTER_COMPARE = 1UL << 26,
SANITIZE_POINTER_SUBTRACT = 1UL << 27,
+ SANITIZE_HWADDRESS = 1UL << 28,
SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
| SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
diff --git a/gcc/gcc.c b/gcc/gcc.c
index
7ebdf1f225b49769af3047c852ad3b72d6912fc0..c3d939af1a0fac87a8de95dff3960f2175aecf6d
100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -708,6 +708,24 @@ proper position among the other output files. */
#define LIBASAN_EARLY_SPEC ""
#endif
+#ifndef LIBHWASAN_SPEC
+#define STATIC_LIBHWASAN_LIBS \
+ " %{static-libhwasan|static:%:include(libsanitizer.spec)%(link_libhwasan)}"
+#ifdef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_SPEC STATIC_LIBHWASAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBHWASAN_SPEC "%{static-libhwasan:" LD_STATIC_OPTION \
+ "} -lhwasan %{static-libhwasan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBHWASAN_LIBS
+#else
+#define LIBHWASAN_SPEC "-lhwasan" STATIC_LIBHWASAN_LIBS
+#endif
+#endif
+
+#ifndef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC ""
+#endif
+
#ifndef LIBTSAN_SPEC
#define STATIC_LIBTSAN_LIBS \
" %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}"
@@ -982,6 +1000,7 @@ proper position among the other output files. */
#ifndef SANITIZER_EARLY_SPEC
#define SANITIZER_EARLY_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC
"} \
+ %{%:sanitize(hwaddress):" LIBHWASAN_EARLY_SPEC "} \
%{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
%{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}"
#endif
@@ -991,6 +1010,8 @@ proper position among the other output files. */
#define SANITIZER_SPEC "\
%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=address}}\
+ %{%:sanitize(hwaddress):" LIBHWASAN_SPEC "\
+ %{static:%ecannot specify -static with -fsanitize=hwaddress}}\
%{%:sanitize(thread):" LIBTSAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=thread}}\
%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
@@ -9387,6 +9408,8 @@ sanitize_spec_function (int argc, const char **argv)
if (strcmp (argv[0], "address") == 0)
return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "hwaddress") == 0)
+ return (flag_sanitize & SANITIZE_HWADDRESS) ? "" : NULL;
if (strcmp (argv[0], "kernel-address") == 0)
return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL;
if (strcmp (argv[0], "thread") == 0)
diff --git a/gcc/opts.c b/gcc/opts.c
index
879ab17c3620ca6e002b46f4f833ed2b4c0f5432..aedb1db6c00a139f575a341559006d9c3871d233
100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1174,6 +1174,20 @@ finish_options (struct gcc_options *opts, struct
gcc_options *opts_set,
error_at (loc,
"%<-fsanitize=leak%> is incompatible with %<-fsanitize=thread%>");
+ /* HWASan and ASan conflict with each other. */
+ if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
+ && (opts->x_flag_sanitize & SANITIZE_HWADDRESS))
+ error_at (loc,
+ "%<-fsanitize=hwaddress%> is incompatible with both"
+ "%<-fsanitize=address%> and %<-fsanitize=kernel-address%>");
+
+ /* And with TSan. */
+ if ((opts->x_flag_sanitize & SANITIZE_HWADDRESS)
+ && (opts->x_flag_sanitize & SANITIZE_THREAD))
+ error_at (loc,
+ "%<-fsanitize=hwaddress%> is incompatible with "
+ "%<-fsanitize=thread%>");
+
/* Check error recovery for -fsanitize-recover option. */
for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
@@ -1193,7 +1207,8 @@ finish_options (struct gcc_options *opts, struct
gcc_options *opts_set,
/* Enable -fsanitize-address-use-after-scope if address sanitizer is
enabled. */
- if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+ if (((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
+ || (opts->x_flag_sanitize & SANITIZE_HWADDRESS))
&& !opts_set->x_flag_sanitize_address_use_after_scope)
opts->x_flag_sanitize_address_use_after_scope = true;
@@ -1752,6 +1767,8 @@ const struct sanitizer_opts_s sanitizer_opts[] =
#define SANITIZER_OPT(name, flags, recover) \
{ #name, flags, sizeof #name - 1, recover }
SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true),
+ // TODO Look into this properly
+ SANITIZER_OPT (hwaddress, (SANITIZE_HWADDRESS), false),
SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
true),
SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true),