linker_trace/
lib.rs

1//! This crate defines a format for storing debug traces associated with particular addresses in the
2//! linker output.
3
4use anyhow::Context;
5use anyhow::Result;
6use serde::Deserialize;
7use serde::Serialize;
8use std::io::Write;
9use std::ops::Range;
10use std::path::Path;
11use std::path::PathBuf;
12
13#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Default)]
14pub struct TraceData {
15    pub traces: Vec<AddressTrace>,
16}
17
18#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
19pub struct AddressTrace {
20    pub address: u64,
21    pub messages: Vec<String>,
22}
23
24#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
25pub struct Section {
26    pub mem_range: Range<u64>,
27}
28
29impl TraceData {
30    pub fn write(&self, writer: &mut impl Write) -> Result<()> {
31        postcard::to_io(self, writer)?;
32        Ok(())
33    }
34
35    pub fn to_bytes(&self) -> Result<Vec<u8>> {
36        Ok(postcard::to_stdvec(self)?)
37    }
38
39    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
40        postcard::from_bytes(bytes).context("Invalid linker trace")
41    }
42}
43
44#[must_use]
45pub fn trace_path(base_path: &Path) -> PathBuf {
46    let mut new_extension = base_path.extension().unwrap_or_default().to_owned();
47    new_extension.push(".trace");
48    base_path.with_extension(new_extension)
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_round_trip() {
57        let layout = TraceData {
58            traces: vec![AddressTrace {
59                address: 100,
60                messages: vec!["Test".to_owned()],
61            }],
62        };
63        let bytes = layout.to_bytes().unwrap();
64        let layout2 = TraceData::from_bytes(&bytes).unwrap();
65        assert_eq!(layout, layout2);
66    }
67}