How to fix `definition of unknown language item 'panic_fmt'`? [duplicate] - rust

This question already has an answer here:
What is a crate attribute and where do I add it?
(1 answer)
Closed 4 years ago.
For a no_std application there are a few language items defined in lang_items.rs, one of them being the panic_fmt language item (to specify the behavior of panic! in this no_std context) defined like:
#[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt() -> ! { loop{} }
When compiling, I receive this error:
error[E0522]: definition of an unknown language item: `panic_fmt`
--> src/lang_items.rs:3:1
|
3 | #[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt() -> ! { loop{} }
| ^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `panic_fmt`
error: `#[panic_implementation]` function required, but not found
After reading RFC 2070 I learned there was a recent breaking change for no_std/embedded programs. While it's recommended that I use the #[panic_implementation] attributes, a recently added feature, I still receive an error, doing so like:
#[panic_implementation] #[no_mangle] pub extern fn panic_fmt() -> ! { loop{} }
Gives the error:
error[E0658]: #[panic_implementation] is an unstable feature (see issue #44489)
--> src/lang_items.rs:4:1
|
4 | #[panic_implementation] #[no_mangle] pub extern fn panic_fmt() -> ! { loop{} }
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(panic_implementation)] to the crate attributes to enable
Following their suggestion of adding #![feature(panic_implementation)] to the top of the lang_items.rs file doesn't seem to do the trick, as I'm getting the same error. How do I enable this unstable feature properly so that I can compile this no_std application with behavior for panic! defined?

Okay, it was a simple mistake I was making. Here is a link to the playground containing my code. First of all, I needed to add the crate attribute to the top of my crate root (which, for me, was lib.rs). lang_items.rs was just a file that was used in lib.rs like so:
#![feature(compiler_builtins_lib, lang_items, asm, panic_implementation, core_intrinsics)]
#![no_builtins]
#![no_std]
pub mod lang_items;
const GPIO_BASE: usize = 0x3F000000 + 0x200000;
const GPIO_FSEL1: *mut u32 = (GPIO_BASE + 0x04) as *mut u32;
const GPIO_SET0: *mut u32 = (GPIO_BASE + 0x1C) as *mut u32;
const GPIO_CLR0: *mut u32 = (GPIO_BASE + 0x28) as *mut u32;
#[inline(never)]
fn spin_sleep_ms(ms: usize) {
for _ in 0..(ms * 600) {
unsafe { asm!("nop" :::: "volatile"); }
}
}
#[no_mangle]
pub unsafe extern "C" fn kmain() {
// STEP 1: Set GPIO Pin 16 as output.
GPIO_FSEL1.write_volatile(0x1 << 0x12);
// STEP 2: Continuously set and clear GPIO 16.
loop {
GPIO_SET0.write_volatile(0x1 << 0x10);
spin_sleep_ms(256);
GPIO_CLR0.write_volatile(0x1 << 0x10);
spin_sleep_ms(256);
}
}

Related

How do I re-export a symbol from a crate via FFI with a different name?

I have a crate, ffizz-string, which has a number of public functions with an fz_string_ prefix. In another crate taskchampion-lib, I would like to export these same functions, but with a different prefix (tc_string_). The idea here is that ffizz-string provides some generic FFI string utilities, and the crate using those utilities wants to "rebrand" the functions to match the crate's other FFI functions.
For Rust libraries, this renaming is easy: pub use fz_string_borrow as tc_string_borrow. However, this does not seem to do the trick for exported functions. I have a few things I've tried below, and for each I looked at the resulting symbols using `nm ./target/debug/deps/libtaskchampion_lib-....rlib | grep string_borrow
#![allow(non_upper_case_globals)]
// attempt 0: demonstrate that regular function symbols appear in the nm grep
#[no_mangle]
pub unsafe extern "C" fn tc_string_borrow_0() {
todo!()
}
// result: appears in nm grep as 'tc_string_borrow_0`:
// 0000000000000000 T tc_string_borrow_0
// attempt 1: just rename using 'as'
pub use ffizz_string::fz_string_borrow as tc_string_borrow_1;
// result: appears in nm grep as 'fz_string_borrow`
// attempt 2: rename with `link_name`
// link_name only applies to foreign fns and statics
extern "C" {
#[link_name = "tc_string_borrow_2"]
pub static tc_string_borrow_2:
unsafe extern "C" fn(cstr: *const i8) -> ffizz_string::fz_string_t;
}
// result: not renamed (turns out link_name was the wrong attribute)
// attempt 3: export_name on a fn
/*
// "attribute should be applied to a free function, impl method or static"
#[export_name="tc_string_borrow_3"]
pub use ffizz_string::fz_string_borrow as tc_string_borrow_3;
*/
// result: error: attribute should be applied to a free function, impl method or static
// attempt 4: export_name on a static
#[export_name = "tc_string_borrow_4"]
pub static tc_string_borrow_4: unsafe extern "C" fn(cstr: *const i8) -> ffizz_string::fz_string_t =
ffizz_string::fz_string_borrow;
// result: compiles, but tc_string_borrow_4 is a pointer to fz_string_borrow:
// 0000000000000000 D tc_string_borrow_4
// attempt 5: export_name on a static
#[used]
pub static tc_string_borrow_5: unsafe extern "C" fn(cstr: *const i8) -> ffizz_string::fz_string_t =
ffizz_string::fz_string_borrow;
// result: not renamed
The one approach that I've found effective is to wrap the utility functions with another function:
#[inline]
pub unsafe extern "C" fn tc_string_borrow(cstr: *const i8) -> ffizz_string::fz_string_t {
ffizz_string::fz_string_borrow(cstr)
}
But this relies on the compiler to inline those cross-crate calls, and also requires reiterating the function signature. Is there a better way?

How to verify `extern "C"` definition signature matches implementation

Given the following files:
main.rs:
mod ffi;
mod impl_do_print;
fn main() {
unsafe {
ffi::do_print(42.0);
}
}
ffi.rs:
extern "C" {
pub fn do_print(x: f32);
}
impl_do_print.rs:
#[no_mangle]
pub extern "C" fn do_print(x: i32) {
println!("{}", x);
}
Obviously, the f32 of the definition and the i32 of the implementation don't match.
When I execute this, it prints:
1047505936
I understand that no_mangle is automatically considered unsafe, but is there any way I could ask the compiler to catch the mismatch, or would I have to write my own linter for this?
Usecase:
This question came up with generated FFIs. I am able to modify the implementation in any way possible, but I cannot edit the function definition, as it is generated via bindgen.
So far, two potentially viable solutions were proposed:
Use the ffi.rs to auto-generate an implementation for the method that simply forwards the call to my own implementation. That way, the compiler would catch mismatching arguments.
Use the ffi.rs to generate a type definition for the function. That way, you could write a compiler check to verify that the implementation matches the definition, like this: const _: fn_type = fn_impl.
Either way, it seems to require proc macros or an external generator.
After a little more experimenting, I managed to achieve a compile time check by utilizing a macro:
impl_do_print.rs:
#[no_mangle]
pub extern "C" fn do_print(x: i32) {
println!("{}", x);
}
macro_rules! check_implementation_type {
($t:ty, $name:ident) => {
const _: $t = $name;
const _: $t = crate::ffi::$name;
};
}
check_implementation_type!(unsafe extern "C" fn(i32), do_print);
This still requires me to write a check_implementation_type entry for every function I implement, but it gives me a reliable compile time error if either the ffi.rs or the implementation don't match:
error[E0308]: mismatched types
--> src/impl_do_print.rs:9:23
|
9 | const _: $t = crate::ffi::$name;
| ^^^^^^^^^^^^^^^^^ expected `i32`, found `f32`
...
13 | check_implementation_type!(unsafe extern "C" fn(i32), do_print);
| --------------------------------------------------------------- in this macro invocation
|
= note: expected fn pointer `unsafe extern "C" fn(i32)`
found fn item `unsafe extern "C" fn(f32) {ffi::do_print}`
= note: this error originates in the macro `check_implementation_type` (in Nightly builds, run with -Z macro-backtrace for more info)

Undefined reference to main when using Real-Time For the Masses

I'm trying to write a multi-threaded bare-metal application for the STM32F4Discovery using the Real-Time For the Masses (RTFM) crate. I've frankensteined together a minimal application from an example for the STM32F3Discovery board and this example:
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate cortex_m_semihosting;
extern crate panic_semihosting;
extern crate stm32f4;
use stm32f4::stm32f407;
use rtfm::app;
app! {
device: stm32f407,
}
fn init(_p: init::Peripherals) {
}
fn idle() -> ! {
loop {
rtfm::wfi();
}
}
I can get it to compile but linking with rust-lld fails with
= note: rust-lld: error: undefined symbol: main
I am confused because when I run cargo expand I do get a main function:
fn main() {
#![allow(path_statements)]
let init: fn(init::Peripherals) = init;
rtfm::atomic(unsafe { &mut rtfm::Threshold::new(0) },
|_t|
unsafe {
let _late_resources =
init(init::Peripherals{core:
::stm32f407::CorePeripherals::steal(),
device:
::stm32f407::Peripherals::steal(),});
});
let idle: fn() -> ! = idle;
idle();
}
I'm new to Rust (in fact I was hoping to learn the language with this project) and have no idea where the error might be located.
As you ask the compiler to not insert main, there is no main symbol in your program.
Rust uses symbol mangling so your main function doesn't have a symbol named main.
The answer depends on your contextm but generally this should do it:
#[no_mangle] // ensure that this symbol is called `main` in the output
pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
}
All additional information can be found here

Cannot implement quickchecks Arbitrary for my own type - "source trait is private"

I am using quickcheck to validate some properties of my code. At one point, I need an ASCII byte, so I tried to write an implementation of Arbitrary like this:
extern crate quickcheck;
use quickcheck::{quickcheck,Arbitrary,Gen};
#[derive(Debug,Copy,Clone)]
struct AsciiChar(u8);
impl Arbitrary for AsciiChar {
fn arbitrary<G>(g: &mut G) -> AsciiChar
where G: Gen
{
let a: u8 = g.gen_range(0, 128);
AsciiChar(a)
}
}
#[test]
fn it_works() {}
This fails with the error:
src/lib.rs:12:21: 12:40 error: source trait is private
src/lib.rs:12 let a: u8 = g.gen_range(0, 128);
^~~~~~~~~~~~~~~~~~~
Some searching led me to various bug reports (1, 2, 3, 4) that all seem to suggest I need to use the supertrait of Gen, which is rand::Rng. I updated my crates and use statements to
extern crate quickcheck;
extern crate rand;
use rand::Rng;
use quickcheck::{quickcheck,Arbitrary,Gen};
But I continue to get the same error.
I've tried with
rustc version 1.1.0-dev (b402c43f0 2015-05-07) (built 2015-05-07)
rustc 1.1.0-dev (3ca008dcf 2015-05-12) (built 2015-05-12)
I'm also using quickcheck v0.2.18
Ah, this was a tricky one. To progress in my testing, I added this hack:
impl Arbitrary for AsciiChar {
fn arbitrary<G>(g: &mut G) -> AsciiChar
where G: Gen
{
let a: u8 = Arbitrary::arbitrary(g);
AsciiChar(a % 128)
}
}
After that compiled, I got this error:
src/lib.rs:419:5: 419:23 error: use of unstable library feature 'rand': use `rand` from crates.io
src/lib.rs:419 extern crate rand;
^~~~~~~~~~~~~~~~~~
src/lib.rs:419:5: 419:23 help: add #![feature(rand)] to the crate attributes to enable
My problem was that I forgot to add rand to my Cargo.toml. I was thinking that I would just magically get the same version pulled in by quickcheck.
The ultimate problem was that I hadn't actually used the correct version of Rng, the one that Gen was a subtrait of. Very confusing!
After adding rand to my Cargo.toml, I am back in business.
That's strange. I can reproduce your initial error, but your suggested fix works for me:
extern crate quickcheck;
extern crate rand;
use quickcheck::{Arbitrary,Gen};
use rand::Rng;
#[derive(Debug,Copy,Clone)]
struct AsciiChar(u8);
impl Arbitrary for AsciiChar {
fn arbitrary<G>(g: &mut G) -> AsciiChar
where G: Gen
{
let a: u8 = g.gen_range(0, 128);
AsciiChar(a)
}
}
#[test]
fn it_works() {}
Running cargo test on both beta5 and the 2015-05-12 nightly works.

How do I access core traits like StrExt when using #![no_std]?

I'm trying to write some Rust with #![no_std] set. I am trying to iterate over a str one character at a time; however none of the usual techniques seem to work. When I try to access the characters via a function provided by str, e.g. for c in s.char_indices() or for c in s.chars() I receive the error:
type &str does not implement any method in scope named ___
My understanding was that str was a part of core and therefore any traits it implements should be available in no_std. Is there a way to access this functionality, or an alternate way to iterate over a str?
You need to import the trait to be able to call their methods, e.g.
#![no_std]
extern crate core;
use core::str::StrExt;
fn foo(s: &str) {
for c in s.char_indices() {}
}
core also provides an alternative prelude, which includes the functionality in std::prelude that is available in core. You can import it like use core::prelude::*;.
Is core::str::StrExt automatically available though? I don't have the setup to compile something with ![no_std], but I got past a few hoops in the Playpen by adding
#![no_std]
#![feature(lang_items)]
extern crate core;
use core::str::StrExt;
fn main() {
let s = "Hello";
let mut cnt = 0u8;
for c in s.chars() {
cnt += 1;
}
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }

Resources