Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

crates/mimir-room/src/symbols.rs

//! The binary stream's own facts, beyond the one `linked` flag: every linked
//! symbol with its size / section / role / artifact — and the record of the
//! node ids the fold MERGED (several rows, one id).

use anyhow::Result;
use serde::Serialize;

use crate::Room;
use crate::evidence::Answer;
use crate::query::Mask;
use crate::snapshot::{DupKey, NONE};

/// One linked symbol of an artifact.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub struct SymbolView<'a> {
    /// The node it belongs to (an item, a mono instance, an FFI import).
    pub node: u64,
    /// The linker name (mangled).
    pub symbol: &'a str,
    pub demangled: Option<&'a str>,
    /// `item` · `mono` · `closure` · `shim` · `import` (`mimir_schema::role`).
    pub role: Option<&'a str>,
    /// The artifact that links it (`name@target-triple:profile`).
    pub artifact: &'a str,
    /// The artifact's file name.
    pub binary: Option<&'a str>,
    pub section: Option<&'a str>,
    /// Bytes; `None` for an import (resolved by the dynamic linker).
    pub size: Option<u64>,
}

impl Room {
    fn symbol_at(&self, i: usize) -> SymbolView<'_> {
        let s = &self.snap.symbols;
        let st = |v: u32| (v != NONE).then(|| s.strs[v as usize].as_str());
        SymbolView {
            node: s.node[i] as u64,
            symbol: s.symbol.get(i),
            demangled: Some(s.demangled.get(i)).filter(|d| !d.is_empty()),
            role: st(s.role[i]),
            artifact: st(s.artifact[i]).unwrap_or(""),
            binary: st(s.binary[i]),
            section: st(s.section[i]),
            size: (s.size[i] != u64::MAX).then_some(s.size[i]),
        }
    }

    /// The linked symbols of one node (several: one per artifact, plus its
    /// closures and shims), by symbol name.
    pub fn symbols_of(&self, ordinal: u64) -> Vec<SymbolView<'_>> {
        let s = &self.snap.symbols;
        let o = ordinal as u32;
        let at = s.node.partition_point(|n| *n < o);
        (at..s.len()).take_while(|i| s.node[*i] == o).map(|i| self.symbol_at(i)).collect()
    }

    /// Bytes linked for one node: the sum of its symbols' sizes over every
    /// artifact (0 when nothing of it is linked).
    pub fn linked_bytes(&self, ordinal: u64) -> u64 {
        self.symbols_of(ordinal).iter().filter_map(|s| s.size).sum()
    }

    /// Every linked symbol row (of the nodes in `within`, when given), by
    /// (node, symbol); `cap` = return at most that many.
    pub fn symbols(&self, within: Option<&Mask>, cap: Option<usize>) -> Result<Answer<Vec<SymbolView<'_>>>> {
        let mut ev = self.evidence(format!("symbols(within {:?}, cap {cap:?})", within.map(|m| m.len())), true, &[]);
        if let Some(m) = within {
            self.check_mask(m)?;
        }
        let s = &self.snap.symbols;
        let keep: Vec<usize> = (0..s.len()).filter(|i| within.is_none_or(|m| m.contains(s.node[*i] as u64))).collect();
        let shown = cap.map_or(keep.len(), |c| c.min(keep.len()));
        ev.cap(shown, keep.len());
        Ok(Answer::new(keep[..shown].iter().map(|i| self.symbol_at(*i)).collect(), ev))
    }

    /// The node ids the fold merged: an id that several open rows describe
    /// with DIFFERENT payloads (`distinct_payloads > 1` — two owners
    /// disagree about the item), or that one dump repeated inside a unit
    /// (`key_dup_rows > 0`). By ordinal. The ledger (`ingest_runs.
    /// key_collisions`) counts the second kind per commit; this is the list.
    pub fn duplicate_keys(&self, within: Option<&Mask>) -> Result<Answer<Vec<DupKey>>> {
        let ev = self.evidence(format!("duplicate_keys(within {:?})", within.map(|m| m.len())), false, &[]);
        if let Some(m) = within {
            self.check_mask(m)?;
        }
        let v: Vec<DupKey> = self.snap.dups.iter().filter(|d| within.is_none_or(|m| m.contains(d.node))).cloned().collect();
        Ok(Answer::new(v, ev))
    }
}