esp-idf: Override ESP panic print handler (IDFGH-5996)

Is your feature request related to a problem? Please describe.

We want to be able to capture all the errors/panics that occur on our ESP32 based product. Is there a way to override the panic handler so that we can redirect output to our own console/logs and also keep a count of the number of panics etc.?

Describe the solution you’d like

The panic handler provides a user hook where it passes the formatted output, which can then be printed to a console or logged somewhere or sent over a network.

Describe alternatives you’ve considered

We’ve been trying to use the linker wrap option -Wl,--wrap=panic_print_char but this seems like a major hack.

Additional context

Add any other context or screenshots about the feature request here.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (2 by maintainers)

Most upvoted comments

Hello @shreyasbharath ,

The simplest way I see to override or extend the panic handler is to wrap the panic handler function, and not panic_print_char, thanks to the linker.

I wouldn’t consider wrapping a function through the linker as a hack. After all, it is a static behavior, defined as compilation time, it is thus by definition safer than a dynamic behavior. Anyway, here is what I came up with:

In your project C file, create a wrapper for esp_panic_handler:

/* Declare the real panic handler function. We'll be able to call it after executing our custom code */
void __real_esp_panic_handler(void*);

/* This function will be considered the esp_panic_handler to call in case a panic occurs */
void __wrap_esp_panic_handler (void* info) {
    /* Custom code, count the number of panics or simply print a message */
    esp_rom_printf("Panic has been triggered by the program!\n");
    
    /* Call the original panic handler function to finish processing this error (creating a core dump for example...) */
    __real_esp_panic_handler(info);
}

Remark, this function is called after enabling the cache, so it can be placed in flash.

In the CMakeLists.txt of your project, add the following line between include($ENV{IDF_PATH}/tools/cmake/project.cmake) and project(my_super_project):

idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)

In the case of the hello-world example, it’ll look like:

# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)
project(hello_world)

Feel free to ask if you have any other question

Hi @mmoskal , I understand why one would need to do this, but the fact is this function is not meant to be wrapped. Defining it in another file would also make it non-inlinable.

One solution I can think of is force the inclusion of a header file when compiling that lib in order to make panic_print_char() weak. Then, in your main component you will be able to define a strong panic_print_char() function. All the references to panic_print_char() would then result to your function instead of the weak one.

To do so, I will take the get_started/hello_world example. In its CMakeLists.txt file, add the following line at the end:

set_target_properties("__idf_esp_system" PROPERTIES COMPILE_FLAGS "-include ../weakprint.h")

Near CMakeLists.txt file, define weakprint.h, as:

#pragma weak panic_print_char

In main/hello_world_main.c, you can now define:

void panic_print_char (const char c) {
    /* Custom code, count the number of panics or simply print a message */
    esp_rom_printf("Panic has been triggered by the program!\n");
}

This is not equivalent to wrapping because you do have access to the weak function, but at least now it will replace all the occurences of panic_print_char, even in esp_system component (where panic.c is part of)

@shreyasbharath Glad it worked for you!

Do you mean documentation for wrapping any function from ESP-IDF or wrapping this panic function in particular?

Thank you for responding so quickly @o-marshmallow 😁

I’ll try this out and report back.