esp-rs / esp-mbedtls

mbedtls for ESP32 bare-metal
Apache License 2.0
17 stars 7 forks source link

`printf` binding doesn't work for strings without arguments. #13

Closed AnthonyGrondin closed 10 months ago

AnthonyGrondin commented 1 year ago

When enabling the logging in syslog, which printf calls, by enabling the wifi-logs feature, calls to mbedtls_printf in the C library are logged as info, except for any of them that don't have arguments.

Example: This will log

mbedtls_printf("  SHA-%d test #%d: ", 512 - is384 * 128, i + 1);

This will not log

mbedtls_printf("passed\n");
bjoernQ commented 1 year ago

Mhh that's weird. I think mbedtls_printf is a C macro which calls printf from esp-wifi.

When I call printf it works so maybe there is something strange in the definition of the C macro - but there are so many conditional defines that I'm not sure what it's really calling in the end

AnthonyGrondin commented 1 year ago

I've narrowed it down a bit. The behavior is different on esp32c3 vs esp32s3. Issue was originally opened for esp32c3. So I assume this must be in the syslog() implementation from esp-wifi.

esp32c3

; it fails to print if the string ends with 1 or more \n specifically and doesn't have arguments. It works with \t. It works if \n is not the last character.

Ex:

mbedtls_printf("word-0\n");
mbedtls_printf("word-1\n ");
mbedtls_printf("word-2\n\n");
mbedtls_printf("word-3\t test");
mbedtls_printf("word-4\t");
mbedtls_printf("word-5\n newline");
mbedtls_printf("word-6");
mbedtls_printf("word-7");

Will log:

INFO - word-1

INFO - word-3    test
INFO - word-4
INFO - word-5
 newline
INFO - word-6
INFO - word-7

esp32s3

It prints newlines successfully but it doesn't handle formatting correctly.

mbedtls_printf("  SHA-%d test #%d: ", 512 - is384 * 128, i + 1);

logs

INFO -   SHA-%d test #%d: 

P.S. I wonder now, that we have a considerable amount of binding for C functions, in a few projects, if we should move them to a specific crate for that, (esp-hal-sys, esp-sys, etc.), and then we just have to import the crate, and the definition of those bindings is unified among projects. And no more double definition errors.

bjoernQ commented 1 year ago

Interesting finding. I guess that should help to track it down.

On the Xtensa targets we unfortunately still have the problem with C variadics ( https://github.com/esp-rs/esp-wifi/issues/16 ) so we currently only can print the format string.

P.S. I wonder now, that we have a considerable amount of binding for C functions, in a few projects, if we should move them to a specific crate for that, (esp-hal-sys, esp-sys, etc.), and then we just have to import the crate, and the definition of those bindings is unified among projects. And no more double definition errors.

Probably something like an "esp-c-compat" crate or similar would make sense. I think there won't be too much functions which are really worth to live there but for those who are it makes sense

bugadani commented 10 months ago

I compiled the async_client example and opened it with ghidra. It looks like parameterless prints compile down to puts, parametered ones to phy_printf (or whatever, printf, there are a few of those simplified to the same address).

image

Obviously the code above isn't correct, but close enough for me. Now, why puts eats the strings, is probably because it outputs with trace! instead of info!