From ca7c9947fc85df6dc75d2f5633fa7dd877ef6e4c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 23 Jun 2022 16:41:23 +0200 Subject: [PATCH] esp_system: fix address printed by ESP_ERROR_CHECK ...to point to the calling function, not to _esp_error_check_failed. --- components/esp_hw_support/include/esp_cpu.h | 23 +++++++++++++++++++++ components/esp_system/esp_err.c | 19 +++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index 61a4f3865f..c4d74d93e8 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -511,6 +511,29 @@ FORCE_INLINE_ATTR void esp_cpu_dbgr_break(void) #endif } +// ---------------------- Instructions ------------------------- + +/** + * @brief Given the return address, calculate the address of the preceding call instruction + * This is typically used to answer the question "where was the function called from?" + * @param return_address The value of the return address register. + * Typically set to the value of __builtin_return_address(0). + * @return Address of the call instruction preceding the return address. + */ +FORCE_INLINE_ATTR intptr_t esp_cpu_get_call_addr(intptr_t return_address) +{ + /* Both Xtensa and RISC-V have 2-byte instructions, so to get this right we + * should decode the preceding instruction as if it is 2-byte, check if it is a call, + * else treat it as 3 or 4 byte one. However for the cases where this function is + * used, being off by one instruction is usually okay, so this is kept simple for now. + */ +#ifdef __XTENSA__ + return return_address - 3; +#else + return return_address - 4; +#endif +} + /* ------------------------------------------------------ Misc --------------------------------------------------------- * * ------------------------------------------------------------------------------------------------------------------ */ diff --git a/components/esp_system/esp_err.c b/components/esp_system/esp_err.c index 2dcc3a5629..7fbaf9dcaa 100644 --- a/components/esp_system/esp_err.c +++ b/components/esp_system/esp_err.c @@ -13,13 +13,24 @@ #include "esp_rom_sys.h" -static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression) +#ifndef CONFIG_IDF_TARGET_LINUX + #include "esp_cpu.h" +#else + /* esp_cpu.h isn't available when building for Linux */ + static intptr_t esp_cpu_get_call_addr(intptr_t return_address) + { + /* on x86, there is no hope to get the address of the previous instruction */ + return return_address; + } +#endif + +static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression, intptr_t addr) { esp_rom_printf("%s failed: esp_err_t 0x%x", msg, rc); #ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP esp_rom_printf(" (%s)", esp_err_to_name(rc)); #endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP - esp_rom_printf(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3); + esp_rom_printf(" at 0x%08x\n", esp_cpu_get_call_addr(addr)); if (spi_flash_cache_enabled()) { // strings may be in flash cache esp_rom_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); } @@ -27,11 +38,11 @@ static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const ch void _esp_error_check_failed_without_abort(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - esp_error_check_failed_print("ESP_ERROR_CHECK_WITHOUT_ABORT", rc, file, line, function, expression); + esp_error_check_failed_print("ESP_ERROR_CHECK_WITHOUT_ABORT", rc, file, line, function, expression, (intptr_t)__builtin_return_address(0)); } void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - esp_error_check_failed_print("ESP_ERROR_CHECK", rc, file, line, function, expression); + esp_error_check_failed_print("ESP_ERROR_CHECK", rc, file, line, function, expression, (intptr_t)__builtin_return_address(0)); abort(); }