cargo test with no_std fails with error code 176, 160 - rust

Using the below code in main.rs, when I run cargo test it returns error code 176, when I add a test or `any statement in main function. It starts returning error code 160.
#![no_std]
#![no_main]
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(not(test))]
extern crate panic_halt;
#[no_mangle]
pub unsafe extern "C" fn main() {
}
From this link I found out, that
Exit code 176 means "Unable to install on a network drive. Select
another install location in your preferences and retry installing."
When I tried to find back trace through lldb it returned
error: invalid thread
I couldn't find any thread which mentions similar error, so asking it here.
Any help is appreciated.
Using nightly (nightly-x86_64-apple-darwin)
Thanks.

The problem is your main function, which has an invalid signature for unix platforms. It must return an i32 (or better c_int, but for simplicity we suppose they are idential).
The 176 is just some random value in the rax register when leaving the main function.
So change your main signature to:
pub unsafe extern "C" fn main() -> i32
and return a return code (e.g. 0 which means success)
or
pub unsafe extern "C" fn main() -> !
and use the exit syscall on linux (or an infinite loop on embedded systems).

Related

Trouble with POST declaration in Rust/Rocket

I am attempting to write a simple api with rocket to help myself learn rust but I have run into this error after I attempted declaring a POST route:
error: malformed attribute
--> src/main.rs:26:1
|
26 | #[post("/producers", format="application/json", data =<"prod">)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: expected syntax: #[post(key = value, ..)]
Here is the function declaration for that route:
#[post("/producers", format="application/json", data =<"producer">)]
fn post_producer(producer: Json<Producer>) -> String {
return("hello".to_string());
}
And I am importing these macros:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate rocket_contrib;
use rocket_contrib::json::Json;
I have another method declared for GET but that one works fine. I've done some research and found these examples and documentation:
https://api.rocket.rs/v0.4/rocket_codegen/attr.post.html
https://rocket.rs/v0.4/guide/requests/#format
As far as I can tell I am following the conventions mentioned in both of those pages and I'm a bit lost on where to go from here. Is there some bit of syntax or an import that I'm missing?
According to the documentation, the data parameter must have the <> inside of the quotation marks. So data="<prod>" should fix the issue.

Cannot call a function-like procedural macro: cannot be expanded to statements

I'm trying to get my head around function-like procedural macros and struggling with the basics.
For a starter, I tried to create a macro that just prints all the tokens and does nothing:
extern crate proc_macro;
extern crate syn;
use proc_macro::TokenStream;
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
println!( "{:?}", input );
TokenStream::new()
}
I then tried to use it in another binary:
extern crate rust_procmacro_test;
fn main() {
rust_procmacro_test::my_macro!( aaa );
}
When I do cargo build I get this:
Compiling rust_procmacro_test v0.1.0
Compiling procmacro_user v0.1.0
error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
--> src\main.rs:5:5
|
5 | rust_procmacro_test::my_macro!( aaa );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TokenStream [Ident { ident: "aaa", span: #0 bytes(114..117) }]
error: aborting due to previous error
It tells me that this cannot be compiled, but println inside the macro works. What is happening?
Issue #54727 is very broad and I'm not sure how it relates to this.
I'm using stable-i686-pc-windows-gnu, rustc 1.31.1 (b6c32da9b 2018-12-18).
What is happening?
While it's possible to define a function-like procedural macro in stable Rust, it's not yet possible to call one as an expression / statement. This is because there are concerns about how hygiene should be applied. There are other locations, such as in item position, where it is available:
extern crate rust_procmacro_test;
rust_procmacro_test::my_macro!( aaa );
fn main() {}
but println inside the macro works
This is probably just some laziness in the implementation — the macro is eagerly evaluated and then the feature gate is checked later. While this might be inefficient at the moment, once the feature is fully stabilized it won't matter.

What is returned when a Rust FFI function returns a struct without #[repr(C)] to C?

EDIT: It was pointed out that my example isn't complete enough to be useful. My question is resolved, but if you're interested in looking at the complete code you can see it here.
Given the following code:
#[no_mangle]
pub extern "C" fn create_acceptor() -> Acceptor {
Acceptor {}
}
pub struct Acceptor {}
If I call this from C what does it actually get? Is it a pointer? An id of some sort?
I'm currently using code like the following on the C side:
extern int create_acceptor();
int main(int argc, char **argv) {
int acceptor = create_acceptor();
return 0;
}
It seems to work fine. I'm using it like an opaque type that I pass back to Rust like acceptor_doSomething(acceptor).
But I'm confused because it doesn't seem to matter what type I use for acceptor on the C side. void* and int both behave the same. Also, the documentation seems to indicate that I should be using #[repr(C)], but it seems to work without it. Why is that?
When printing the value received on the C side, it's showing very small integers, so I'm guessing it's an id on the Rust side?
TL;DR: The example isn't a useful one and doesn't show anything.
what does it actually get? Is it a pointer? An id of some sort?
It's the struct, exactly as defined on the Rust side. It's a pointer if you return a pointer (this example does not) or an id if you return some id (this example does not).
Rust's FFI imposes no overhead or abstraction — what you return is what is returned.
the documentation seems to indicate that I should be using #[repr(C)]
Yes, you should. Without it, your code is most likely undefined behavior. The layout of a Rust struct is not yet guaranteed. Without specifying the representation as C, there's no way for the C code to know which fields are where.
but it seems to work without it
That's because your example struct has no fields and thus no size (which AFAIK isn't even valid in C without non-standard extensions). Rust basically never even needs to look at the data (what data?) so it doesn't matter what you pass back.
When printing the value received on the C side, it's showing very small integers
This is probably just junk on the stack laying around. Literally uninitialized data.
Using a struct with fields without #[repr(C)]
This is bad. Don't do it. String is a struct with non-trivial fields and it is not marked #[repr(C)].
Cargo.toml
[package]
name = "shear"
version = "0.1.0"
authors = ["An Devloper"]
[lib]
crate-type = ["cdylib"]
[dependencies]
src/lib.rs
// Don't do this, `String` isn't #[repr(C)]!
#[no_mangle]
pub extern "C" fn create_example() -> String {
String::from("hello")
}
// Don't do this, `String` isn't #[repr(C)]!
#[no_mangle]
pub extern "C" fn use_example(e: String) {
println!("{}", e);
}
main.c
extern int create_example();
extern void use_example(int example);
int main(int argc, char **argv) {
int example = create_example();
use_example(example);
}
Execution
$ cargo build
Compiling shear v0.1.0 (file:///home/ubuntu/shear)
Finished dev [unoptimized + debuginfo] target(s) in 1.02s
$ gcc -o example main.c -L target/debug/ -lshear
$ LD_LIBRARY_PATH=target/debug/ ./example
Segmentation fault
Please read the The Rust FFI Omnibus for details about how to properly transfer values across the FFI boundary. Disclaimer: I am the primary author.

LLVM produced by rustc gives error about argument type of main when run with lli

I'm trying to learn a little about the LLVM IR, particularly what exactly rustc outputs. I'm having a little bit of trouble running even a very simple case.
I put the following in a source file simple.rs:
fn main() {
let x = 7u32;
let y = x + 2;
}
and run rustc --emit llvm-ir simple.rs to get the file simple.ll, containing
; ModuleID = 'simple.cgu-0.rs'
source_filename = "simple.cgu-0.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: uwtable
define internal void #_ZN6simple4main17h8ac50d7470339b75E() unnamed_addr #0 {
start:
br label %bb1
bb1: ; preds = %start
ret void
}
define i64 #main(i64, i8**) unnamed_addr {
top:
%2 = call i64 #_ZN3std2rt10lang_start17ha09816a4e25587eaE(void ()* #_ZN6simple4main17h8ac50d7470339b75E, i64 %0, i8** %1)
ret i64 %2
}
declare i64 #_ZN3std2rt10lang_start17ha09816a4e25587eaE(void ()*, i64, i8**) unnamed_addr
attributes #0 = { uwtable }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"PIE Level", i32 2}
I then try to run this with the command
lli-3.9 -load ~/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/libstd-35ad9950c7e5074b.so simple.ll
but I get the error message
LLVM ERROR: Invalid type for first argument of main() supplied
I'm able to make a minimal reproduction of this as follows: I make a file called s2.ll, containing
define i32 #main(i64, i8**) {
ret i32 42
}
and running lli-3.9 s2.ll gives the same error message. But if I change the contents of s2.ll to
define i32 #main(i32, i8**) {
ret i32 42
}
(i.e. I've changed the type of argc in main) then lli-3.9 s2.ll runs, and echo $? reveals that it did indeed return 42.
I don't think I should have to pass in the i64 explicitly - my argument list or C strings should be put into memory somewhere and the pointer and length passed to main automatically, right? Therefore I assume that I'm doing something wrong in the way in invoke lli - but I have no idea what.
Rust marks its entry point (the function marked with #[start] attribute, by default the function lang_start in the standard library) as taking an argc parameter of type isize. This is a bug because it should have the type of a C int, so it should be 32 bits on a 64-bit platform, but isize is 64 bits. However, due to the way 64-bit calling conventions work, this happens to still work correctly. The same issue also exists for the return type.
A fix for this has been committed on 2017-10-01 and should be present in Rust 1.22.
lli is apparently more strict about checking the type of main which is why it gives the error. But if you use llc instead, it should work correctly.
To get the correct main signature, you can cancel the default main by putting #![no_main] at the top of the module, and provide your own main marked with #[no_mangle]. But note that this will skip the standard library's initialization.
#![no_main]
#[no_mangle]
pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
0
}
See also:
documentation about lang_items and disabling main
Tracking issue for #[start] feature, where some people mention isize not being correct.

How does Rust handle functions with "..." at the end of args?

I have this code:
pub type f_t =
::std::option::Option<extern "C" fn(a: ::std::os::raw::c_int, ...)>;
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct Foo {
pub f: f_t,
}
fn main() {
}
It does not compile because there is no default Clone implementation for functions with "..." at the end of args.
How does Rust handle this "..." at the end of line, does it do the same thing as "..." in C?
Rust can not compile this code, but if I comment , ..., it compiles fine. What is the difference, why does one class of function pointers implement Clone while the other does not?
How should I implement Clone for such functions?
It means approximately the same as it does in C. Rust does not have native variadic functions (you cannot implement one in Rust itself), but it supports the syntax as a special case for binding to C functions.
Rust does not know what the real signature of the C function is. So you can declare it as whatever you want, but if you get it wrong then calling the function will likely crash at runtime.
It's an unintentional omission, these function pointers are supposed to magically be Clone. On nightly and beta this is already fixed.

Resources