Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@
//! let nodes = crashlog.decode(&mut cm);
//!
//! // Get the status register of the fourth MCA bank from the register tree.
//! let status = nodes.get_by_path("core0.thread.arch_state.mca.bank3.status").unwrap();
//! let status = nodes.get_by_path(
//! "pcore.core0.thread0.thread.arch_state.mca.bank3.status"
//! ).unwrap();
//! assert_eq!(status.kind, NodeType::Field { value: 0xbe000000e1840400 });
//!
//! // Get the instruction pointer of the first core.
//! let lip = nodes.get_by_path("core0.thread.arch_state.lip").unwrap();
//! let lip = nodes.get_by_path("pcore.core0.thread0.thread.arch_state.lip").unwrap();
//! assert_eq!(lip.kind, NodeType::Field { value: 0xfffff80577036530 });
//! ```
//!
Expand Down
40 changes: 40 additions & 0 deletions lib/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,46 @@ impl Node {
Some(ptr)
}

/// Returns the value associated to the node if present.
///
/// # Examples
///
/// ```
/// use intel_crashlog::prelude::*;
///
/// let field = Node::field("foo", 42);
/// assert_eq!(field.value(), Some(42));
/// let section = Node::section("bar");
/// assert_eq!(section.value(), None);
/// ```
pub fn value(&self) -> Option<u64> {
if let NodeType::Field { value } = self.kind {
Some(value)
} else {
None
}
}

/// Returns the value of the field stored at the given path.
///
/// # Examples
///
/// ```
/// use intel_crashlog::prelude::*;
///
/// let mut foo = Node::section("foo");
/// foo.add(Node::field("bar", 42));
/// let mut root = Node::root();
/// root.add(foo);
///
/// assert_eq!(root.get_value_by_path("foo.bar"), Some(42));
/// assert_eq!(root.get_value_by_path("foo"), None);
/// assert_eq!(root.get_value_by_path("foo.baz"), None);
/// ```
pub fn get_value_by_path(&self, path: &str) -> Option<u64> {
self.get_by_path(path).and_then(|node| node.value())
}

fn merge_instance(&mut self, mut other: Node) {
let mut instance = 0;
let name = other.name.clone();
Expand Down
56 changes: 33 additions & 23 deletions lib/src/record/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::Record;
use crate::Error;
#[cfg(feature = "collateral_manager")]
use crate::collateral::{CollateralManager, CollateralTree};
use crate::node::{Node, NodeType};
use crate::node::Node;
#[cfg(not(feature = "std"))]
use alloc::format;

Expand All @@ -15,33 +15,43 @@ impl Record {
&self,
cm: &mut CollateralManager<T>,
) -> Result<Node, Error> {
let mut section = Node::section("core");

for decode_def in ["layout_thread.csv", "layout_core.csv"] {
if let Ok(thread) = self.decode_with_decode_def(cm, decode_def, 0) {
let core_id = thread
.children()
.next()
.and_then(|child| child.get_by_path("hdr.whoami.core_id"))
.map(|core_id| &core_id.kind);
if let Some(NodeType::Field { value }) = core_id {
section.name = format!("core{value}");
}
section.merge(thread);
}
}
let mut section = Node::section(self.header.record_type()?);

for subsection_name in ["thread", "core"] {
let decode_def = format!("layout_{subsection_name}.csv");
let Ok(mut root) = self.decode_with_decode_def(cm, &decode_def, 0) else {
continue;
};

if let Some(offset) = self.header.extended_record_offset() {
for decode_def in ["layout_sq.csv", "layout_module.csv"] {
if let Ok(node) = self.decode_with_decode_def(cm, decode_def, offset) {
section.merge(node);
if let Some(offset) = self.header.extended_record_offset() {
for decode_def in ["layout_sq.csv", "layout_module.csv"] {
let Ok(extension) = self.decode_with_decode_def(cm, decode_def, offset) else {
continue;
};

root.merge(extension);
break;
}
}

let Some(subsection) = root.get(subsection_name) else {
continue;
};
let hierarchy = ["module", "core", "thread"]
.into_iter()
.filter_map(|level| {
subsection
.get_value_by_path(&format!("hdr.whoami.{level}_id"))
.map(|id| format!("{level}{id}"))
});

section.create_hierarchy_from_iter(hierarchy).merge(root);

let mut root = Node::root();
root.add(section);
return Ok(root);
}

let mut root = Node::root();
root.add(section);
Ok(root)
Err(Error::MissingDecodeDefinitions(self.header.version.clone()))
}
}
8 changes: 5 additions & 3 deletions lib/tests/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn lnc_three_strike_timeout() {
let nodes = crashlog.decode(&mut cm);

let status = nodes
.get_by_path("core0.thread.arch_state.mca.bank3.status")
.get_by_path("pcore.core0.thread0.thread.arch_state.mca.bank3.status")
.unwrap();
assert_eq!(
status.kind,
Expand All @@ -20,15 +20,17 @@ fn lnc_three_strike_timeout() {
}
);

let lip = nodes.get_by_path("core0.thread.arch_state.lip").unwrap();
let lip = nodes
.get_by_path("pcore.core0.thread0.thread.arch_state.lip")
.unwrap();
assert_eq!(
lip.kind,
NodeType::Field {
value: 0xfffff80577036530
}
);

let entry = nodes.get_by_path("core0.sq.entry0").unwrap();
let entry = nodes.get_by_path("pcore.core0.thread0.sq.entry0").unwrap();
assert_eq!(
entry.kind,
NodeType::Field {
Expand Down
4 changes: 2 additions & 2 deletions lib/tests/crashlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn core_box_header_type6() {
let root = crashlog.decode(&mut cm);

let entry0 = root
.get_by_path("processors.cpu0.die8.core0.sq.entry0")
.get_by_path("processors.cpu0.die8.pcore.core0.thread0.sq.entry0")
.unwrap();

assert_eq!(
Expand All @@ -62,7 +62,7 @@ fn core_box_header_type6() {
assert_eq!(record_type_box.kind, NodeType::Field { value: 0x3d });

let bank3 = root
.get_by_path("processors.cpu0.die8.core0.thread.arch_state.mca.bank3.status")
.get_by_path("processors.cpu0.die8.pcore.core0.thread0.thread.arch_state.mca.bank3.status")
.unwrap();

assert_eq!(
Expand Down
Loading