Finish collecting dwarf dependencies
This commit is contained in:
parent
68aa47a94e
commit
6926711e83
|
@ -4,6 +4,7 @@ use std::{
|
|||
path::PathBuf, borrow::Cow,
|
||||
};
|
||||
|
||||
use gimli::{constants, AttributeValue, DW_TAG_compile_unit};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{digest::generic_array::{GenericArray, typenum::U32}, Digest, Sha256};
|
||||
use object::{Object, ReadCache, ObjectSection};
|
||||
|
@ -129,14 +130,15 @@ impl FileStore {
|
|||
}
|
||||
|
||||
let fp = fs::File::open(&filename)?;
|
||||
self.ingest_output(filename, fp)
|
||||
self.ingest_output(filename, fp);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ingest_output(
|
||||
&mut self,
|
||||
filename: PathBuf,
|
||||
mut content: (impl io::Read + io::Seek),
|
||||
) -> anyhow::Result<()> {
|
||||
) -> anyhow::Result<usize> {
|
||||
let mut h = Sha256::new();
|
||||
io::copy(&mut content, &mut h)?;
|
||||
let hash = h.finalize().into();
|
||||
|
@ -167,7 +169,7 @@ impl FileStore {
|
|||
|
||||
self.filenames.insert(filename, index);
|
||||
|
||||
Ok(())
|
||||
Ok(index)
|
||||
}
|
||||
|
||||
fn parse_format(&mut self, fp: &mut (impl io::Read + io::Seek)) -> anyhow::Result<FileFormat> {
|
||||
|
@ -189,22 +191,57 @@ impl FileStore {
|
|||
let mut load_section = |id: gimli::SectionId| -> Result<_, _> {
|
||||
load_file_section(id, &elf, endian, &arena_data)
|
||||
};
|
||||
let mut dwarf = gimli::Dwarf::load(&mut load_section).unwrap();
|
||||
let dwarf = gimli::Dwarf::load(&mut load_section).unwrap();
|
||||
let mut units = dwarf.units();
|
||||
let mut inputs = vec![];
|
||||
while let Ok(Some(unit)) = units.next() {
|
||||
let abbrev = dwarf.abbreviations(&unit)?;
|
||||
let mut entries = unit.entries(&abbrev);
|
||||
while let Ok(Some(entry)) = entries.next_sibling() {
|
||||
while let Some((_, entry)) = entries.next_dfs()? {
|
||||
if entry.tag() == DW_TAG_compile_unit {
|
||||
let mut basename = None;
|
||||
let mut dirname = None;
|
||||
if let Some(name) = entry.attr(constants::DW_AT_name)?.map(|a| a.value()) {
|
||||
if let Ok(name) = dwarf.attr_string(&dwarf.unit(unit)?, name) {
|
||||
basename = Some(PathBuf::from(name.to_string()?));
|
||||
}
|
||||
}
|
||||
if let Some(name) = entry.attr(constants::DW_AT_comp_dir)?.map(|a| a.value()) {
|
||||
if let Ok(name) = dwarf.attr_string(&dwarf.unit(unit)?, name) {
|
||||
dirname = Some(PathBuf::from(name.to_string()?));
|
||||
}
|
||||
}
|
||||
if let (Some(dirname), Some(basename)) = (dirname, basename) {
|
||||
inputs.push(dirname.join(basename));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(elf.is_little_endian());
|
||||
|
||||
let references = inputs.into_iter().map(|input| self.ingest_dependency_local(input)).collect::<Result<Vec<_>, _>>()?.into_iter().filter_map(|x| x).collect();
|
||||
FileFormat::ELF {
|
||||
references: vec![],
|
||||
references,
|
||||
}
|
||||
},
|
||||
_ => FileFormat::Other,
|
||||
})
|
||||
}
|
||||
|
||||
fn ingest_dependency_local(&mut self, filename: PathBuf) -> anyhow::Result<Option<usize>> {
|
||||
// TODO: this needs to try suffixes of the filename against the filepath table to see if it
|
||||
// was moved between compilation and ingestion
|
||||
let metadata = match fs::metadata(&filename) {
|
||||
Ok(m) => m,
|
||||
Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(None),
|
||||
Err(e) => return Err(e)?,
|
||||
};
|
||||
if !metadata.is_file() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let fp = fs::File::open(&filename)?;
|
||||
Ok(Some(self.ingest_output(filename, fp)?))
|
||||
}
|
||||
}
|
||||
|
||||
fn load_file_section<'input, 'arena, Endian: gimli::Endianity, R: object::ReadRef<'input>>(
|
||||
|
|
|
@ -585,6 +585,8 @@ impl Tracer {
|
|||
// So we need to determine whether exec is successful here.
|
||||
// PTRACE_EVENT_EXEC only happens for successful exec.
|
||||
p.is_exec_successful = true;
|
||||
let path = p.pending_syscall_event.iter().find_map(|e| match e { Event::Exec { prog, .. } => Some(prog.clone()), _ => None }).unwrap();
|
||||
self.report.files.ingest_output_local(path)?;
|
||||
self.drain_syscall_events(pid.into(), Box::new(|_| {}));
|
||||
// Don't use seccomp_aware_cont here because that will skip the next syscall exit stop
|
||||
self.syscall_enter_cont(pid.into())?;
|
||||
|
|
Loading…
Reference in New Issue