Rust musl/.NET-Glibc简析

💡 原文中文,约7100字,阅读约需17分钟。
📝

内容提要

这篇文章主要讨论了rust-glibc/musl和.net-glibc的一些函数和调用过程。文章介绍了rust-glibc的_start函数和main函数的汇编代码,以及glibc-main和__libc_start_call_main函数的关系。同时,还提到了rust-musl和.net-glibc的类似情况。

🔎

延伸解读

从内核态到用户态:_start 的关键作用

文章指出,_start 是 Linux 内核态切换到用户态后执行的第一个函数。在 rust-glibc 中,_start 的汇编代码负责清空帧指针、处理参数,并将 main 函数的地址作为参数传递给 __libc_start_main。这一过程是程序启动的起点,理解它有助于把握用户态程序的初始化流程。

glibc 启动流程:__libc_start_main 与 __libc_st

文章分析了 glibc 的启动过程:_start 调用 __libc_start_main,后者进一步调用 __libc_start_call_main,最终执行用户定义的 main 函数。在 rust-glibc 中,main 函数由编译器和链接器自动生成,其汇编代码显示它调用了 std::rt::lang_start,从而进入 Rust 运行时。

musl 与 glibc 的差异:静态链接与启动函数

文章提到,rust-musl 需要指定目标 x86_64-unknown-linux-musl 进行编译。musl 将 glibc 的部分功能直接编译到最终可执行文件中,实现静态链接。在 musl 中,启动流程与 glibc 类似,但调用栈显示 __libc_start_main_stage2 和 _start_c,表明 musl 有自己的启动实现。

.NET 与 Rust 启动过程的异同

文章比较了 .NET-glibc 与 rust-glibc 的启动过程。两者都经过 _start、__libc_start_main 和 __libc_start_call_main,最终调用 main 函数。不同之处在于,.NET 的 main 函数定义在 corerun.cpp 中,而 Rust 的 main 函数由编译器生成并调用 lang_start。这反映了不同语言运行时在启动阶段的差异。

❓

Q&A

rust-glibc的_start函数有什么作用?

rust-glibc的_start函数是从Linux内核态到用户态的第一个函数,负责初始化程序的执行环境。

如何编译rust-musl项目?

要编译rust-musl项目,需要指定目标为x86_64-unknown-linux-musl,使用命令:rustup target add x86_64-unknown-linux-musl,然后使用cargo build进行编译。

.NET-glibc的main函数在哪里定义?

.NET-glibc的main函数在corerun.cpp文件中定义。

rust-musl与.net-glibc有什么相似之处?

rust-musl与.net-glibc在函数调用过程上相似,都是通过_start函数启动程序并调用main函数。

glibc-main和__libc_start_call_main函数有什么关系?

glibc-main是传递给__libc_start_call_main函数的main函数,后者负责调用用户定义的main函数并处理参数。

musl如何处理glibc的部分功能?

musl将glibc的部分功能直接编译到最终的可执行二进制文件中,从而减少了对外部glibc库的依赖。

🏷️

标签

➡️

继续阅读