From 5ff9cd495e8bf4c2bf669e97aa30b61278c874d5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 29 Jul 2020 12:20:52 +0200 Subject: [PATCH] panic: skip over the first invalid PC in case of InstrFetchProhibited InstrFetchProhibited usually occurs because of a jump to an invalid pointer. In this case, PC in the exception frame is the address of the jump destination. 'esp_ptr_executable' check in print_backtrace function recognizes the first frame as invalid, and the backtrace is interrupted. This prevents the user from finding the location where the invalid pointer is dereferenced. Bypass the 'esp_ptr_executable' check if the exception cause is InstrFetchProhibited. Update the test case to no longer ignore this issue. --- components/esp_system/port/panic_handler.c | 6 ++++-- tools/test_apps/system/panic/panic_tests.py | 7 ++----- .../system/panic/test_panic_util/test_panic_util.py | 4 ++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c index de1dd3f26e..37d334a177 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/panic_handler.c @@ -156,7 +156,9 @@ static void print_backtrace(const void *f, int core) //Check if first frame is valid bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) && - esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc))); + (esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) || + /* Ignore the first corrupted PC in case of InstrFetchProhibited */ + frame->exccause == EXCCAUSE_INSTR_PROHIBITED)); uint32_t i = ((depth <= 0) ? INT32_MAX : depth) - 1; //Account for stack frame that's already printed while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) { @@ -456,7 +458,7 @@ static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseu info->description = "Exception was unhandled."; - if (info->reason == reason[0]) { + if (frame->exccause == EXCCAUSE_ILLEGAL) { info->details = print_illegal_instruction_details; } } diff --git a/tools/test_apps/system/panic/panic_tests.py b/tools/test_apps/system/panic/panic_tests.py index e322c55583..c939f24ce5 100644 --- a/tools/test_apps/system/panic/panic_tests.py +++ b/tools/test_apps/system/panic/panic_tests.py @@ -107,10 +107,7 @@ def instr_fetch_prohibited_inner(env, test_name): with get_dut(env, test_name, "test_instr_fetch_prohibited") as dut: dut.expect_gme("InstrFetchProhibited") dut.expect_reg_dump(0) - dut.expect("Backtrace:") - # At the moment the backtrace is corrupted, need to jump over the first PC in case of InstrFetchProhibited. - # Fix this and change expect to expect_none. - dut.expect("CORRUPTED") + dut.expect_backtrace() dut.expect_elf_sha256() - dut.expect_none("Guru Meditation") + dut.expect_none("CORRUPTED", "Guru Meditation") test_common(dut, test_name) diff --git a/tools/test_apps/system/panic/test_panic_util/test_panic_util.py b/tools/test_apps/system/panic/test_panic_util/test_panic_util.py index 39f0cfda09..d50c100861 100644 --- a/tools/test_apps/system/panic/test_panic_util/test_panic_util.py +++ b/tools/test_apps/system/panic/test_panic_util/test_panic_util.py @@ -76,6 +76,10 @@ class PanicTestMixin(object): elf_sha256_len = int(sdkconfig.get("CONFIG_APP_RETRIEVE_LEN_ELF_SHA", "16")) self.expect("ELF file SHA256: " + elf_sha256[0:elf_sha256_len]) + def expect_backtrace(self): + self.expect("Backtrace:") + self.expect_none("CORRUPTED") + def __enter__(self): self._raw_data = None return self