Skip to content

Commit

Permalink
Merge branch 'coredump_fixes' into 'master'
Browse files Browse the repository at this point in the history
Coredump fixes

Closes IDFGH-12775 and IDFCI-2141

See merge request espressif/esp-idf!30641
  • Loading branch information
erhankur committed May 9, 2024
2 parents 8c97b7f + 8e524d7 commit 1e90b1f
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 8 deletions.
12 changes: 10 additions & 2 deletions components/espcoredump/src/core_dump_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ static int elf_write_tasks_data(core_dump_elf_t *self)

#if CONFIG_ESP_COREDUMP_CAPTURE_DRAM
/* Only crashed task data will be saved here. The other task's data will be automatically saved within the sections */
if (esp_core_dump_get_current_task_handle() != task_iter.pxTaskHandle)
if (esp_core_dump_get_current_task_handle() == task_iter.pxTaskHandle)
#endif
{
ret = elf_save_task(self, &task_hdr);
Expand Down Expand Up @@ -916,6 +916,14 @@ static esp_err_t elf_core_dump_image_mmap(esp_partition_mmap_handle_t* core_data
return err;
}

/* Data read from the mmapped core dump partition will be garbage if flash
* encryption is enabled in hardware and core dump partition is not encrypted
*/
if (esp_flash_encryption_enabled() && !core_part->encrypted) {
ESP_COREDUMP_LOGE("Flash encryption enabled in hardware and core dump partition is not encrypted!");
return ESP_ERR_NOT_SUPPORTED;
}

/* map the full core dump partition, including the checksum. */
return esp_partition_mmap(core_part, 0, out_size, ESP_PARTITION_MMAP_DATA,
map_addr, core_data_handle);
Expand All @@ -925,7 +933,7 @@ static void elf_parse_version_info(esp_core_dump_summary_t *summary, void *data)
{
core_dump_elf_version_info_t *version = (core_dump_elf_version_info_t *)data;
summary->core_dump_version = version->version;
memcpy(summary->app_elf_sha256, version->app_elf_sha256, ELF_APP_SHA256_SIZE);
memcpy(summary->app_elf_sha256, version->app_elf_sha256, sizeof(summary->app_elf_sha256));
ESP_COREDUMP_LOGD("Core dump version 0x%x", summary->core_dump_version);
ESP_COREDUMP_LOGD("App ELF SHA2 %s", (char *)summary->app_elf_sha256);
}
Expand Down
2 changes: 1 addition & 1 deletion tools/test_apps/system/panic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if(CONFIG_TEST_MEMPROT)
endif()
endif()

if(NOT CONFIG_TEST_MEMPROT)
if(NOT CONFIG_TEST_MEMPROT AND NOT CONFIG_ESP_COREDUMP_CAPTURE_DRAM)
# Enable UBSAN checks
#
# shift-base sanitizer is disabled due to the following pattern found in register header files:
Expand Down
2 changes: 1 addition & 1 deletion tools/test_apps/system/panic/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ endif()

idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include"
REQUIRES spi_flash esp_psram esp_system esp_partition
REQUIRES spi_flash esp_psram esp_system esp_partition espcoredump
PRIV_REQUIRES esp_gdbstub)

target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-unused-variable"
Expand Down
7 changes: 6 additions & 1 deletion tools/test_apps/system/panic/main/include/test_panic.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -67,6 +67,11 @@ void test_illegal_access(void);

void test_capture_dram(void);

#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
void test_setup_coredump_summary(void);
void test_coredump_summary(void);
#endif

#ifdef __cplusplus
}
#endif
4 changes: 4 additions & 0 deletions tools/test_apps/system/panic/main/test_app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ void app_main(void)
HANDLE_TEST(test_name, test_assert_cache_disabled);
HANDLE_TEST(test_name, test_assert_cache_write_back_error_can_print_backtrace);
HANDLE_TEST(test_name, test_assert_cache_write_back_error_can_print_backtrace2);
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
HANDLE_TEST(test_name, test_setup_coredump_summary);
HANDLE_TEST(test_name, test_coredump_summary);
#endif
#if CONFIG_IDF_TARGET_ESP32
HANDLE_TEST(test_name, test_illegal_access);
#endif
Expand Down
33 changes: 33 additions & 0 deletions tools/test_apps/system/panic/main/test_panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "esp_flash.h"
#include "esp_system.h"
#include "spi_flash_mmap.h"
#include "esp_core_dump.h"

#include "esp_private/cache_utils.h"
#include "esp_memory_utils.h"
Expand Down Expand Up @@ -268,6 +269,38 @@ void test_ub(void)
printf("%d\n", stuff[rand()]);
}

#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
void test_setup_coredump_summary(void)
{
if (esp_core_dump_image_erase() != ESP_OK)
die("Coredump image can not be erased!");
assert(0);
}

void test_coredump_summary(void)
{
esp_core_dump_summary_t *summary = malloc(sizeof(esp_core_dump_summary_t));
if (summary) {
esp_err_t err = esp_core_dump_get_summary(summary);
if (err == ESP_OK) {
printf("App ELF file SHA256: %s\n", (char *)summary->app_elf_sha256);
printf("Crashed task: %s\n", summary->exc_task);
#if __XTENSA__
printf("Exception cause: %ld\n", summary->ex_info.exc_cause);
#else
printf("Exception cause: %ld\n", summary->ex_info.mcause);
#endif
char panic_reason[200];
err = esp_core_dump_get_panic_reason(panic_reason, sizeof(panic_reason));
if (err == ESP_OK) {
printf("Panic reason: %s\n", panic_reason);
}
}
free(summary);
}
}
#endif

/* NOTE: The following test verifies the behaviour for the
* Xtensa-specific MPU instructions (Refer WDTLB, DSYNC, WDTIB, ISYNC)
* used for memory protection.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x11000,24K,
phy_init,data,phy,,4K,
factory,app,factory,0x20000,1M,
coredump,data,coredump,,64K,encrypted
6 changes: 6 additions & 0 deletions tools/test_apps/system/panic/partitions_coredump_plain.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x11000,24K,
phy_init,data,phy,,4K,
factory,app,factory,0x20000,1M,
coredump,data,coredump,,64K,
48 changes: 47 additions & 1 deletion tools/test_apps/system/panic/pytest_panic.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@

CONFIG_CAPTURE_DRAM = [pytest.param('coredump_flash_capture_dram', marks=TARGETS_ALL)]

CONFIG_COREDUMP_SUMMARY = [pytest.param('coredump_flash_elf_sha', marks=TARGETS_ALL)]

CONFIG_COREDUMP_SUMMARY_FLASH_ENCRYPTED = [
pytest.param('coredump_flash_encrypted', marks=[pytest.mark.esp32, pytest.mark.esp32c3]),
pytest.param('coredump_flash_encrypted_coredump_plain', marks=[pytest.mark.esp32, pytest.mark.esp32c3])
]

# Panic abort information will start with this string.
PANIC_ABORT_PREFIX = 'Panic reason: '

Expand Down Expand Up @@ -957,10 +964,19 @@ def test_illegal_access(dut: PanicTestDut, config: str, test_func_name: str) ->
@pytest.mark.generic
def test_capture_dram(dut: PanicTestDut, config: str, test_func_name: str) -> None:
dut.run_test_func(test_func_name)

regex_pattern = rb'assert failed:[\s\w()]*?\s[.\w/]*\.(?:c|cpp|h|hpp):\d.*$'
dut.expect(re.compile(regex_pattern, re.MULTILINE))
if dut.is_xtensa:
dut.expect_backtrace()
else:
dut.expect_stack_dump()
dut.expect_elf_sha256()
dut.expect_none(['Guru Meditation', 'Re-entered core dump'])

dut.expect_exact('Save core dump to flash...')
dut.expect_exact('Core dump has been saved to flash.')
dut.expect('Rebooting...')

core_elf_file = dut.process_coredump_flash()
dut.start_gdb_for_coredump(core_elf_file)

Expand All @@ -973,3 +989,33 @@ def test_capture_dram(dut: PanicTestDut, config: str, test_func_name: str) -> No
if dut.target != 'esp32c2':
assert int(dut.gdb_data_eval_expr('g_rtc_data_var')) == 0x55AA
assert int(dut.gdb_data_eval_expr('g_rtc_fast_var')) == 0xAABBCCDD


def _test_coredump_summary(dut: PanicTestDut, flash_encrypted: bool, coredump_encrypted: bool) -> None:
dut.run_test_func('test_setup_coredump_summary')
dut.expect_cpu_reset()
if flash_encrypted:
dut.expect_exact('Flash encryption mode is DEVELOPMENT (not secure)')
dut.run_test_func('test_coredump_summary')
if flash_encrypted and not coredump_encrypted:
dut.expect_exact('Flash encryption enabled in hardware and core dump partition is not encrypted!')
return
dut.expect_elf_sha256('App ELF file SHA256: ')
dut.expect_exact('Crashed task: main')
if dut.is_xtensa:
dut.expect_exact('Exception cause: 29')
else:
dut.expect_exact('Exception cause: 7')
dut.expect(PANIC_ABORT_PREFIX + r'assert failed:[\s\w()]*?\s[.\w/]*\.(?:c|cpp|h|hpp):\d.*$')


@pytest.mark.generic
@pytest.mark.parametrize('config', CONFIG_COREDUMP_SUMMARY, indirect=True)
def test_coredump_summary(dut: PanicTestDut) -> None:
_test_coredump_summary(dut, False, False)


@pytest.mark.flash_encryption
@pytest.mark.parametrize('config', CONFIG_COREDUMP_SUMMARY_FLASH_ENCRYPTED, indirect=True)
def test_coredump_summary_flash_encrypted(dut: PanicTestDut, config: str) -> None:
_test_coredump_summary(dut, True, config == 'coredump_flash_encrypted')
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y
CONFIG_ESP_COREDUMP_CAPTURE_DRAM=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_capture_dram.csv"
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
15 changes: 15 additions & 0 deletions tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_encrypted
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_coredump_encrypted.csv"

CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y
CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y
CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y

CONFIG_SECURE_FLASH_ENC_ENABLED=y
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_coredump_plain.csv"

CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y
CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y
CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y

CONFIG_SECURE_FLASH_ENC_ENABLED=y
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
4 changes: 2 additions & 2 deletions tools/test_apps/system/panic/test_panic_util/panic_dut.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ def expect_cpu_reset(self) -> None:
# no digital system reset for panic handling restarts (see IDF-7255)
self.expect(r'.*rst:.*(RTC_SW_CPU_RST|SW_CPU_RESET|SW_CPU)')

def expect_elf_sha256(self) -> None:
def expect_elf_sha256(self, caption: str = 'ELF file SHA256: ') -> None:
"""Expect method for ELF SHA256 line"""
elf_sha256 = sha256(self.app.elf_file)
elf_sha256_len = int(
self.app.sdkconfig.get('CONFIG_APP_RETRIEVE_LEN_ELF_SHA', '9')
)
self.expect_exact('ELF file SHA256: ' + elf_sha256[0:elf_sha256_len])
self.expect_exact(caption + elf_sha256[0:elf_sha256_len])

def expect_coredump(self, output_file_name: str, patterns: List[Union[str, re.Pattern]]) -> None:
with open(output_file_name, 'r') as file:
Expand Down

0 comments on commit 1e90b1f

Please sign in to comment.