1use std::fmt;
3
4use crate::error;
5
6#[derive(Clone, Default, Debug)]
8pub struct File {
9 pub start: u64,
11 pub end: u64,
13 pub offset: u64,
15 pub name: String,
17}
18
19impl File {
20 pub fn new(start: u64, end: u64, offset: u64, fname: &str) -> Self {
32 File {
33 start,
34 end,
35 offset,
36 name: String::from(fname),
37 }
38 }
39}
40
41impl fmt::Display for File {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 write!(
44 f,
45 "File {{ Start: 0x{:x}, End: 0x{:x}, offset: 0x{:x}, path: {} }}",
46 self.start, self.end, self.offset, self.name
47 )
48 }
49}
50
51pub type MappedFiles = Vec<File>;
53
54pub trait MappedFilesExt {
55 fn from_gdb<T: AsRef<str>>(mapping: T) -> error::Result<MappedFiles>;
61
62 fn find(&self, addr: u64) -> Option<File>;
68}
69
70impl MappedFilesExt for MappedFiles {
71 fn from_gdb<T: AsRef<str>>(mapping: T) -> error::Result<MappedFiles> {
72 let mut hlp = mapping
73 .as_ref()
74 .lines()
75 .map(|s| s.trim().to_string())
76 .collect::<Vec<String>>();
77
78 if let Some(pos) = hlp.iter().position(|x| x.contains("Start Addr")) {
79 hlp.drain(0..pos + 1);
80 }
81
82 let mut info = Vec::new();
84 let mut name_idx = 0;
85 for x in hlp.iter() {
86 let filevec = x
87 .split_whitespace()
88 .map(|s| s.trim().to_string())
89 .filter(|s| !s.is_empty())
90 .collect::<Vec<String>>();
91 if filevec.len() < 4 {
92 return Err(error::Error::MappedFilesParse(format!(
93 "Expected at least 4 columns in {x}"
94 )));
95 }
96
97 name_idx = name_idx.max(filevec.len() - 1);
100
101 info.push(filevec);
102 }
103
104 let mut files = MappedFiles::new();
105
106 for x in info.iter() {
108 let f = File {
109 start: u64::from_str_radix(x[0].get(2..).unwrap_or(&x[0]), 16)?,
110 end: u64::from_str_radix(x[1].get(2..).unwrap_or(&x[1]), 16)?,
111 offset: u64::from_str_radix(x[3].get(2..).unwrap_or(&x[3]), 16)?,
112 name: x.get(name_idx).unwrap_or(&String::new()).clone(),
113 };
114 files.push(f);
115 }
116
117 Ok(files)
118 }
119
120 fn find(&self, addr: u64) -> Option<File> {
121 self.iter()
122 .find(|&x| (x.start <= addr) && (x.end > addr))
123 .cloned()
124 }
125}