diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-11-04 14:03:22 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-11-09 01:30:35 +0000 |
commit | c0b5a7d0405289beae2af1cd6edde3a0b86cec17 (patch) | |
tree | 793850631b617f756a81d4ab8f4d7326248efc96 | |
parent | 50e25f8df748d1e1e0e2c25b065be3544414149c (diff) | |
download | chrome-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.toolchain | 4 | ||||
-rw-r--r-- | board/hatch_fp/build.mk | 1 | ||||
-rw-r--r-- | board/nocturne_fp/build.mk | 1 | ||||
-rw-r--r-- | include/test_util.h | 1 | ||||
-rw-r--r-- | test/build.mk | 1 | ||||
-rw-r--r-- | test/ftrapv.c | 265 | ||||
-rw-r--r-- | test/ftrapv.tasklist | 10 | ||||
-rwxr-xr-x | test/run_device_tests.py | 1 |
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], |