no_std
Executable files in the environment
Author: Wu Feixiang @Pymongo/Post editor: Zhang Handong
No_std binary
Since the author only has Linux operating system devices around, this article only discusses the executable files of Rust/C/C++ under Linux operating system no_STD
This article is more about compiling and generating a purely statically linked no_STD executable without dynamic links. It is not only the Rust standard library, but also the OPERATING system’s own C standard library
Making Our Own Executable Packer (Linux)
Before explaining how Rust compiles executables that run no_STD, let’s look at how assembly and C/C++ compile executables for no_std
Assembler language compiles executable files
X86 assembly has two main syntax, one is AT&T syntax for Unix and the other is Intel syntax for Windows
Since AT&T owns Bell LABS, which invented both the Unix operating system and the C language, both GCC and AS for Linux use AT&T assembly syntax
If you want to use Intel assembly syntax you can use LLVM or NASM tools
The assembly generated by RUSTC defaults to Intel syntax, and you can pass the LLVM parameter to ruSTC to generate assembly code for AT&T syntax
rustc –emit asm -C llvm-args=-x86-asm-syntax=att main.rs
Refer to the first section of assembly code described in the GNU Assembler Examples section of this site
Compilation runs this code in two ways:
gcc -c s.s && ld s.o && ./a.out
Or use the AS tool (GNU Assembler (GNU Binutils))
as s.s && ld s.o && ./a.out
Use the LDD tool to verify that compiled executables are statically linked (no dynamic link libraries introduced)
The disadvantage of assembly is that the code is tied to the hardware architecture. GCC compiles this assembly code with the -m32 parameter specifying that a 32-bit executable is generated
C Compiles the no_std executable
It’s easy to generate an executable without a dynamically linked library using GCC or clang’s -nostdlib parameter
[w@w-manjaro temp]$ echo "int main(){return 0; }" > main.c && gcc -nostdlib main.c && ldd ./a.out /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000 statically linkedCopy the code
C In the no_std environment, the entry function name cannot be main, should be changed to _start
[w@w-manjaro temp]$ echo "int _start(){return 0; }" > main.c && gcc -nostdlib main.c && ldd ./a.out statically linkedCopy the code
It is also possible to use GCC with the -m32 argument to generate a 32-bit executable
Note that using GCC or clang’s -nostdlib parameter on MAC or Windows might cause an error
$ clang -nostdlib c.c
ld: dynamic main executables must link with libSystem.dylib for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Copy the code
According to the Apple developer documentation, Apple does not support statically linked binaries on Mac OS X
MacOS may need special LD tools or slightly more complicated methods to compile purely statically linked executables, but that is beyond the scope of this article
Rust compiles no_STD executables
#! [no_std]
#! [no_main]
#! [feature(lang_items,asm)]
/// entry_point/start_address of process, since the linker looks for a function named `_start` by default
#[no_mangle]
extern "C" fn _start() -> ! {
exit(0); // macOS: illegal hardware instruction
}
fn exit(code: isize) -> ! {
unsafe{ asm! ("syscall".in("rax") 60.// exit
in("rdi") code, options(noreturn) ); }}#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
loop{}}Copy the code
Source code in my warehouse, Linux under the compilation method:
rustc -C link-arg=-nostartfiles main.rs
Or write the following two lines to cargo/config.toml
[target.'cfg(target_os = "linux")']
rustflags = ["-C", "link-arg=-nostartfiles"]
Copy the code
If you only compile dynamically linked libraries (cdylib) in the NO_STD environment, you do not need to add the above ruSTC parameter
Contents: Rust Chinese Collection (Rust_Magazine) march issue