diff --git a/lib/src/crashlog.rs b/lib/src/crashlog.rs index 24351ea..c4f36b2 100644 --- a/lib/src/crashlog.rs +++ b/lib/src/crashlog.rs @@ -14,8 +14,6 @@ use alloc::{collections::VecDeque, vec, vec::Vec}; #[cfg(feature = "std")] use std::collections::VecDeque; -use crate::header::record_types; - /// Set of all the Crash Log records captured on a platform. #[derive(Default)] pub struct CrashLog { @@ -31,29 +29,9 @@ impl CrashLog { let mut regions = Vec::new(); while let Some(region) = queue.pop_front() { - for record in region.records.iter() { - let errata = record.header.version.errata(); - let is_box = record.header.version.record_type == record_types::BOX - || errata.type0_legacy_server_box; - - if !is_box { - continue; - } - - let Some(payload) = record.data.get(record.header.header_size()..) else { - log::error!("The Box record has an empty payload"); - continue; - }; - - match Region::from_slice(payload) { - Ok(mut region) => { - region.set_child_context(&record.header); - queue.push_front(region) - } - Err(err) => log::warn!("Invalid region in Box record: {err}"), - } + for child in region.get_children() { + queue.push_back(child); } - regions.push(region) } diff --git a/lib/src/region.rs b/lib/src/region.rs index ff2747f..d49d52a 100644 --- a/lib/src/region.rs +++ b/lib/src/region.rs @@ -5,11 +5,13 @@ use crate::cper::section::{CperSectionBody, fer}; use crate::error::Error; -use crate::header::Header; +use crate::header::{Header, record_types}; use crate::record::Record; #[cfg(not(feature = "std"))] use alloc::vec::Vec; +const MAX_NESTED_BOXES: usize = 4; + /// A container for one or several Crash Log records. /// /// A Crash Log region refers to a region in an on-die memory that is allocated for storing @@ -17,6 +19,7 @@ use alloc::vec::Vec; #[derive(Default)] pub struct Region { pub records: Vec, + depth: usize, } impl Region { @@ -35,10 +38,42 @@ impl Region { } } - pub(crate) fn set_child_context(&mut self, hdr: &Header) { - for record in self.records.iter_mut() { - record.context.parent_header = Some(hdr.clone()); + pub(crate) fn get_children(&self) -> Vec { + let mut children = Vec::new(); + + if self.depth >= MAX_NESTED_BOXES { + return children; + } + + for record in self.records.iter() { + let errata = record.header.version.errata(); + let is_box = record.header.version.record_type == record_types::BOX + || errata.type0_legacy_server_box; + + if !is_box { + continue; + } + + let Some(payload) = record.data.get(record.header.header_size()..) else { + log::error!("The Box record has an empty payload"); + continue; + }; + + match Region::from_slice(payload) { + Ok(mut child) => { + for child_record in child.records.iter_mut() { + child_record.context.parent_header = Some(record.header.clone()); + } + + child.depth = self.depth + 1; + + children.push(child) + } + Err(err) => log::warn!("Invalid region in Box record: {err}"), + } } + + children } pub fn from_slice(bytes: &[u8]) -> Result {