Blog coding article

defmt-rtt linker error


defmt-rtt linker error

Published on 3 min read
Knurling icon
A tool set to develop embedded applications faster.
❤️ Sponsor


    Compiling a Rust project with defmt-rtt v0.3 fails with a linker error if an application author (this is you!) does not select a critical section implementation.

    To fix this do the following (taken from the critical-section docs):

    Add a dependency on a crate providing a critical section implementation. Enable the critical-section-* Cargo feature if required by the crate.

    Implementations are typically provided by either architecture-support crates (cortex-m, riscv, etc), or HAL crates.

    For example, for single-core Cortex-M targets, you can use:

    cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}

    Additionally you should update from defmt-rtt v0.3 to defmt-rtt v0.4:

    defmt-rtt = "0.4"

    See the knurling-rs/app-template as an example how the final list of dependencies may look like. See the critical-section documentation for more details on critical-section.

    Why did this happen?

    On 29.11.2022, our dependency critical-section released a patch version v0.2.8, which breaks compilation. It requires an application author to select a critical section implementation manually. See above how to do that.

    While this breaks the semver guarantees, which promise that a patch version should not break compilation, this case is a bit special. It turned out that critical-section had an unsoundness bug up to version v0.2.7, which was fixed in version v1.0.0. To push the ecosystem to stop using the unsound version, they came up with a plan consisting of two steps. Step one is to publish version v0.2.8, which internally uses version v1.1.1. Step two is to yank the unsound versions.

    Understanding the error

    The error message you get when you hit this bug is pretty long and looks pretty scary. You can scroll over it, below we will explain what it (tries to) tell you.

    $ cargo build --bin hello
       Compiling krate v0.1.0 (/home/urhengulas/Documents/
    error: linking with `flip-link` failed: exit status: 1
      = note: "flip-link" "-flavor" "gnu" "/tmp/rustcF1Rfjq/symbols.o" "/home/urhengulas/Documents/" "--as-needed" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/Documents/" "-L" "/home/urhengulas/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv7em-none-eabihf/lib" "-Bstatic" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/Documents/" "/home/urhengulas/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv7em-none-eabihf/lib/librustc_std_workspace_core-8f64384142cbfee6.rlib" "/home/urhengulas/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv7em-none-eabihf/lib/libcore-3ad9929a938dd9d2.rlib" "/home/urhengulas/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv7em-none-eabihf/lib/libcompiler_builtins-1f7e7d1541f43b6f.rlib" "-Bdynamic" "--eh-frame-hdr" "-znoexecstack" "-L" "/home/urhengulas/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/thumbv7em-none-eabihf/lib" "-o" "/home/urhengulas/Documents/" "--gc-sections" "-Tlink.x" "-Tdefmt.x" "--nmagic"
      = note: rust-lld: warning: section type mismatch for .uninit.defmt-rtt.BUFFER
              >>> /home/urhengulas/Documents/ SHT_PROGBITS
              >>> output section .uninit: SHT_NOBITS
              rust-lld: warning: section type mismatch for .got
              >>> <internal>:(.got): SHT_PROGBITS
              >>> output section .got: SHT_NOBITS
              rust-lld: warning: section type mismatch for .got.plt
              >>> <internal>:(.got.plt): SHT_PROGBITS
              >>> output section .got: SHT_NOBITS
              rust-lld: warning: section type mismatch for .got
              >>> <internal>:(.got): SHT_PROGBITS
              >>> output section .got: SHT_NOBITS
              rust-lld: error: undefined symbol: _critical_section_1_0_acquire
              >>> referenced by (/home/urhengulas/.cargo/registry/src/
              >>>               defmt_rtt-8f91bdadd9f22437.defmt_rtt.cf21a68e-cgu.0.rcgu.o:(_$LT$defmt_rtt..Logger$u20$as$u20$defmt..traits..Logger$GT$::acquire::h9d3858e61ffb8d8d) in archive /home/urhengulas/Documents/
              rust-lld: error: undefined symbol: _critical_section_1_0_release
              >>> referenced by (/home/urhengulas/.cargo/registry/src/
              >>>               defmt_rtt-8f91bdadd9f22437.defmt_rtt.cf21a68e-cgu.0.rcgu.o:(_$LT$defmt_rtt..Logger$u20$as$u20$defmt..traits..Logger$GT$::release::h9526e652a9425b09) in archive /home/urhengulas/Documents/
              flip-link: the native linker failed to link the program normally; please check your project configuration and linker scripts
    error: could not compile `krate` due to previous error

    The error tells us that "linking […] failed", which is the part of the build process that happens after each crate has been compiled into object code. Although the error message mentions flip-link, the error is related to the underlying linker that flip-link calls, as is stated by "the native linker failed to link the program normally".

    The important parts of the error are "undefined symbol: _critical_section_1_0_acquire" and "undefined symbol: _critical_section_1_0_release". critical-section works using #[no_mangle] functions, to avoid every user of a critical section (e.g. a driver) having to depend on your specific implementation (e.g. your HAL). Instead, the user (the driver) just has to depend on the critical-section crate, which assumes the existence of those two symbols, and elsewhere your dependency tree, something (typically your HAL) has to supply them.

    In version 0.2.7 of critical-section these symbols had a default implementation which just disabled interrupts, but this is not appropriate in many cases (e.g. you use the nRF Soft Device), and is unsound for multicore systems (e.g. the Raspberry Pi Silicon RP2040). Now another crate needs to implement these symbols for your system as there is no longer that unsound default implementation. The 'unsound' implementation still exists in the critical-section crate, but it's now behind a feature flag called critical-section-single-core.