strong vApplicationStackOverflowHook

User avatar
urbanze
Posts: 295
Joined: Sat Jun 10, 2017 9:55 pm
Location: Brazil

Re: strong vApplicationStackOverflowHook

Postby urbanze » Tue May 10, 2022 5:40 pm

ESP_Sprite wrote:
Tue May 10, 2022 2:04 am
See the docs for that.
Oh, I tried "target_link_libraries" but still failing... I can't understand why :(

Let me explain better my project.

My project is created using IDF 4.0 and use various custom modules created by me. Module for network, another module for NVS, RTC, webpage and etc.

[firmware_network] module have files for control WiFi, Ethernet, MQTT and so on.
[firmware_scheduler] module have files for control relay based on unix time.

However, to keep modules independents, in MQTT.cpp, when ESP receive [MQTT_EVENT_HANDLER -> data_event], this call 2 empty weak functions (weak functions inside mqtt.cpp contain a simple print inside).
- One weak function is called in main.cpp to process json to specific board. This work.
- Another weak function is called in [firmware_scheduler] to process specific scheduler jsons, but I can't do this work correctly.

I added "target_link_libraries(${COMPONENT_LIB} INTERFACE "-u mqtt_callback_scheduler")" in [firmware_network], but fail.
I tried to add this in command in [firmware_scheduler] but fail again.

In all tests of scheduler, weak function inside of mqtt.cpp keeps in use and function defined in scheduler.cpp is never called.


mqtt.h

Code: Select all

void mqtt_callback_scheduler(char *data) __attribute__((weak));
mqtt.cpp

Code: Select all

void mqtt_callback_scheduler(char *data)
{
    ESP_LOGW(__func__, "Replace me");
}
scheduler.cpp

Code: Select all

void mqtt_callback_scheduler(char *data)
{
    ESP_LOGI(__func__, "Scheduler test");
}

ESP_Sprite
Posts: 8884
Joined: Thu Nov 26, 2015 4:08 am

Re: strong vApplicationStackOverflowHook

Postby ESP_Sprite » Wed May 11, 2022 1:22 am

No. You specifically need a *dummy function* (or symbol) to declare as undefined. It works like this.

- C compiler compiles all the objects
- Linker tries to recursively resolve all symbols (=functions and variable names that are used between functions). It starts with the assumption that there are no object files needed, but there is an unresolved symbol called 'app_main'. It searches through the objects it has until it finds it, in main.cpp. Cool, it'll include that in the binary. But now main.cpp has a bunch of unresolved symbols. It again searches throught he object files it has until it can resolve those symbols. But those files may have unresolved symbols, so it searches again, etc.
- When there are no more unresolved symbols, it will link the binary using *only the object files it needed to resolve all symbols*

The thing is, at this point the linker does not care about weak symbols that may or may not be also declared somewhere in a strong way. It takes your MQTT library thingy, sees the mqtt_callback_scheduler symbol is not undefined anymore (as that file has an internal weak symbol for it) and as such it never has an excuse to look at your scheduler file as it (presumably) only has functions in it that are otherwise declared as 'weak'. (Your main.cpp also has functions in it that actually are required to be resolved for the link to succeed, so the linker *does* take that into account.)

So how to solve it? You need to tell the linker to also take your scheduler file into account. Easiest way is to introduce an unlinked dummy symbol (which you do with the -u flag) which only can be resolved by taking the scheduler file into account. So you put '-u some_dummy_function_that_is_otherwise_entirely_unused' in the linker flags and put a corresponding 'void some_dummy_function_that_is_otherwise_entirely_unused() {}' in the C file.

User avatar
urbanze
Posts: 295
Joined: Sat Jun 10, 2017 9:55 pm
Location: Brazil

Re: strong vApplicationStackOverflowHook

Postby urbanze » Thu May 12, 2022 1:40 pm

ESP_Sprite wrote:
Wed May 11, 2022 1:22 am
No. You specifically need a *dummy function* (or symbol) to declare as undefined. It works like this.

- C compiler compiles all the objects
- Linker tries to recursively resolve all symbols (=functions and variable names that are used between functions). It starts with the assumption that there are no object files needed, but there is an unresolved symbol called 'app_main'. It searches through the objects it has until it finds it, in main.cpp. Cool, it'll include that in the binary. But now main.cpp has a bunch of unresolved symbols. It again searches throught he object files it has until it can resolve those symbols. But those files may have unresolved symbols, so it searches again, etc.
- When there are no more unresolved symbols, it will link the binary using *only the object files it needed to resolve all symbols*

The thing is, at this point the linker does not care about weak symbols that may or may not be also declared somewhere in a strong way. It takes your MQTT library thingy, sees the mqtt_callback_scheduler symbol is not undefined anymore (as that file has an internal weak symbol for it) and as such it never has an excuse to look at your scheduler file as it (presumably) only has functions in it that are otherwise declared as 'weak'. (Your main.cpp also has functions in it that actually are required to be resolved for the link to succeed, so the linker *does* take that into account.)

So how to solve it? You need to tell the linker to also take your scheduler file into account. Easiest way is to introduce an unlinked dummy symbol (which you do with the -u flag) which only can be resolved by taking the scheduler file into account. So you put '-u some_dummy_function_that_is_otherwise_entirely_unused' in the linker flags and put a corresponding 'void some_dummy_function_that_is_otherwise_entirely_unused() {}' in the C file.
It's not possible, something strange is happening. It just doesn't work. :cry: :oops: :shock:

I added dummy empty function inside scheduler files and "target_link_libraries" on [firmware_network CMakeLists], but the weak function continues to be called!

Test 1:
Added "target_link_libraries(${COMPONENT_LIB} INTERFACE "-u mqtt_callback_scheduler_dummy")" to [Firmware_network CMakeLists].
Added "void mqtt_callback_scheduler_dummy();" in [scheduler.h]
Added "void mqtt_callback_scheduler_dummy(){}" in [scheduler.cpp]

Test 2:
Remove line from [scheduler.h].

Test 3:
Change "target_link..." to [firmware_scheduler CMakeLists] rather than [firmware_network CMakeLists], but not happened.

I can compile and run all tests but none worked. In all test, weak function is called. :shock:

Note1: Inside of main.cpp, I already call one "init_scheduler()" from scheduler file and this work normally. Only the weak function inside of [firmware_network mqtt.cpp] not working to call strong function in scheduler.cpp.

Note2: In all tests, I do "idf.py fullclean".

ESP_Sprite
Posts: 8884
Joined: Thu Nov 26, 2015 4:08 am

Re: strong vApplicationStackOverflowHook

Postby ESP_Sprite » Fri May 13, 2022 1:44 am

That's odd... just to check if it's an issue with that file, can you put the strong function in main.cpp rather than an external file and see what happens? (Also, note that the dummy function doesn't need to be mentioned in the .h file as there's no other C files that need to use it.)

boarchuz
Posts: 557
Joined: Tue Aug 21, 2018 5:28 am

Re: strong vApplicationStackOverflowHook

Postby boarchuz » Fri May 13, 2022 2:30 am

I suspect mangling is ruining your day, try:

Code: Select all

extern "C" void mqtt_callback_scheduler_dummy(){}
You will likely need to add

Code: Select all

extern "C"
to the default one as well, and you might need the weak attribute in its definition.

User avatar
urbanze
Posts: 295
Joined: Sat Jun 10, 2017 9:55 pm
Location: Brazil

Re: strong vApplicationStackOverflowHook

Postby urbanze » Fri May 13, 2022 6:02 pm

ESP_Sprite wrote:
Fri May 13, 2022 1:44 am
That's odd... just to check if it's an issue with that file, can you put the strong function in main.cpp rather than an external file and see what happens? (Also, note that the dummy function doesn't need to be mentioned in the .h file as there's no other C files that need to use it.)
Putting [mqtt_callback_scheduler] in main.cpp work correctly. When drag this function to [scheduler.cpp] (with or without .h definition), never work. I really need this working :x :cry:

Firmware_network CMakeLists

Code: Select all

idf_component_register(SRCS "net_eth.c" "net_wifi.c" "net_mqtt.c" "net_ota.c" "net_common.c"
                    INCLUDE_DIRS "."
                    EMBED_FILES "certs/ca_certificate.pem" "certs/client_certificate.pem" "certs/client_private_key.pem" "certs/api-user-chain.pem" "certs/dev.cer" "certs/dev.key"
                    REQUIRES mqtt firmware_misc firmware_cjson esp_https_ota)

Firmware_scheduler CMakeLists

Code: Select all

idf_component_register(SRCS "scheduler.cpp" "relay.cpp"
                    INCLUDE_DIRS "."
                    REQUIRES firmware_misc firmware_nvs firmware_cjson firmware_network)
Last edited by urbanze on Tue May 17, 2022 8:27 pm, edited 1 time in total.

User avatar
urbanze
Posts: 295
Joined: Sat Jun 10, 2017 9:55 pm
Location: Brazil

Re: strong vApplicationStackOverflowHook

Postby urbanze » Fri May 13, 2022 6:04 pm

boarchuz wrote:
Fri May 13, 2022 2:30 am
I suspect mangling is ruining your day, try:

Code: Select all

extern "C" void mqtt_callback_scheduler_dummy(){}
You will likely need to add

Code: Select all

extern "C"
to the default one as well, and you might need the weak attribute in its definition.
I tried but doesnt work too.

ESP_Sprite
Posts: 8884
Joined: Thu Nov 26, 2015 4:08 am

Re: strong vApplicationStackOverflowHook

Postby ESP_Sprite » Sat May 14, 2022 1:46 am

And what happens if you actually call the dummy function in your main.cpp?

User avatar
urbanze
Posts: 295
Joined: Sat Jun 10, 2017 9:55 pm
Location: Brazil

Re: strong vApplicationStackOverflowHook

Postby urbanze » Tue May 17, 2022 8:29 pm

ESP_Sprite wrote:
Sat May 14, 2022 1:46 am
And what happens if you actually call the dummy function in your main.cpp?
Error. Dummy function exists only in scheduler.cpp.

Code: Select all

../main/main.cpp:20:5: error: 'mqtt_callback_scheduler_dummy' was not declared in this scope
     mqtt_callback_scheduler_dummy();
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../main/main.cpp:20:5: note: suggested alternative: 'mqtt_callback_scheduler'
     mqtt_callback_scheduler_dummy();
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     mqtt_callback_scheduler

User avatar
urbanze
Posts: 295
Joined: Sat Jun 10, 2017 9:55 pm
Location: Brazil

Re: strong vApplicationStackOverflowHook

Postby urbanze » Thu May 19, 2022 12:49 pm

any idea to solve this? I need this feature working to keep modules more independents

Who is online

Users browsing this forum: No registered users and 80 guests