• 初识rust



    调试下rust 的执行流程

    参考:

    认识 Cargo - Rust语言圣经(Rust Course)

    新建一个hello world 程序:

    1. fn main() {
    2. println!("Hello, world!");
    3. }

    IDA 打开exe,并加载符号:

    根据字符串找到主程序入口:

    双击该符号,然后按x,快捷键,查看所有的符号引用:

    之后跳转到对应的程序位置:

    PE 起始地址为140000000

    读取"hello,world"字符的指令地址:140001040:

    使用windbg ,加载该程序,并在lea 指令的位置下断点:

    1. 0:000> kp
    2. # Child-SP RetAddr Call Site
    3. 00 000000e6`c38ff9a8 00007ff7`b2571006 hello_world!__ImageBase
    4. 01 000000e6`c38ff9b0 00007ff7`b257101c hello_world!__ImageBase
    5. 02 000000e6`c38ff9e0 00007ff7`b25736a8 hello_world!__ImageBase
    6. 03 (Inline Function) --------`-------- hello_world!std::rt::lang_start_internal::closure$2(void)+0xb [/rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs @ 148]
    7. 04 (Inline Function) --------`-------- hello_world!std::panicking::try::do_call(void)+0xb [/rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs @ 502]
    8. 05 (Inline Function) --------`-------- hello_world!std::panicking::try(void)+0xb [/rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs @ 466]
    9. 06 (Inline Function) --------`-------- hello_world!std::panic::catch_unwind(void)+0xb [/rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panic.rs @ 142]
    10. 07 000000e6`c38ffa10 00007ff7`b25710ac hello_world!std::rt::lang_start_internal(void)+0xb8 [/rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs @ 148]
    11. 08 000000e6`c38ffb10 00007ff7`b258a510 hello_world!main+0x2c
    12. 09 (Inline Function) --------`-------- hello_world!invoke_main(void)+0x22 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78]
    13. 0a 000000e6`c38ffb50 00007ffc`c2a0257d hello_world!__scrt_common_main_seh(void)+0x10c [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
    14. 0b 000000e6`c38ffb90 00007ffc`c39caa78 KERNEL32!BaseThreadInitThunk+0x1d
    15. 0c 000000e6`c38ffbc0 00000000`00000000 ntdll!RtlUserThreadStart+0x28
    1. //! Runtime services
    2. //!
    3. //! The `rt` module provides a narrow set of runtime services,
    4. //! including the global heap (exported in `heap`) and unwinding and
    5. //! backtrace support. The APIs in this module are highly unstable,
    6. //! and should be considered as private implementation details for the
    7. //! time being.
    8. #![unstable(
    9. feature = "rt",
    10. reason = "this public module should not exist and is highly likely \
    11. to disappear",
    12. issue = "none"
    13. )]
    14. #![doc(hidden)]
    15. #![deny(unsafe_op_in_unsafe_fn)]
    16. #![allow(unused_macros)]
    17. use crate::ffi::CString;
    18. // Re-export some of our utilities which are expected by other crates.
    19. pub use crate::panicking::{begin_panic, panic_count};
    20. pub use core::panicking::{panic_display, panic_fmt};
    21. use crate::sync::Once;
    22. use crate::sys;
    23. use crate::sys_common::thread_info;
    24. use crate::thread::Thread;
    25. // Prints to the "panic output", depending on the platform this may be:
    26. // - the standard error output
    27. // - some dedicated platform specific output
    28. // - nothing (so this macro is a no-op)
    29. macro_rules! rtprintpanic {
    30. ($($t:tt)*) => {
    31. if let Some(mut out) = crate::sys::stdio::panic_output() {
    32. let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
    33. }
    34. }
    35. }
    36. macro_rules! rtabort {
    37. ($($t:tt)*) => {
    38. {
    39. rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*));
    40. crate::sys::abort_internal();
    41. }
    42. }
    43. }
    44. macro_rules! rtassert {
    45. ($e:expr) => {
    46. if !$e {
    47. rtabort!(concat!("assertion failed: ", stringify!($e)));
    48. }
    49. };
    50. }
    51. macro_rules! rtunwrap {
    52. ($ok:ident, $e:expr) => {
    53. match $e {
    54. $ok(v) => v,
    55. ref err => {
    56. let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug
    57. rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
    58. }
    59. }
    60. };
    61. }
    62. // One-time runtime initialization.
    63. // Runs before `main`.
    64. // SAFETY: must be called only once during runtime initialization.
    65. // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
    66. //
    67. // # The `sigpipe` parameter
    68. //
    69. // Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to
    70. // `SIG_IGN`. Applications have good reasons to want a different behavior
    71. // though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that
    72. // can be used to select how `SIGPIPE` shall be setup (if changed at all) before
    73. // `fn main()` is called. See
    74. // for more info.
    75. //
    76. // The `sigpipe` parameter to this function gets its value via the code that
    77. // rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for
    78. // all platforms and not only Unix, is because std is not allowed to have `cfg`
    79. // directives as this high level. See the module docs in
    80. // `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe`
    81. // has a value, but its value is ignored.
    82. //
    83. // Even though it is an `u8`, it only ever has 4 values. These are documented in
    84. // `compiler/rustc_session/src/config/sigpipe.rs`.
    85. #[cfg_attr(test, allow(dead_code))]
    86. unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
    87. unsafe {
    88. sys::init(argc, argv, sigpipe);
    89. let main_guard = sys::thread::guard::init();
    90. // Next, set up the current Thread with the guard information we just
    91. // created. Note that this isn't necessary in general for new threads,
    92. // but we just do this to name the main thread and to give it correct
    93. // info about the stack bounds.
    94. let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main"))));
    95. thread_info::set(main_guard, thread);
    96. }
    97. }
    98. // One-time runtime cleanup.
    99. // Runs after `main` or at program exit.
    100. // NOTE: this is not guaranteed to run, for example when the program aborts.
    101. pub(crate) fn cleanup() {
    102. static CLEANUP: Once = Once::new();
    103. CLEANUP.call_once(|| unsafe {
    104. // Flush stdout and disable buffering.
    105. crate::io::cleanup();
    106. // SAFETY: Only called once during runtime cleanup.
    107. sys::cleanup();
    108. });
    109. }
    110. // To reduce the generated code of the new `lang_start`, this function is doing
    111. // the real work.
    112. #[cfg(not(test))]
    113. fn lang_start_internal(
    114. main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
    115. argc: isize,
    116. argv: *const *const u8,
    117. sigpipe: u8,
    118. ) -> Result<isize, !> {
    119. use crate::{mem, panic};
    120. let rt_abort = move |e| {
    121. mem::forget(e);
    122. rtabort!("initialization or cleanup bug");
    123. };
    124. // Guard against the code called by this function from unwinding outside of the Rust-controlled
    125. // code, which is UB. This is a requirement imposed by a combination of how the
    126. // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
    127. // mechanism itself.
    128. //
    129. // There are a couple of instances where unwinding can begin. First is inside of the
    130. // `rt::init`, `rt::cleanup` and similar functions controlled by bstd. In those instances a
    131. // panic is a std implementation bug. A quite likely one too, as there isn't any way to
    132. // prevent std from accidentally introducing a panic to these functions. Another is from
    133. // user code from `main` or, more nefariously, as described in e.g. issue #86030.
    134. // SAFETY: Only called once during runtime initialization.
    135. panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?;
    136. let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
    137. .map_err(move |e| {
    138. mem::forget(e);
    139. rtabort!("drop of the panic payload panicked");
    140. });
    141. panic::catch_unwind(cleanup).map_err(rt_abort)?;
    142. ret_code
    143. }
    144. #[cfg(not(test))]
    145. #[lang = "start"]
    146. fn lang_start'static>(
    147. main: fn() -> T,
    148. argc: isize,
    149. argv: *const *const u8,
    150. sigpipe: u8,
    151. ) -> isize {
    152. let Ok(v) = lang_start_internal(
    153. &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
    154. argc,
    155. argv,
    156. sigpipe,
    157. );
    158. v
    159. }

    其核心运行时如上

    panic

    看起来是利用panic 库进行一些基本的异常捕获与异常处理。

    panic! 深入剖析 - Rust语言圣经(Rust Course)

    实验:

    主动 异常
    1. fn main() {
    2. panic!("crash and burn");
    3. }
    1. PS E:\learn\rust\panic_test> $env:RUST_BACKTRACE="full" ; cargo run release
    2. Compiling panic_test v0.1.0 (E:\learn\rust\panic_test)
    3. Finished dev [unoptimized + debuginfo] target(s) in 0.18s
    4. Running `target\debug\panic_test.exe release`
    5. thread 'main' panicked at src\main.rs:2:5:
    6. crash and burn
    7. stack backtrace:
    8. 0: 0x7ff7a439709a - std::sys_common::backtrace::_print::impl$0::fmt
    9. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:44
    10. 1: 0x7ff7a43a52db - core::fmt::rt::Argument::fmt
    11. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\fmt\rt.rs:138
    12. 2: 0x7ff7a43a52db - core::fmt::write
    13. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\fmt\mod.rs:1094
    14. 3: 0x7ff7a43953d1 - std::io::Write::write_fmt
    15. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\io\mod.rs:1714
    16. 4: 0x7ff7a4396e1a - std::sys_common::backtrace::_print
    17. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:47
    18. 5: 0x7ff7a4396e1a - std::sys_common::backtrace::print
    19. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:34
    20. 6: 0x7ff7a4398e4a - std::panicking::default_hook::closure$1
    21. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:270
    22. 7: 0x7ff7a4398ab8 - std::panicking::default_hook
    23. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:290
    24. 8: 0x7ff7a43994fe - std::panicking::rust_panic_with_hook
    25. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:707
    26. 9: 0x7ff7a43993aa - std::panicking::begin_panic_handler::closure$0
    27. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:597
    28. 10: 0x7ff7a4397a89 - std::sys_common::backtrace::__rust_end_short_backtrace$0,never$>
    29. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:170
    30. 11: 0x7ff7a43990f0 - std::panicking::begin_panic_handler
    31. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:595
    32. 12: 0x7ff7a43aa235 - core::panicking::panic_fmt
    33. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\panicking.rs:67
    34. 13: 0x7ff7a43910a1 - panic_test::main
    35. at E:\learn\rust\panic_test\src\main.rs:2
    36. 14: 0x7ff7a439123b - core::ops::function::FnOnce::call_once >
    37. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\core\src\ops\function.rs:250
    38. 15: 0x7ff7a439119e - std::sys_common::backtrace::__rust_begin_short_backtrace >
    39. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\sys_common\backtrace.rs:154
    40. 16: 0x7ff7a439119e - std::sys_common::backtrace::__rust_begin_short_backtrace >
    41. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\sys_common\backtrace.rs:154
    42. 17: 0x7ff7a4391061 - std::rt::lang_start::closure$0 >
    43. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\rt.rs:166
    44. 18: 0x7ff7a4393558 - std::rt::lang_start_internal::closure$2
    45. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs:148
    46. 19: 0x7ff7a4393558 - std::panicking::try::do_call
    47. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:502
    48. 20: 0x7ff7a4393558 - std::panicking::try
    49. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:466
    50. 21: 0x7ff7a4393558 - std::panic::catch_unwind
    51. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panic.rs:142
    52. 22: 0x7ff7a4393558 - std::rt::lang_start_internal
    53. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs:148
    54. 23: 0x7ff7a439103a - std::rt::lang_start >
    55. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\rt.rs:165
    56. 24: 0x7ff7a43910c9 - main
    57. 25: 0x7ff7a43a8c80 - invoke_main
    58. at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    59. 26: 0x7ff7a43a8c80 - __scrt_common_main_seh
    60. at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    61. 27: 0x7ffcc2a0257d - BaseThreadInitThunk
    62. 28: 0x7ffcc39caa78 - RtlUserThreadStart
    63. error: process didn't exit successfully: `target\debug\panic_test.exe release` (exit code: 101)
    被动 异常
    1. fn main() {
    2. let v = vec![1, 2, 3];
    3. v[99];
    4. }
    1. PS E:\learn\rust\panic_test> $env:RUST_BACKTRACE="full" ; cargo run release
    2. Finished dev [unoptimized + debuginfo] target(s) in 0.00s
    3. Running `target\debug\panic_test.exe release`
    4. thread 'main' panicked at src\main.rs:4:6:
    5. index out of bounds: the len is 3 but the index is 99
    6. stack backtrace:
    7. 0: 0x7ff75aca794a - std::sys_common::backtrace::_print::impl$0::fmt
    8. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:44
    9. 1: 0x7ff75acb5c1b - core::fmt::rt::Argument::fmt
    10. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\fmt\rt.rs:138
    11. 2: 0x7ff75acb5c1b - core::fmt::write
    12. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\fmt\mod.rs:1094
    13. 3: 0x7ff75aca5c81 - std::io::Write::write_fmt
    14. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\io\mod.rs:1714
    15. 4: 0x7ff75aca76ca - std::sys_common::backtrace::_print
    16. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:47
    17. 5: 0x7ff75aca76ca - std::sys_common::backtrace::print
    18. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:34
    19. 6: 0x7ff75aca978a - std::panicking::default_hook::closure$1
    20. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:270
    21. 7: 0x7ff75aca93f8 - std::panicking::default_hook
    22. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:290
    23. 8: 0x7ff75aca9e3e - std::panicking::rust_panic_with_hook
    24. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:707
    25. 9: 0x7ff75aca9d2d - std::panicking::begin_panic_handler::closure$0
    26. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:599
    27. 10: 0x7ff75aca8339 - std::sys_common::backtrace::__rust_end_short_backtrace$0,never$>
    28. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:170
    29. 11: 0x7ff75aca9a30 - std::panicking::begin_panic_handler
    30. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:595
    31. 12: 0x7ff75acbab75 - core::panicking::panic_fmt
    32. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\panicking.rs:67
    33. 13: 0x7ff75acbacee - core::panicking::panic_bounds_check
    34. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\panicking.rs:162
    35. 14: 0x7ff75aca1afd - core::slice::index::impl$2::index
    36. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\core\src\slice\index.rs:261
    37. 15: 0x7ff75aca1076 - alloc::vec::impl$12::index
    38. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\alloc\src\vec\mod.rs:2675
    39. 16: 0x7ff75aca1366 - panic_test::main
    40. at E:\learn\rust\panic_test\src\main.rs:4
    41. 17: 0x7ff75aca14ab - core::ops::function::FnOnce::call_once >
    42. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\core\src\ops\function.rs:250
    43. 18: 0x7ff75aca13de - std::sys_common::backtrace::__rust_begin_short_backtrace >
    44. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\sys_common\backtrace.rs:154
    45. 19: 0x7ff75aca13de - std::sys_common::backtrace::__rust_begin_short_backtrace >
    46. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\sys_common\backtrace.rs:154
    47. 20: 0x7ff75aca12e1 - std::rt::lang_start::closure$0 >
    48. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\rt.rs:166
    49. 21: 0x7ff75aca3e08 - std::rt::lang_start_internal::closure$2
    50. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs:148
    51. 22: 0x7ff75aca3e08 - std::panicking::try::do_call
    52. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:502
    53. 23: 0x7ff75aca3e08 - std::panicking::try
    54. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:466
    55. 24: 0x7ff75aca3e08 - std::panic::catch_unwind
    56. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panic.rs:142
    57. 25: 0x7ff75aca3e08 - std::rt::lang_start_internal
    58. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs:148
    59. 26: 0x7ff75aca12ba - std::rt::lang_start >
    60. at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\rt.rs:165
    61. 27: 0x7ff75aca13c9 - main
    62. 28: 0x7ff75acb95c0 - invoke_main
    63. at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    64. 29: 0x7ff75acb95c0 - __scrt_common_main_seh
    65. at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    66. 30: 0x7ffcc2a0257d - BaseThreadInitThunk
    67. 31: 0x7ffcc39caa78 - RtlUserThreadStart
    68. error: process didn't exit successfully: `target\debug\panic_test.exe release` (exit code: 101)

    可以看到,包括我们用windbg 看到的,比较完整的js 运行时的入口都看到了

     rust 程序main 入口前,就已经安装了一个默认的panic handler ,用来打印一些全局的错误信息,和堆栈列表。

    rt.rs 详解

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. char v4; // [rsp+20h] [rbp-18h]
    4. __int64 (__fastcall *v5)(); // [rsp+30h] [rbp-8h] BYREF
    5. v5 = sub_140001040;
    6. v4 = 0;
    7. return std::rt::lang_start_internal::h8a2184178aa988dc(&v5, &off_14001D360, argc, argv, v4);
    8. }

    其中,sub_140001040 即为main 函数:

     

    1. __int64 sub_140001040()
    2. {
    3. __int64 v1[3]; // [rsp+28h] [rbp-30h] BYREF
    4. __int128 v2; // [rsp+40h] [rbp-18h]
    5. v1[0] = (__int64)&off_14001D3A0;
    6. v1[1] = 1i64;
    7. v1[2] = (__int64)"called `Option::unwrap()` on a `None` value";
    8. v2 = 0i64;
    9. return std::io::stdio::_print::h445fdab5382e0576(v1);
    10. }

     

  • 相关阅读:
    Redis为什么这么快?
    小程序常用组件小结
    基于SpringBoot+MyBatisPlus+DynamicDatasource+mysql的多数据源本地事务方案
    acedGetString 函数
    记一次MySQL5初始化被kill的问题排查 | 京东云技术团队
    十三、手把手教你搭建SpringCloudAlibaba之Seata分布式事务
    对象存储?CRUD Boy实现对文件的增删改查
    U4_1:图论之DFS/BFS/TS/Scc
    《乔布斯传》英文原著重点词汇笔记(六)【 chapter four 】
    设计模式 -- 工厂模式
  • 原文地址:https://blog.csdn.net/qq_18218335/article/details/134230729