迷你傾印是當機時的程序記憶體傾印,可用於偵錯當機原因。
本教學課程會逐步介紹偵錯工作流程,該工作流程可將 Minidump 檔案載入 然後依照偵錯步驟逐步操作,藉此瞭解 檔案內容
擷取 minidump 檔案
你可以使用 savedump
從 zxdb 中的偵錯工作階段擷取 Minidump
指令
舉例來說,如果您在 cobalt.cm
元件上使用 zxdb:
ffx component debug cobalt.cm
您應該會看到類似下方的輸出內容:
Waiting for process matching "job 20999".
Type "filter" to see the current filters.
👉 To get started, try "status" or "help".
Attached Process 1 state=Running koid=21246 name=cobalt.cm component=cobalt.cm
Loading 15 modules for cobalt.cm ...Done.
如果您想擷取迷你轉儲,請先 pause
偵錯工具:
pause
您應該會看到類似以下的輸出內容:
508 const zx_port_packet_t* packet))
509
▶ 510 BLOCKING_SYSCALL(port_wait, zx_status_t, /* no attributes */, 3, (handle, deadline, packet),
511 (_ZX_SYSCALL_ANNO(use_handle("Fuchsia")) zx_handle_t handle, zx_time_t deadline,
512 zx_port_packet_t* packet))
🛑 thread 1 $elf(SYSCALL_zx_port_wait) + 0x7 • syscalls.inc:510
使用 savedump
儲存迷你轉儲:
savedump cobalt.dump
您應該會看到類似下方的輸出內容:
Saving minidump...
Minidump written to cobalt.dump
儲存迷你轉儲記錄後,您可以退出偵錯工具:
quit
您的 minidump 現已儲存在工作目錄中。您現在可以載入 minidump 檔案並進行偵錯。
載入 Minidump 檔案並進行偵錯
無論您嘗試對元件進行偵錯的語言為何,在 zxdb 中載入及偵錯迷你傾印檔案的程序都相同。不過 每種語言要留意的事項差異
荒漠油廠
如要將 minidump 檔案載入 zxdb,您可以使用
ffx debug core
。例如,如要載入名為archivist_unittest.dump
的迷你轉儲檔案:ffx debug core archivist_unittest.dump
您應該會看到類似以下的輸出內容:
Opening dump file... Dump loaded successfully. 👉 To get started, try "status" or "help". Attached Process 1 state=Running koid=14446435 name=<_> Loading 6 modules for <_> Downloading symbols... Done. 🛑 (no location information) Attached Process 2 state=Running koid=14446435 name=<_> Attaching to previously connected processes: 14446435: <_> Loading 6 modules for <_> Done. Symbol downloading complete. 5 succeeded, 0 failed.
列出堆疊框架:
frame
您應該會看到類似以下的輸出內容:
▶ 0 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::test_entry_point::λ(…) • archivist.rs:547 1 core::future::future::«impl»::poll<…>(…) • future/future.rs:123 2 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:27 3 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:122 4 fuchsia_async::atomic_future::«impl»::poll<…>(…) • atomic_future.rs:72 5 fuchsia_async::atomic_future::AtomicFuture::try_poll(…) • atomic_future.rs:230 6 fuchsia_async::runtime::fuchsia::executor::common::Executor::try_poll(…) • executor/common.rs:554 7 fuchsia_async::runtime::fuchsia::executor::common::Executor::poll_ready_tasks(…) • executor/common.rs:133 8 fuchsia_async::runtime::fuchsia::executor::common::Executor::worker_lifecycle<…>(…) • executor/common.rs:429 9 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run<…>(…) • executor/local.rs:104 10 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run_singlethreaded<…>(…) • executor/local.rs:70 11 fuchsia_async::test_support::«impl»::run_singlethreaded::λ() • test_support.rs:120 12 fuchsia_async::test_support::Config::in_parallel(…) • test_support.rs:215 13 fuchsia_async::test_support::«impl»::run_singlethreaded(…) • test_support.rs:117 14 fuchsia_async::test_support::run_singlethreaded_test<…>(…) • test_support.rs:227 15 fuchsia::test_singlethreaded<…>(…) • fuchsia/src/lib.rs:195 16 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log() • archivist.rs:524 17 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::λ(…) • archivist.rs:525 18 core::ops::function::FnOnce::call_once<…>(…) • fuchsia-third_party-rust/library/core/src/ops/function.rs:250 19 core::ops::function::FnOnce::call_once<…>(…) • library/core/src/ops/function.rs:250 (inline) 20 test::__rust_begin_short_backtrace<…>(…) • library/test/src/lib.rs:625 21 test::run_test_in_spawned_subprocess(…) • library/test/src/lib.rs:753 22 test::test_main_static_abort(…) • library/test/src/lib.rs:199 23 archivist_lib_lib_test::main() • archivist/src/lib.rs:1 24 core::ops::function::FnOnce::call_once<…>(…) • fuchsia-third_party-rust/library/core/src/ops/function.rs:250 25 std::sys::backtrace::__rust_begin_short_backtrace<…>(…) • fuchsia-third_party-rust/library/std/src/sys/backtrace.rs:155 26 std::rt::lang_start::λ() • fuchsia-third_party-rust/library/std/src/rt.rs:159 27 core::ops::function::impls::«impl»::call_once<…>(…) • library/core/src/ops/function.rs:284 (inline) 28 std::panicking::try::do_call<…>(…) • library/std/src/panicking.rs:553 (inline) 29 std::panicking::try<…>() • library/std/src/panicking.rs:517 (inline) 30 std::panic::catch_unwind<…>() • library/std/src/panic.rs:350 (inline) 31 std::rt::lang_start_internal::λ() • library/std/src/rt.rs:141 (inline) 32 std::panicking::try::do_call<…>(…) • library/std/src/panicking.rs:553 (inline) 33 std::panicking::try<…>() • library/std/src/panicking.rs:517 (inline) 34 std::panic::catch_unwind<…>() • library/std/src/panic.rs:350 (inline) 35 std::rt::lang_start_internal(…) • library/std/src/rt.rs:141 36 std::rt::lang_start<…>(…) • fuchsia-third_party-rust/library/std/src/rt.rs:158 37 $elf(main) + 0x21 38…40 «libc startup» (-r expands)
你現在可以使用快速鍵在所有執行緒中快速執行動作。
列出每個執行緒的框架:
thread * frame
您應該會看到類似以下的輸出內容:
Thread 1 state="Core Dump" koid=14450503 name="" ▶ 0 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::test_entry_point::λ(…) • archivist.rs:547
您可以將
thread
與backtrace
動詞結合,列出每個執行緒的框架,但會提供更詳細的資訊:thread * backtrace
這個指令可協助您查看每個堆疊框架的本機變數。請注意,為了縮短擷取時間並減少擷取檔案大小,迷你轉儲檔案只會擷取堆疊記憶體。堆積變數的指標大多不會解析為任何有用的內容。
您應該會看到類似下方的輸出內容:
Thread 1 state="Core Dump" koid=14450503 name="" ▶ 0 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::test_entry_point::λ(…) • archivist.rs:547 (*)0x5c626904e0 ➔ Context{waker: (*)0x5c626904c8, local_waker: (*)0x5c626904c8, ext: AssertUnwindSafe<core::task::wake::ExtData>(…), _marker: PhantomData<fn(&())->&()>, _marker2: PhantomData<*mut()>} 1 core::future::future::«impl»::poll<…>(…) • future/future.rs:123 self = Pin<&mut core::pin::Pin<alloc…>{__pointer: (*)0xa2987a4580} cx = (*)0x5c626904e0 ➔ Context{waker: (*)0x5c626904c8, local_waker: (*)0x5c626904c8, ext: AssertUnwindSafe<core::task::wake::ExtData>(…), _marker: PhantomData<fn(&())->&()>, _marker2: PhantomData<*mut()>} 2 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:27 (*)0x5c626904e0 ➔ Context{waker: (*)0x5c626904c8, local_waker: (*)0x5c626904c8, ext: AssertUnwindSafe<core::task::wake::ExtData>(…), _marker: PhantomData<fn(&())->&()>, _marker2: PhantomData<*mut()>} 3 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:122 (*)0x5c626904e0 ➔ Context{waker: (*)0x5c626904c8, local_waker: (*)0x5c626904c8, ext: AssertUnwindSafe<core::task::wake::ExtData>(…), _marker: PhantomData<fn(&())->&()>, _marker2: PhantomData<*mut()>} 4 fuchsia_async::atomic_future::«impl»::poll<…>(…) • atomic_future.rs:72 self = (*)0xa2987a4520 cx = (*)0x5c626904e0 ➔ Context{waker: (*)0x5c626904c8, local_waker: (*)0x5c626904c8, ext: AssertUnwindSafe<core::task::wake::ExtData>(…), _marker: PhantomData<fn(&())->&()>, _marker2: PhantomData<*mut()>} 5 fuchsia_async::atomic_future::AtomicFuture::try_poll(…) • atomic_future.rs:230 self = (*)0x9d587a4118 cx = (*)0x5c626904e0 ➔ Context{waker: (*)0x5c626904c8, local_waker: (*)0x5c626904c8, ext: AssertUnwindSafe<core::task::wake::ExtData>(…), _marker: PhantomData<fn(&())->&()>, _marker2: PhantomData<*mut()>} 6 fuchsia_async::runtime::fuchsia::executor::common::Executor::try_poll(…) • executor/common.rs:554 self = (*)0x9b187a9300 task = (*)0x5c62690588 ➔ (*)0x9d587a40f0 7 fuchsia_async::runtime::fuchsia::executor::common::Executor::poll_ready_tasks(…) • executor/common.rs:133 self = (*)0x9b187a9300 local_collector = (*)0x5c62690600 ➔ LocalCollector{collector: (*)0x9b187a9438, last_ticks: 1050997948718604, polls: 1, tasks_pending_max: 10} 8 fuchsia_async::runtime::fuchsia::executor::common::Executor::worker_lifecycle<…>(…) • executor/common.rs:429 self = (*)0xa4187a90a0 9 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run<…>(…) • executor/local.rs:104 self = (*)0x5c62690878 ➔ LocalExecutor{ehandle: EHandle{…}} main_future = AtomicFuture{state: AtomicUsize{1}, future: UnsafeCell{$(alloc::boxed::Box<dyn fuchsia_async::atomic_future::FutureOrResultAccess, alloc::alloc::Global>){…}}} 10 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run_singlethreaded<…>(…) • executor/local.rs:70 self = (*)0x5c62690878 ➔ LocalExecutor{ehandle: EHandle{…}} main_future = Unresumed{run_stream: (*)0xa3187a86a0, test: λ{…}} 11 fuchsia_async::test_support::«impl»::run_singlethreaded::λ() • test_support.rs:120 12 fuchsia_async::test_support::Config::in_parallel(…) • test_support.rs:215 self = (*)0x5c62690ae8 ➔ Config{repeat_count: 1, max_concurrency: 0, max_threads: 0, timeout: …} f = <The value of type '*const alloc::sync::ArcInner<(dyn core::ops::function::Fn<(), Output=()> + core::marker::Send + core::marker::Sync)>' is the incorrect size (expecting 8, got 16). Please file a bug.> 13 fuchsia_async::test_support::«impl»::run_singlethreaded(…) • test_support.rs:117 test = <The value of type '*const alloc::sync::ArcInner<(dyn core::ops::function::Fn<(usize), Output=core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output=()>, alloc::alloc::Global>>> + core::marker::Send + core::marker::Sync)>' is the incorrect size (expecting 8, got 16). Please file a bug.> cfg = Config{repeat_count: 1, max_concurrency: 0, max_threads: 0, timeout: None<Duration>} 14 fuchsia_async::test_support::run_singlethreaded_test<…>(…) • test_support.rs:227 test = <Unavailable> 15 fuchsia::test_singlethreaded<…>(…) • fuchsia/src/lib.rs:195 f = <Register rdi not available.> 16 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log() • archivist.rs:524 17 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::λ(…) • archivist.rs:525 (*)0x5c62690bde ➔ λ 18 core::ops::function::FnOnce::call_once<…>(…) • fuchsia-third_party-rust/library/core/src/ops/function.rs:250 λ <Value has no data.> 19 core::ops::function::FnOnce::call_once<…>(…) • library/core/src/ops/function.rs:250 (inline) <Register rsi not available.> <Optimized out> 20 test::__rust_begin_short_backtrace<…>(…) • library/test/src/lib.rs:625 f = <Register rsi not available.> 21 test::run_test_in_spawned_subprocess(…) • library/test/src/lib.rs:753 desc = <Register rdi not available.> runnable_test = Static(&core::ops::function::FnOnce::call_once<archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::{closure_env#0}, ()>) 22 test::test_main_static_abort(…) • library/test/src/lib.rs:199 tests = <Unavailable> 23 archivist_lib_lib_test::main() • archivist/src/lib.rs:1 24 core::ops::function::FnOnce::call_once<…>(…) • fuchsia-third_party-rust/library/core/src/ops/function.rs:250 &archivist_lib_lib_test::main <Value has no data.> 25 std::sys::backtrace::__rust_begin_short_backtrace<…>(…) • fuchsia-third_party-rust/library/std/src/sys/backtrace.rs:155 f = &archivist_lib_lib_test::main 26 std::rt::lang_start::λ() • fuchsia-third_party-rust/library/std/src/rt.rs:159 27 core::ops::function::impls::«impl»::call_once<…>(…) • library/core/src/ops/function.rs:284 (inline) self = $(&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)){pointer: (*)0x5c62690f50 ➔ $((dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)), vtable = <Invalid data offset 8 in object of size 8.>} args = <Optimized out> 28 std::panicking::try::do_call<…>(…) • library/std/src/panicking.rs:553 (inline) data = <Optimized out> 29 std::panicking::try<…>() • library/std/src/panicking.rs:517 (inline) 30 std::panic::catch_unwind<…>() • library/std/src/panic.rs:350 (inline) 31 std::rt::lang_start_internal::λ() • library/std/src/rt.rs:141 (inline) 32 std::panicking::try::do_call<…>(…) • library/std/src/panicking.rs:553 (inline) data = <Optimized out> 33 std::panicking::try<…>() • library/std/src/panicking.rs:517 (inline) 34 std::panic::catch_unwind<…>() • library/std/src/panic.rs:350 (inline) 35 std::rt::lang_start_internal(…) • library/std/src/rt.rs:141 main = $(&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)){pointer: (*)0x5c62690f50 ➔ $((dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)), vtable: (*)0x13a66000958} argc = <Register rdx not available.> argv = <Register rcx not available.> sigpipe = <Register r8 not available.> 36 std::rt::lang_start<…>(…) • fuchsia-third_party-rust/library/std/src/rt.rs:158 main = &archivist_lib_lib_test::main argc = 2 argv = (*)0xecf9d19fb0 sigpipe = 0 37 $elf(main) + 0x21 38…40 «libc startup» (-r expands)
列出目前的執行緒:
thread
您應該會看到類似以下的輸出內容:
# state koid name ▶ 1 Core Dump 14450503
列出特定執行緒。例如
thread 1
:thread 1
您應該會看到類似以下的輸出內容:
Thread 1 state="Core Dump" koid=14450503 name=""
接著,您可以使用
frame
查看thread 1
中的這個特定堆疊框架:frame
您應該會看到類似以下的輸出內容:
▶ 0 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::test_entry_point::λ(…) • archivist.rs:547 1 core::future::future::«impl»::poll<…>(…) • future/future.rs:123 2 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:27 3 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:122 4 fuchsia_async::atomic_future::«impl»::poll<…>(…) • atomic_future.rs:72 5 fuchsia_async::atomic_future::AtomicFuture::try_poll(…) • atomic_future.rs:230 6 fuchsia_async::runtime::fuchsia::executor::common::Executor::try_poll(…) • executor/common.rs:554 7 fuchsia_async::runtime::fuchsia::executor::common::Executor::poll_ready_tasks(…) • executor/common.rs:133 8 fuchsia_async::runtime::fuchsia::executor::common::Executor::worker_lifecycle<…>(…) • executor/common.rs:429 9 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run<…>(…) • executor/local.rs:104 10 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run_singlethreaded<…>(…) • executor/local.rs:70 11 fuchsia_async::test_support::«impl»::run_singlethreaded::λ() • test_support.rs:120 12 fuchsia_async::test_support::Config::in_parallel(…) • test_support.rs:215 13 fuchsia_async::test_support::«impl»::run_singlethreaded(…) • test_support.rs:117 14 fuchsia_async::test_support::run_singlethreaded_test<…>(…) • test_support.rs:227 15 fuchsia::test_singlethreaded<…>(…) • fuchsia/src/lib.rs:195 16 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log() • archivist.rs:524 17 archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::λ(…) • archivist.rs:525 18 core::ops::function::FnOnce::call_once<…>(…) • fuchsia-third_party-rust/library/core/src/ops/function.rs:250 19 core::ops::function::FnOnce::call_once<…>(…) • library/core/src/ops/function.rs:250 (inline) 20 test::__rust_begin_short_backtrace<…>(…) • library/test/src/lib.rs:625 21 test::run_test_in_spawned_subprocess(…) • library/test/src/lib.rs:753 22 test::test_main_static_abort(…) • library/test/src/lib.rs:199 23 archivist_lib_lib_test::main() • archivist/src/lib.rs:1 24 core::ops::function::FnOnce::call_once<…>(…) • fuchsia-third_party-rust/library/core/src/ops/function.rs:250 25 std::sys::backtrace::__rust_begin_short_backtrace<…>(…) • fuchsia-third_party-rust/library/std/src/sys/backtrace.rs:155 26 std::rt::lang_start::λ() • fuchsia-third_party-rust/library/std/src/rt.rs:159 27 core::ops::function::impls::«impl»::call_once<…>(…) • library/core/src/ops/function.rs:284 (inline) 28 std::panicking::try::do_call<…>(…) • library/std/src/panicking.rs:553 (inline) 29 std::panicking::try<…>() • library/std/src/panicking.rs:517 (inline) 30 std::panic::catch_unwind<…>() • library/std/src/panic.rs:350 (inline) 31 std::rt::lang_start_internal::λ() • library/std/src/rt.rs:141 (inline) 32 std::panicking::try::do_call<…>(…) • library/std/src/panicking.rs:553 (inline) 33 std::panicking::try<…>() • library/std/src/panicking.rs:517 (inline) 34 std::panic::catch_unwind<…>() • library/std/src/panic.rs:350 (inline) 35 std::rt::lang_start_internal(…) • library/std/src/rt.rs:141 36 std::rt::lang_start<…>(…) • fuchsia-third_party-rust/library/std/src/rt.rs:158 37 $elf(main) + 0x21 38…40 «libc startup» (-r expands)
根據上一個步驟的輸出內容,您可能需要深入瞭解
frame 0
:frame 0
您應該會看到類似下方的輸出內容:
archivist_lib_lib_test::archivist::tests::can_log_and_retrieve_log::test_entry_point::λ(…) • archivist.rs:547
如要查看目前頁框的其他幾行程式碼,請使用
list
:list
您應該會看到類似下方的輸出內容:
542 543 let mut expected = vec!["my msg1".to_owned(), "my msg2".to_owned()]; 544 expected.sort(); 545 546 let mut actual = vec![recv_logs.next().await.unwrap(), recv_logs.next().await.unwrap()]; ▶ 547 actual.sort(); 548 549 assert_eq!(expected, actual); 550 551 // can log after killing log sink proxy 552 log_helper.kill_log_sink(); 553 log_helper.write_log("my msg1"); 554 log_helper.write_log("my msg2"); 555 556 assert_eq!( 557 expected,
這個框架實際上含有一些封存主義程式碼,因此您可以使用
locals
可查看這個堆疊框架中的本機變數。如要查看目前堆疊框架中的所有本機變數,請使用
locals
:locals
您應該會看到類似以下的輸出內容:
_task_context = (*)0x5c626904e0 ➔ Context{ waker: (*)0x5c626904c8 local_waker: (*)0x5c626904c8 ext: AssertUnwindSafe<core::task::wake::ExtData>(None(<Value has no data.>)) _marker: PhantomData<fn(&())->&()> _marker2: PhantomData<*mut()> } actual = <Invalid pointer 0x9c187a04e8> directory = <Invalid pointer 0x9c187a0460> expected = <Invalid pointer 0x9c187a04d0> log_helper = <Invalid pointer 0x9c187a0470> log_helper2 = <Invalid pointer 0x9c187a04c0> recv_logs = <Invalid pointer 0x9c187a0468>
接著,您可以使用
print
進一步瞭解特定變數的相關資訊。例如:print _task_context
您應該會看到類似下方的輸出內容:
(*)0x5c626904e0 ➔ Context{ waker: (*)0x5c626904c8 local_waker: (*)0x5c626904c8 ext: AssertUnwindSafe<core::task::wake::ExtData>(None(<Value has no data.>)) _marker: PhantomData<fn(&())->&()> _marker2: PhantomData<*mut()> }
您已成功載入並分析 Rust 程式碼的 Minidump。
C++
如要將 Minidump 檔案載入 zxdb,可以使用
ffx debug core
。 例如,如要載入名為cobalt_minidump.dump
的 Minidump 檔案:ffx debug core cobalt_minidump.dump
您應該會看到類似以下的輸出內容:
Opening dump file... Dump loaded successfully. 👉 To get started, try "status" or "help". Attached Process 1 state=Running koid=15650768 name=<_> Loading 15 modules for <_> ...Done. Attached Process 2 state=Running koid=15650768 name=<_> Attaching to previously connected processes: 15650768: <_> Loading 15 modules for <_> Done.
載入迷你快照檔案後,您現在可以檢查迷你快照擷取時顯示的所有執行緒的堆疊。
列出堆疊框架:
frame
您應該會看到類似下方的輸出內容:
▶ 0…4 «Waiting for event in async::Loop::Run()» (-r expands) 5 main(…) • cobalt_main.cc:349 6…8 «libc startup» (-r expands)
您現在可以使用快速鍵在所有執行緒中快速執行動作:
列出每個執行緒的框架:
thread * frame
您應該會看到類似以下的輸出內容:
Thread 1 state="Core Dump" koid=19601 name="" ▶ 0…4 «Waiting for event in async::Loop::Run()» (-r expands) 5 main(…) • cobalt_main.cc:349 6…8 «libc startup» (-r expands) Thread 2 state="Core Dump" koid=26944 name="" ▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 2 __timedwait_assign_owner(…) • __timedwait.c:23 3 __timedwait(…) • threads_impl.h:322 (inline) 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 5 std::__2::__libcpp_condvar_timedwait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:127 (inline) 6 std::__2::condition_variable::__do_timed_wait(…) • condition_variable.cpp:54 7 std::__2::condition_variable::wait_for<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:196 8 std::__2::condition_variable::__do_timed_wait<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:235 9 std::__2::condition_variable::wait_until<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:161 10 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:240 11 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:247 12 std::__2::condition_variable_any::wait_for<…>(…) • condition_variable:260 13 cobalt::local_aggregation::DelayedLocalAggregateStorage::Run(…) • delayed_local_aggregate_storage.cc:200 14 λ(…) • delayed_local_aggregate_storage.cc:45 15 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 16 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 17 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 18…19 «pthread startup» (-r expands) Thread 3 state="Core Dump" koid=26975 name="" ▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 2 __timedwait_assign_owner(…) • __timedwait.c:23 3 __timedwait(…) • threads_impl.h:322 (inline) 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 5 std::__2::__libcpp_condvar_wait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:122 (inline) 6 std::__2::condition_variable::wait(…) • condition_variable.cpp:30 7 std::__2::condition_variable_any::wait<…>(…) • condition_variable:225 8 std::__2::condition_variable_any::wait<…>(…) • condition_variable:231 9 cobalt::uploader::ShippingManager::Run(…) • shipping_manager.cc:217 10 λ(…) • shipping_manager.cc:76 11 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 12 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 13 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 14…15 «pthread startup» (-r expands) Thread 4 state="Core Dump" koid=26983 name="" ▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 2 __timedwait_assign_owner(…) • __timedwait.c:23 3 __timedwait(…) • threads_impl.h:322 (inline) 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 5 std::__2::__libcpp_condvar_timedwait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:127 (inline) 6 std::__2::condition_variable::__do_timed_wait(…) • condition_variable.cpp:54 7 std::__2::condition_variable::wait_for<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:196 8 std::__2::condition_variable::__do_timed_wait<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:235 9 std::__2::condition_variable::wait_until<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:161 10 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:240 11 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:247 12 cobalt::local_aggregation::ObservationGenerator::Run(…) • observation_generator.cc:92 13 λ(…) • observation_generator.cc:65 14 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 15 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 16 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 17…18 «pthread startup» (-r expands)
如要列出每個執行緒的幀,並提供更詳細的資訊,您可以將
thread
與backtrace
動詞結合:thread * backtrace
這個指令可協助您查看每個堆疊框架的本機變數。保留 請記住,只有堆疊記憶體會擷取至 Minidump 中,以便改善 擷取的時間和大小堆積變數的指標大多不會解析為任何實用的內容,這些指標的格式類似
<Invalid pointer 0x285f3fd5a18>
。您應該會看到類似下方的輸出內容:
Thread 1 state="Core Dump" koid=19601 name="" ▶ 0…4 «Waiting for event in async::Loop::Run()» (-r expands) 5 main(…) • cobalt_main.cc:349 argc = 2 argv = (*)0x26866821fc0 6…8 «libc startup» (-r expands) Thread 2 state="Core Dump" koid=26944 name="" ▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 value_ptr = (*)0x285f3fd5904 current_value = 2 new_futex_owner = 0 deadline = 612921722073211 2 __timedwait_assign_owner(…) • __timedwait.c:23 futex = <Register rdi not available.> val = <Register rsi not available.> clk = <Register rdx not available.> at = <Register rcx not available.> new_owner = <Register r8 not available.> 3 __timedwait(…) • threads_impl.h:322 (inline) futex = (*)0x285f3fd5904 val = 2 clk = 0 at = (*)0x285f3fd5918 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 c = (*)0x370ff24ae20 m = (*)0x3707f2b76c8 ts = (*)0x285f3fd5918 5 std::__2::__libcpp_condvar_timedwait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:127 (inline) __cv = <Register rdi not available.> __m = <Register rsi not available.> __ts = <Optimized out> 6 std::__2::condition_variable::__do_timed_wait(…) • condition_variable.cpp:54 this = <Register rdi not available.> lk = <Register rsi not available.> tp = <Register rdx not available.> 7 std::__2::condition_variable::wait_for<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:196 this = (*)0x370ff24ae20 __lk = <Invalid pointer 0x285f3fd5a18> __d = <Invalid pointer 0x285f3fd59a8> 8 std::__2::condition_variable::__do_timed_wait<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:235 this = (*)0x370ff24ae20 __lk = <Invalid pointer 0x285f3fd5a18> __tp = <Invalid pointer 0x285f3fd59b0> 9 std::__2::condition_variable::wait_until<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:161 this = (*)0x370ff24ae20 __lk = <Invalid pointer 0x285f3fd5a18> __t = <Invalid pointer 0x285f3fd5a60> 10 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:240 this = (*)0x370ff24ae20 __lock = <Invalid pointer 0x285f3fd5ab0> __t = <Invalid pointer 0x285f3fd5a60> 11 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:247 this = (*)0x370ff24ae20 __lock = <Invalid pointer 0x285f3fd5ab0> __t = <Invalid pointer 0x285f3fd5a60> __pred = <Invalid pointer 0x285f3fd5a40> 12 std::__2::condition_variable_any::wait_for<…>(…) • condition_variable:260 this = (*)0x370ff24ae20 __lock = <Invalid pointer 0x285f3fd5ab0> __d = <Invalid pointer 0x370ff24ae00> __pred = {locked_state = <Invalid pointer 0x285f3fd5ab0>} 13 cobalt::local_aggregation::DelayedLocalAggregateStorage::Run(…) • delayed_local_aggregate_storage.cc:200 this = (*)0x370ff24acf0 14 λ(…) • delayed_local_aggregate_storage.cc:45 this = (*)0x36bff27b228 15 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 __f = <Invalid pointer 0x36bff27b228> 16 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 __t = <Invalid pointer 0x36bff27b220> {} 17 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 __vp = (*)0x36bff27b220 18…19 «pthread startup» (-r expands) Thread 3 state="Core Dump" koid=26975 name="" ▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 value_ptr = (*)0x23b6ad77434 current_value = 2 new_futex_owner = 0 deadline = 9223372036854775807 2 __timedwait_assign_owner(…) • __timedwait.c:23 futex = <Register rdi not available.> val = <Register rsi not available.> clk = <Register rdx not available.> at = <Register rcx not available.> new_owner = <Register r8 not available.> 3 __timedwait(…) • threads_impl.h:322 (inline) futex = (*)0x23b6ad77434 val = 2 clk = 0 at = (*)0x0 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 c = (*)0x3673f24a610 m = (*)0x3707f2b7998 ts = (*)0x0 5 std::__2::__libcpp_condvar_wait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:122 (inline) __cv = <Register rdi not available.> __m = <Register rsi not available.> 6 std::__2::condition_variable::wait(…) • condition_variable.cpp:30 this = <Register rdi not available.> lk = <Register rsi not available.> 7 std::__2::condition_variable_any::wait<…>(…) • condition_variable:225 this = (*)0x3673f24a610 __lock = <Invalid pointer 0x23b6ad77608> 8 std::__2::condition_variable_any::wait<…>(…) • condition_variable:231 this = (*)0x3673f24a610 __lock = <Invalid pointer 0x23b6ad77608> __pred = <Invalid pointer 0x23b6ad77480> 9 cobalt::uploader::ShippingManager::Run(…) • shipping_manager.cc:217 this = (*)0x3673f24a530 10 λ(…) • shipping_manager.cc:76 this = (*)0x36bff27a7a8 11 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 __f = <Invalid pointer 0x36bff27a7a8> 12 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 __t = <Invalid pointer 0x36bff27a7a0> {} 13 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 __vp = (*)0x36bff27a7a0 14…15 «pthread startup» (-r expands) Thread 4 state="Core Dump" koid=26983 name="" ▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 value_ptr = (*)0x149c84b2bc4 current_value = 2 new_futex_owner = 0 deadline = 615784347537787 2 __timedwait_assign_owner(…) • __timedwait.c:23 futex = <Register rdi not available.> val = <Register rsi not available.> clk = <Register rdx not available.> at = <Register rcx not available.> new_owner = <Register r8 not available.> 3 __timedwait(…) • threads_impl.h:322 (inline) futex = (*)0x149c84b2bc4 val = 2 clk = 0 at = (*)0x149c84b2bd8 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 c = (*)0x3673f24b128 m = (*)0x3707f2b6548 ts = (*)0x149c84b2bd8 5 std::__2::__libcpp_condvar_timedwait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:127 (inline) __cv = <Register rdi not available.> __m = <Register rsi not available.> __ts = <Optimized out> 6 std::__2::condition_variable::__do_timed_wait(…) • condition_variable.cpp:54 this = <Register rdi not available.> lk = <Register rsi not available.> tp = <Register rdx not available.> 7 std::__2::condition_variable::wait_for<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:196 this = (*)0x3673f24b128 __lk = <Invalid pointer 0x149c84b2cd8> __d = <Invalid pointer 0x149c84b2c68> 8 std::__2::condition_variable::__do_timed_wait<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:235 this = (*)0x3673f24b128 __lk = <Invalid pointer 0x149c84b2cd8> __tp = <Invalid pointer 0x149c84b2c70> 9 std::__2::condition_variable::wait_until<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:161 this = (*)0x3673f24b128 __lk = <Invalid pointer 0x149c84b2cd8> __t = <Invalid pointer 0x3673f24b0d8> 10 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:240 this = (*)0x3673f24b128 __lock = <Invalid pointer 0x149c84b2d20> __t = <Invalid pointer 0x3673f24b0d8> 11 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:247 this = (*)0x3673f24b128 __lock = <Invalid pointer 0x149c84b2d20> __t = <Invalid pointer 0x3673f24b0d8> __pred = <Invalid pointer 0x149c84b2d00> 12 cobalt::local_aggregation::ObservationGenerator::Run(…) • observation_generator.cc:92 this = (*)0x3673f24b0a0 clock = (*)0x36bff27aaa0 13 λ(…) • observation_generator.cc:65 this = (*)0x36bff24cf68 14 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 __f = <Invalid pointer 0x36bff24cf68> 15 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 __t = <Invalid pointer 0x36bff24cf60> {} 16 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 __vp = (*)0x36bff24cf60 17…18 «pthread startup» (-r expands)
列出目前的執行緒:
thread
您應該會看到類似以下的輸出內容:
# state koid name ▶ 1 Core Dump 19601 2 Core Dump 26944 3 Core Dump 26975 4 Core Dump 26983
列出特定執行緒。例如
thread 2
:thread 2
您應該會看到類似下方的輸出內容:
Thread 2 state="Core Dump" koid=26944 name=""
接著,您可以使用
frame
查看thread 2
中的這個特定堆疊框架:frame
您應該會看到類似下方的輸出內容:
▶ 0 $elf(CODE_SYSCALL_zx_futex_wait) + 0xa • syscalls.inc:210 1 _zx_futex_wait(…) • syscalls.inc:210 2 __timedwait_assign_owner(…) • __timedwait.c:23 3 __timedwait(…) • threads_impl.h:322 (inline) 4 pthread_cond_timedwait(…) • pthread_cond_timedwait.c:78 5 std::__2::__libcpp_condvar_timedwait(…) • stage2-bins/include/c++/v1/__thread/support/pthread.h:127 (inline) 6 std::__2::condition_variable::__do_timed_wait(…) • condition_variable.cpp:54 7 std::__2::condition_variable::wait_for<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:196 8 std::__2::condition_variable::__do_timed_wait<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:235 9 std::__2::condition_variable::wait_until<…>(…) • linux-x64/include/c++/v1/__condition_variable/condition_variable.h:161 10 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:240 11 std::__2::condition_variable_any::wait_until<…>(…) • condition_variable:247 12 std::__2::condition_variable_any::wait_for<…>(…) • condition_variable:260 13 cobalt::local_aggregation::DelayedLocalAggregateStorage::Run(…) • delayed_local_aggregate_storage.cc:200 14 λ(…) • delayed_local_aggregate_storage.cc:45 15 std::__2::__invoke<…>(…) • linux-x64/include/c++/v1/__type_traits/invoke.h:150 16 std::__2::__thread_execute<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:192 17 std::__2::__thread_proxy<…>(…) • linux-x64/include/c++/v1/__thread/thread.h:201 18…19 «pthread startup» (-r expands)
列出其他特定執行緒。例如
thread 1
:thread 1
您應該會看到類似下方的輸出內容:
Thread 1 state="Core Dump" koid=19601 name=""
接著,您可以使用
frame
查看thread 1
中的這個特定堆疊框架:frame
您應該會看到類似以下的輸出內容:
▶ 0…4 «Waiting for event in async::Loop::Run()» (-r expands) 5 main(…) • cobalt_main.cc:349 6…8 «libc startup» (-r expands)
根據上一個步驟的輸出內容,您可能需要深入瞭解
frame 5
:frame 5
您應該會看到類似下方的輸出內容:
main(…) • cobalt_main.cc:349
如要查看目前頁框的其他幾行程式碼,請使用
list
:list
您應該會看到類似以下的輸出內容:
344 345 if (!app.ok()) { 346 FX_LOGS(FATAL) << "Failed to construct the cobalt app: " << app.status(); 347 } 348 inspector.Health().Ok(); ▶ 349 loop.Run(); 350 FX_LOGS(INFO) << "Cobalt will now shut down."; 351 return 0; 352 }
由於這個影格實際上包含一些程式碼,因此您可以使用
locals
查看這個堆疊影格中的本機變數。如要查看目前堆疊框架中的所有本機變數,請使用
locals
:locals
您應該會看到類似下方的輸出內容:
argc = 2 argv = (*)0x26866821fc0 command_line = <Invalid pointer 0x26866821418> context = <Invalid pointer 0x26866821100> event_aggregator_backfill_days = 2 flag_value = <Invalid pointer 0x268668211d8> initial_interval = <Invalid pointer 0x26866821138> inspector = <Invalid pointer 0x268668212f0> loop = <Invalid pointer 0x26866821108> max_bytes_per_observation_store = 215040 min_interval = <Invalid pointer 0x26866821118> require_lifecycle_service = true schedule_interval = <Invalid pointer 0x26866821140> start_event_aggregator_worker = true status = 0 (ZX_OK) storage_quotas = { per_project_reserved_bytes = 1024 total_capacity_bytes = 731136 } test_dont_backfill_empty_reports = false upload_jitter = 0.2 upload_schedule = { target_interval = {__rep_ = 3600} min_interval = {__rep_ = 10} initial_interval = {__rep_ = 60} jitter = 0.2 } use_fake_clock = false use_memory_observation_store = false
您可以使用
print
查看特定變數的詳細資訊。 例如:print upload_schedule
您應該會看到類似以下的輸出內容:
{ target_interval = {__rep_ = 3600} min_interval = {__rep_ = 10} initial_interval = {__rep_ = 60} jitter = 0.2 }
您已成功載入並分析 C++ 程式碼的 Minidump。