parse_starnix_inspect/
lib.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use diagnostics_data::{DiagnosticsHierarchy, InspectData};
6
7#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
8pub struct CoredumpReport {
9    pub idx: usize,
10    pub thread_koid: u64,
11    pub process_koid: u64,
12    pub pid: i64,
13    pub argv: String,
14    pub thread_name: String,
15    pub uptime: i64,
16    pub signal: String,
17}
18
19impl CoredumpReport {
20    /// Returns `None` if the snapshot seems partially-written, indicating a retry is warranted.
21    ///
22    /// # Panics
23    ///
24    /// If the snapshot has the same rough structure as Starnix's inspect output but was incorrectly
25    /// recorded.
26    pub fn extract_from_snapshot(data: &InspectData) -> Option<Vec<Self>> {
27        let DiagnosticsHierarchy { name, properties, children, .. } = data
28            .payload
29            .as_ref()?
30            .get_child_by_path(&["container", "kernel", "coredumps"])
31            .cloned()?;
32        assert_eq!(name, "coredumps");
33        assert_eq!(properties, vec![]);
34
35        // Examine all of the properties and children so that we are alerted that this test code may
36        // need to be updated if coredump reports gain new information.
37        let mut reports = vec![];
38        for DiagnosticsHierarchy {
39            name: idx_str,
40            properties: coredump_properties,
41            children: coredump_children,
42            ..
43        } in children
44        {
45            assert!(
46                coredump_children.is_empty(),
47                "coredump reports aren't expected to have children, found {coredump_children:?}"
48            );
49
50            let mut argv = None;
51            let mut process_koid = None;
52            let mut thread_koid = None;
53            let mut thread_name = None;
54            let mut pid = None;
55            let mut uptime = None;
56            let mut signal = None;
57            for property in coredump_properties {
58                match property.name() {
59                    "argv" => {
60                        argv = Some(
61                            property
62                                .string()
63                                .expect("getting argv string from report node")
64                                .to_string(),
65                        )
66                    }
67                    "thread_name" => {
68                        thread_name = Some(
69                            property
70                                .string()
71                                .expect("getting thread_name string from report node")
72                                .to_string(),
73                        )
74                    }
75                    "signal" => {
76                        signal = Some(
77                            property
78                                .string()
79                                .expect("getting signal string from report node")
80                                .to_string(),
81                        )
82                    }
83                    "thread_koid" => {
84                        thread_koid =
85                            Some(property.uint().expect("getting thread koid from report node"))
86                    }
87                    "process_koid" => {
88                        process_koid =
89                            Some(property.uint().expect("getting process koid from report node"))
90                    }
91
92                    // TODO(https://fxbug.dev/42081072) i64/int in kernel shows up as u64/uint here
93                    "pid" => {
94                        pid = Some(property.uint().expect("getting pid from report node") as i64)
95                    }
96                    // TODO(https://fxbug.dev/42081072) i64/int in kernel shows up as u64/uint here
97                    "uptime" => {
98                        uptime =
99                            Some(property.uint().expect("getting uptime from report node") as i64)
100                    }
101                    other => panic!("unrecognized coredump report property `{other}`"),
102                }
103            }
104
105            reports.push(Self {
106                idx: idx_str.parse().expect("starnix coredump node names should be integers"),
107                thread_koid: thread_koid.expect("retrieving thread koid property"),
108                process_koid: process_koid.expect("retrieving process koid property"),
109                pid: pid.expect("retrieving pid property"),
110                argv: argv.expect("retrieving argv property"),
111                thread_name: thread_name.expect("retrieving thread_name property"),
112                uptime: uptime.expect("retrieving uptime property"),
113                signal: signal.expect("retrieving signal property"),
114            });
115        }
116        reports.sort();
117
118        Some(reports)
119    }
120}