summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hughes <tomhughes@chromium.org>2022-11-04 14:03:22 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-11-09 01:30:35 +0000
commitc0b5a7d0405289beae2af1cd6edde3a0b86cec17 (patch)
tree793850631b617f756a81d4ab8f4d7326248efc96
parent50e25f8df748d1e1e0e2c25b065be3544414149c (diff)
downloadchrome-ec-c0b5a7d0405289beae2af1cd6edde3a0b86cec17.tar.gz
Makefile.toolchain: Enable -ftrapv for fingerprint boards
The "-ftrapv" flag generates an exception for *signed* integer overflow: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html. This commit adds a unit test to verify the behavior. For now this is clang-only, since the gcc toolchain is missing the "trapping arithmetic functions": __addvsi3, __subvsi3, etc. https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html BRANCH=none BUG=b:144957935, b:258074414 TEST=./test/run_device_tests.py --board dartmonkey -t ftrapv TEST=./test/run_device_tests.py --board bloonchipper -t ftrapv Signed-off-by: Tom Hughes <tomhughes@chromium.org> Change-Id: I2235c2d289bab2a17d7915978c17aaa07302403d Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4007158 Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Reviewed-by: Andrea Grandi <agrandi@google.com>
-rw-r--r--Makefile.toolchain4
-rw-r--r--board/hatch_fp/build.mk1
-rw-r--r--board/nocturne_fp/build.mk1
-rw-r--r--include/test_util.h1
-rw-r--r--test/build.mk1
-rw-r--r--test/ftrapv.c265
-rw-r--r--test/ftrapv.tasklist10
-rwxr-xr-xtest/run_device_tests.py1
8 files changed, 283 insertions, 1 deletions
diff --git a/Makefile.toolchain b/Makefile.toolchain
index 30d0fe7418..181888ed8c 100644
--- a/Makefile.toolchain
+++ b/Makefile.toolchain
@@ -47,6 +47,8 @@ ifeq ($(filter $(BOARD), $(CLANG_BOARDS)), $(BOARD))
CC=clang
USE_BUILTIN_STDLIB:=0
USE_CXX_COMPILER:=1
+# b/144957935: Generate exception on signed integer overflow.
+COMMON_WARN+=-ftrapv
endif
ifeq ($(USE_CXX_COMPILER), 1)
@@ -113,7 +115,7 @@ endif
C_WARN = -Wstrict-prototypes -Wdeclaration-after-statement -Wno-pointer-sign
C_WARN += -Werror-implicit-function-declaration
-COMMON_WARN = -Wall -Wundef \
+COMMON_WARN += -Wall -Wundef \
-Wno-trigraphs -Wno-format-security -Wno-address-of-packed-member \
-fno-common -fno-strict-aliasing -fno-strict-overflow -Wimplicit-fallthrough
# See https://www.chromium.org/chromium-os/build/c-exception-support
diff --git a/board/hatch_fp/build.mk b/board/hatch_fp/build.mk
index 17e85cfb05..541ac5f198 100644
--- a/board/hatch_fp/build.mk
+++ b/board/hatch_fp/build.mk
@@ -40,6 +40,7 @@ test-list-y=\
flash_write_protect \
fpsensor \
fpsensor_hw \
+ ftrapv \
libc_printf \
mpu \
mutex \
diff --git a/board/nocturne_fp/build.mk b/board/nocturne_fp/build.mk
index d91229c7e3..1d8e9174f7 100644
--- a/board/nocturne_fp/build.mk
+++ b/board/nocturne_fp/build.mk
@@ -40,6 +40,7 @@ test-list-y=\
flash_write_protect \
fpsensor \
fpsensor_hw \
+ ftrapv \
libc_printf \
mpu \
mutex \
diff --git a/include/test_util.h b/include/test_util.h
index 004e8aaf0d..47b73605d4 100644
--- a/include/test_util.h
+++ b/include/test_util.h
@@ -124,6 +124,7 @@ enum test_state_t {
TEST_STATE_STEP_7,
TEST_STATE_STEP_8,
TEST_STATE_STEP_9,
+ TEST_STATE_STEP_10,
TEST_STATE_PASSED,
TEST_STATE_FAILED,
};
diff --git a/test/build.mk b/test/build.mk
index eee0e86179..384ad60a59 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -198,6 +198,7 @@ fpsensor-y=fpsensor.o
fpsensor_crypto-y=fpsensor_crypto.o
fpsensor_hw-y=fpsensor_hw.o
fpsensor_state-y=fpsensor_state.o
+ftrapv-y=ftrapv.o
gyro_cal-y=gyro_cal.o gyro_cal_init_for_test.o
hooks-y=hooks.o
host_command-y=host_command.o
diff --git a/test/ftrapv.c b/test/ftrapv.c
new file mode 100644
index 0000000000..60d76d25d0
--- /dev/null
+++ b/test/ftrapv.c
@@ -0,0 +1,265 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <stdlib.h>
+
+#include "common.h"
+#include "panic.h"
+#include "system.h"
+#include "task.h"
+#include "test_util.h"
+
+/*
+ * trapping addition: __addvsi3.
+ */
+test_static int test_ftrapv_addition(void)
+{
+ int32_t test_overflow = INT32_MAX;
+ int32_t ret;
+
+ ccprintf("Testing signed integer addition overflow\n");
+ cflush();
+ ret = test_overflow + 1;
+
+ /* Should never reach this. */
+ ccprintf("ret: %d\n", ret);
+ cflush();
+
+ return EC_ERROR_UNKNOWN;
+}
+
+/*
+ * trapping subtraction: __subvsi3.
+ */
+test_static int test_ftrapv_subtraction(void)
+{
+ int32_t test_overflow = INT32_MIN;
+ int32_t ret;
+
+ ccprintf("Testing signed integer subtraction overflow\n");
+ cflush();
+ ret = test_overflow - 1;
+
+ /* Should never reach this. */
+ ccprintf("ret: %d\n", ret);
+ cflush();
+
+ return EC_ERROR_UNKNOWN;
+}
+
+/*
+ * trapping multiplication: __mulvsi3.
+ */
+test_static int test_ftrapv_multiplication(void)
+{
+ int32_t test_overflow = INT32_MAX;
+ int32_t ret;
+
+ ccprintf("Testing signed integer multiplication overflow\n");
+ cflush();
+ ret = test_overflow * 2;
+
+ /* Should never reach this. */
+ ccprintf("ret: %d\n", ret);
+ cflush();
+
+ return EC_ERROR_UNKNOWN;
+}
+
+/*
+ * trapping negation: __negvsi2.
+ */
+test_static int test_ftrapv_negation(void)
+{
+ int32_t test_overflow = INT32_MIN;
+ int32_t ret;
+
+ ccprintf("Testing signed integer negation overflow\n");
+ cflush();
+ ret = -test_overflow;
+
+ /* Should never reach this. */
+ ccprintf("ret: %d\n", ret);
+ cflush();
+
+ return EC_ERROR_UNKNOWN;
+}
+
+/*
+ * trapping absolute value: __absvsi2.
+ *
+ * TODO(b/258074414): Trapping on absolute value overflow is broken in clang.
+ */
+test_static int test_ftrapv_absolute_value(void)
+{
+ int32_t test_overflow = INT32_MIN;
+ int32_t ret;
+
+ ccprintf("Testing signed integer absolute value overflow\n");
+ cflush();
+
+ ret = abs(test_overflow);
+
+ /* Should never reach this. */
+ ccprintf("ret: %d\n", ret);
+ cflush();
+
+ return EC_ERROR_UNKNOWN;
+}
+
+test_static int test_panic_data(void)
+{
+ const uint32_t expected_reason = 0;
+ const uint32_t expected_info = 0;
+ /*
+ * https://developer.arm.com/documentation/dui0552/a/the-cortex-m3-processor/exception-model/exception-types
+ */
+ const uint8_t expected_exception = 6; /* usage fault */
+
+ uint32_t reason = UINT32_MAX;
+ uint32_t info = UINT32_MAX;
+ uint8_t exception = UINT8_MAX;
+
+ panic_get_reason(&reason, &info, &exception);
+
+ TEST_EQ(reason, expected_reason, "%08x");
+ TEST_EQ(info, expected_info, "%d");
+ TEST_EQ(exception, expected_exception, "%d");
+
+ return EC_SUCCESS;
+}
+
+test_static void run_test_step1(void)
+{
+ test_set_next_step(TEST_STATE_STEP_2);
+ RUN_TEST(test_ftrapv_addition);
+}
+
+test_static void run_test_step2(void)
+{
+ RUN_TEST(test_panic_data);
+
+ if (test_get_error_count())
+ test_reboot_to_next_step(TEST_STATE_FAILED);
+ else
+ test_reboot_to_next_step(TEST_STATE_STEP_3);
+}
+
+test_static void run_test_step3(void)
+{
+ test_set_next_step(TEST_STATE_STEP_4);
+ RUN_TEST(test_ftrapv_subtraction);
+}
+
+test_static void run_test_step4(void)
+{
+ RUN_TEST(test_panic_data);
+
+ if (test_get_error_count())
+ test_reboot_to_next_step(TEST_STATE_FAILED);
+ else
+ test_reboot_to_next_step(TEST_STATE_STEP_5);
+}
+
+test_static void run_test_step5(void)
+{
+ test_set_next_step(TEST_STATE_STEP_6);
+ RUN_TEST(test_ftrapv_multiplication);
+}
+
+test_static void run_test_step6(void)
+{
+ RUN_TEST(test_panic_data);
+
+ if (test_get_error_count())
+ test_reboot_to_next_step(TEST_STATE_FAILED);
+ else
+ test_reboot_to_next_step(TEST_STATE_STEP_7);
+}
+
+test_static void run_test_step7(void)
+{
+ test_set_next_step(TEST_STATE_STEP_8);
+ RUN_TEST(test_ftrapv_negation);
+}
+
+test_static void run_test_step8(void)
+{
+ RUN_TEST(test_panic_data);
+
+ if (test_get_error_count())
+ test_reboot_to_next_step(TEST_STATE_FAILED);
+ else
+ test_reboot_to_next_step(TEST_STATE_STEP_9);
+}
+
+test_static void run_test_step9(void)
+{
+ /*
+ * TODO(b/258074414): Trapping on absolute value overflow is broken in
+ * clang, so skip the check.
+ */
+#if 0
+ test_set_next_step(TEST_STATE_STEP_10);
+ RUN_TEST(test_ftrapv_absolute_value);
+#else
+ test_reboot_to_next_step(TEST_STATE_STEP_10);
+#endif
+}
+
+test_static void run_test_step10(void)
+{
+ /*
+ * TODO(b/258074414): Trapping on absolute value overflow is broken in
+ * clang, so skip the check.
+ */
+#if 0
+ RUN_TEST(test_panic_data);
+#endif
+
+ if (test_get_error_count())
+ test_reboot_to_next_step(TEST_STATE_FAILED);
+ else
+ test_reboot_to_next_step(TEST_STATE_PASSED);
+}
+
+void test_run_step(uint32_t state)
+{
+ if (state & TEST_STATE_MASK(TEST_STATE_STEP_1)) {
+ run_test_step1();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_2)) {
+ run_test_step2();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_3)) {
+ run_test_step3();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_4)) {
+ run_test_step4();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_5)) {
+ run_test_step5();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_6)) {
+ run_test_step6();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_7)) {
+ run_test_step7();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_8)) {
+ run_test_step8();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_9)) {
+ run_test_step9();
+ } else if (state & TEST_STATE_MASK(TEST_STATE_STEP_10)) {
+ run_test_step10();
+ }
+}
+
+int task_test(void *unused)
+{
+ if (IS_ENABLED(SECTION_IS_RW))
+ test_run_multistep();
+ return EC_SUCCESS;
+}
+
+void run_test(int argc, const char **argv)
+{
+ test_reset();
+ msleep(30); /* Wait for TASK_ID_TEST to initialize */
+ task_wake(TASK_ID_TEST);
+}
diff --git a/test/ftrapv.tasklist b/test/ftrapv.tasklist
new file mode 100644
index 0000000000..273a9664c0
--- /dev/null
+++ b/test/ftrapv.tasklist
@@ -0,0 +1,10 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST \
+ TASK_TEST(TEST, task_test, NULL, TASK_STACK_SIZE)
diff --git a/test/run_device_tests.py b/test/run_device_tests.py
index cfa034ac91..0b5a291b6c 100755
--- a/test/run_device_tests.py
+++ b/test/run_device_tests.py
@@ -236,6 +236,7 @@ class AllTests:
test_name="fpsensor",
test_args=["uart"],
),
+ TestConfig(test_name="ftrapv"),
TestConfig(
test_name="libc_printf",
finish_regexes=[PRINTF_CALLED_REGEX],