-
-
Notifications
You must be signed in to change notification settings - Fork 222
/
print_sources.rs
84 lines (73 loc) · 2.55 KB
/
print_sources.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use std::path::Path;
use anyhow::Result;
use clap::{Arg, ArgMatches, Command};
use symbolic::common::ByteView;
use symbolic::debuginfo::{Archive, Object};
pub fn make_command(command: Command) -> Command {
command
.about("Print source files linked by the given debug info file.")
.arg(
Arg::new("path")
.required(true)
.help("The path to the debug info file."),
)
}
pub fn execute(matches: &ArgMatches) -> Result<()> {
let path = Path::new(matches.value_of("path").unwrap());
// which types should we consider?
let data = ByteView::open(path)?;
let archive = Archive::parse(&data)?;
if archive.object_count() == 0 {
println!("No objects found in the given debug info file");
return Ok(());
}
for object in archive.objects() {
let object = object?;
print_object_sources(&object)?;
// In case of a PE file with an embedded PDB, handle the PPDB separately.
if let Object::Pe(pe) = &object {
if let Some(ppdb_data) = pe.embedded_ppdb()? {
let mut buf = Vec::new();
ppdb_data.decompress_to(&mut buf)?;
let ppdb = Object::parse(&buf)?;
print_object_sources(&ppdb)?;
}
}
}
Ok(())
}
fn print_object_sources(object: &Object) -> Result<()> {
let debug_session = object.debug_session()?;
// We're not using object.has_sources() because it only reports on embedded sources, not referenced files.
if debug_session.files().next().is_none() {
println!(
"{} {} has no sources.",
object.file_format(),
object.debug_id()
);
} else {
println!(
"{} {} references sources:",
object.file_format(),
object.debug_id()
);
for file in debug_session.files() {
let file = file?;
let abs_path = file.abs_path_str();
println!(" {}", &abs_path);
match debug_session.source_by_path(abs_path.as_str())? {
Some(source) => {
println!(" Embedded, {} bytes", source.len());
}
None => {
if Path::new(&abs_path).exists() {
println!(" Not embedded, but available on the local disk.");
} else {
println!(" Not embedded nor available locally at the referenced path.");
}
}
}
}
}
Ok(())
}