-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Description
The defmt
crate does deferred formatting. It does this by turning defmt::info!("Hello!")
into a static SYMBOL: u8
with the name {"package":"firmware","tag":"defmt_info","data":"Hello","disambiguator":"16563080428635778541","crate_name":"log"}
. Yes, we emit symbol names that are JSON - the GNU linker for our targets of interest doesn't mind.
However, as of nightly rust, this is broken.
A cargo bisect-rustc
lays the blame at dc0bae1db725fbba8524f195f74f680995fd549e, which is the bump to LLVM 21.
In our CI runs, we use to get a symbol called:
{"package":"firmware","tag":"defmt_info","data":"unsafe extern \"C\" fn(i32, i32, i32, i32, i32) -> i32: {}","disambiguator":"16563080428635778541","crate_name":"log"}
we now get a symbol called:
{"package":"firmware","tag":"defmt_info","data":"unsafe extern "C" fn(i32, i32, i32, i32, i32) -> i32: {}","disambiguator":"16563080428635778541","crate_name":"log"}
Note that the backslashes have gone from around the extern \"C\"
part. This causes the JSON to be invalid. The line of source code that generated this symbol was:
defmt::info!("unsafe extern \"C\" fn() -> i32: {}", unsafe_c_fn);
On stable, this expands to:
#[link_section = ".defmt,aad749f0cc6920fb"]
#[export_name = "{\"package\":\"firmware\",\"tag\":\"defmt_info\",\"data\":\"extern \\\"C\\\" fn() -> i32: {}\",\"disambiguator\":\"17031413998459764745\",\"crate_name\":\"log\"}"]
static DEFMT_LOG_STATEMENT: u8 = 0;
On nightly this expands to the same code, so it's something inside LLVM that has changed how it handles escapes in symbol names.
Is this an expected side-effect? Is this something we can fix, or were we just holding it wrong?
Not fixing this issue will break anyone using defmt
to print strings containing escaped double-quotes, which is going to hurt.
This was originally a Zulip thread at #t-compiler > defmt is broken in nightly - LLVM symbol escaping changed? @ 💬, but we think it is indeed a bug.