1 /*
2  * Copyright (c) 2012-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 #include <zephyr/debug/coredump.h>
10 
11 #ifdef CONFIG_COVERAGE_DUMP
12 #include <zephyr/debug/gcov.h>
13 #endif
14 
15 struct k_thread crash_thread;
16 K_THREAD_STACK_DEFINE(crash_stack, CONFIG_MAIN_STACK_SIZE);
17 
k_sys_fatal_error_handler(unsigned int reason,const struct arch_esf * pEsf)18 void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf)
19 {
20 	ARG_UNUSED(pEsf);
21 
22 	printk("%s is expected; reason = %u; halting ...\n", __func__, reason);
23 
24 #ifdef CONFIG_COVERAGE_DUMP
25 	gcov_coverage_dump();  /* LCOV_EXCL_LINE */
26 #endif
27 	k_fatal_halt(reason);
28 }
29 
30 /* Turn off optimizations to prevent the compiler from optimizing this away
31  * due to the null pointer dereference.
32  */
func_3(uint32_t * addr)33 __no_optimization void func_3(uint32_t *addr)
34 {
35 	/* clang-format off */
36 #if defined(CONFIG_BOARD_M2GL025_MIV) || \
37 	defined(CONFIG_BOARD_HIFIVE1) || \
38 	defined(CONFIG_BOARD_HIFIVE_UNLEASHED) || \
39 	defined(CONFIG_BOARD_HIFIVE_UNMATCHED) || \
40 	defined(CONFIG_BOARD_MPFS_ICICLE) || \
41 	defined(CONFIG_BOARD_LONGAN_NANO) || \
42 	defined(CONFIG_BOARD_QEMU_XTENSA) || \
43 	defined(CONFIG_BOARD_RISCV32_VIRTUAL) || \
44 	defined(CONFIG_SOC_FAMILY_INTEL_ISH) || \
45 	defined(CONFIG_SOC_FAMILY_INTEL_ADSP) || \
46 	defined(CONFIG_SOC_FAMILY_OPENHWGROUP_CVA6)
47 	/* clang-format on */
48 	ARG_UNUSED(addr);
49 	/* Call k_panic() directly so Renode doesn't pause execution.
50 	 * Needed on ADSP as well, since null pointer derefence doesn't
51 	 * fault as the lowest memory region is writable. SOF uses k_panic
52 	 * a lot, so it's good to check that it causes a coredump.
53 	 */
54 	k_panic();
55 #elif !defined(CONFIG_CPU_CORTEX_M)
56 	/* For null pointer reference */
57 	*addr = 0;
58 #else
59 	ARG_UNUSED(addr);
60 	/* Dereferencing null-pointer in TrustZone-enabled
61 	 * builds may crash the system, so use, instead an
62 	 * undefined instruction to trigger a CPU fault.
63 	 */
64 	__asm__ volatile("udf #0" : : : );
65 #endif
66 }
67 
func_2(uint32_t * addr)68 void func_2(uint32_t *addr)
69 {
70 	func_3(addr);
71 }
72 
func_1(uint32_t * addr)73 void func_1(uint32_t *addr)
74 {
75 	func_2(addr);
76 }
77 
crash_entry(void * p1,void * p2,void * p3)78 static void crash_entry(void *p1, void *p2, void *p3)
79 {
80 	printk("Coredump: %s\n", CONFIG_BOARD);
81 
82 	func_1(0);
83 }
84 
main(void)85 int main(void)
86 {
87 	k_thread_create(&crash_thread, crash_stack, CONFIG_MAIN_STACK_SIZE, crash_entry, NULL, NULL,
88 			NULL, -1, IS_ENABLED(CONFIG_USERSPACE) ? K_USER : 0, K_NO_WAIT);
89 	return 0;
90 }
91