summaryrefslogtreecommitdiff
path: root/src/types/debug_symbols.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/types/debug_symbols.rs')
-rw-r--r--src/types/debug_symbols.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/types/debug_symbols.rs b/src/types/debug_symbols.rs
new file mode 100644
index 0000000..f4fc412
--- /dev/null
+++ b/src/types/debug_symbols.rs
@@ -0,0 +1,59 @@
+use crate::*;
+
+
+pub struct DebugSymbols {
+ symbols: Vec<DebugSymbol>
+}
+
+impl DebugSymbols {
+ /// Load debug symbols from a symbols file.
+ pub fn from_path_opt<P: AsRef<Path>>(path: Option<P>) -> Self {
+ let mut symbols = Vec::new();
+ if let Some(path) = path {
+ if let Ok(string) = std::fs::read_to_string(path) {
+ for line in string.lines() {
+ if let Some(symbol) = DebugSymbol::from_line(line) {
+ symbols.push(symbol);
+ }
+ }
+ }
+ }
+ symbols.sort_by_key(|s| s.address);
+ Self { symbols }
+ }
+
+ /// Return the symbol matching a given address.
+ pub fn for_address(&self, address: u16) -> Option<&DebugSymbol> {
+ if self.symbols.is_empty() { return None; }
+ let symbol = match self.symbols.binary_search_by_key(&address, |s| s.address) {
+ Ok(index) => self.symbols.get(index)?,
+ Err(index) => self.symbols.get(index.checked_sub(1)?)?,
+ };
+ Some(&symbol)
+ }
+}
+
+
+pub struct DebugSymbol {
+ pub address: u16,
+ pub name: String,
+ pub location: Option<String>,
+}
+
+impl DebugSymbol {
+ pub fn from_line(line: &str) -> Option<Self> {
+ if let Some((address, line)) = line.split_once(' ') {
+ let address = u16::from_str_radix(address, 16).ok()?;
+ if let Some((name, location)) = line.split_once(' ') {
+ let name = name.to_string();
+ let location = Some(location.to_string());
+ Some( DebugSymbol { address, name, location } )
+ } else {
+ let name = line.to_string();
+ Some( DebugSymbol { address, name, location: None } )
+ }
+ } else {
+ None
+ }
+ }
+}