diff --git a/Cargo.lock b/Cargo.lock index 465bbc4d..8b03b446 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -46,6 +37,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + [[package]] name = "arrayvec" version = "0.7.2" @@ -69,21 +66,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide 0.4.4", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.13.0" @@ -198,22 +180,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - [[package]] name = "cpp_demangle" version = "0.3.5" @@ -358,12 +324,12 @@ checksum = "d4699f5cb7678f099b747ffdc1e6ce6cdc42579e29d28315aa715b9fd10324fc" name = "dump_syms" version = "0.0.7" dependencies = [ + "anyhow", "bitflags", "cab", "clap", "crossbeam", "dirs", - "failure", "futures", "fxhash", "goblin", @@ -371,7 +337,6 @@ dependencies = [ "lazy_static", "log", "num_cpus", - "openssl", "pdb", "regex", "reqwest", @@ -405,28 +370,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "fallible-iterator" version = "0.2.0" @@ -451,7 +394,7 @@ dependencies = [ "cfg-if", "crc32fast", "libc", - "miniz_oxide 0.5.1", + "miniz_oxide", ] [[package]] @@ -460,21 +403,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.0.1" @@ -728,16 +656,16 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-rustls" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "bytes", + "http", "hyper", - "native-tls", + "rustls", "tokio", - "tokio-native-tls", + "tokio-rustls", ] [[package]] @@ -891,16 +819,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.5.1" @@ -942,24 +860,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "native-tls" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "new_debug_unreachable" version = "1.0.4" @@ -1027,15 +927,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.10.0" @@ -1048,49 +939,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "openssl" -version = "0.10.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-sys", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "111.18.0+1.1.1n" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7897a926e1e8d00219127dc020130eca4292e5ca666dd592480d72c3eca2ff6c" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" -dependencies = [ - "autocfg", - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - [[package]] name = "parking_lot" version = "0.12.0" @@ -1152,12 +1000,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" - [[package]] name = "plain" version = "0.2.3" @@ -1255,27 +1097,44 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-tls", + "hyper-rustls", "ipnet", "js-sys", "lazy_static", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-native-tls", + "tokio-rustls", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -1283,21 +1142,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] -name = "ryu" -version = "1.0.9" +name = "rustls" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] [[package]] -name = "schannel" -version = "0.1.19" +name = "rustls-pemfile" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" dependencies = [ - "lazy_static", - "winapi", + "base64", ] +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1331,26 +1201,13 @@ dependencies = [ ] [[package]] -name = "security-framework" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.6.1" +name = "sct" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "core-foundation-sys", - "libc", + "ring", + "untrusted", ] [[package]] @@ -1448,6 +1305,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1566,18 +1429,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "tap" version = "1.0.1" @@ -1678,13 +1529,14 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.0" +name = "tokio-rustls" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" dependencies = [ - "native-tls", + "rustls", "tokio", + "webpki", ] [[package]] @@ -1778,6 +1630,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -1796,12 +1654,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "vec_map" version = "0.8.2" @@ -1918,6 +1770,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" +dependencies = [ + "webpki", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 28f32846..a4b6a7ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,25 @@ description = "Dump debug symbols into Breakpad ones" edition = "2018" license = "MIT/Apache-2.0" +[[bin]] +name = "dump_syms" +required-features = ["cli"] + +[features] +default = ["cli", "http"] +# Feature needed when building the dump_syms executable +cli = ["clap", "simplelog"] +# Feature for allowing retrieval of symbols via HTTP +http = ["reqwest", "futures", "tokio"] + [dependencies] +anyhow = "1.0" bitflags = "1.3" cab = "0.2" -clap = "2.33" +clap = { version = "2.33", optional = true } crossbeam = "0.8.1" dirs = "3.0" -failure = "0.1" -futures = "0.3" +futures = { version = "0.3", optional = true } goblin = "0.5.1" # Keep in sync with symbolic-debuginfo hashbrown = { version = "0.11", features = ["serde"] } lazy_static = "1.4" @@ -23,23 +34,23 @@ log = "0.4" num_cpus = "1.13" pdb = "0.7" regex = "1.4" -reqwest = { version = "0.11", features = ["blocking"] } +reqwest = { version = "0.11", optional = true, default-features = false, features = [ + "blocking", + "rustls-tls", +] } serde = "1.0" serde_json = "1.0" sha2 = "0.9" -simplelog = "0.10" +simplelog = { version = "0.10", optional = true } symbolic = { version = "8", features = ["demangle", "minidump"] } -tokio = "1.8" +tokio = { version = "1.8", optional = true } url = "2.2" uuid = "0.8" [dev-dependencies] +reqwest = { version = "0.11", default-features = false, features = [ + "blocking", + "rustls-tls", +] } fxhash = "0.2" tempfile = "3" - -[features] -vendored-openssl = ["openssl/vendored"] - -[dependencies.openssl] -version = "0.10" -optional = true diff --git a/src/action.rs b/src/action.rs index f30fa1a4..ec029e56 100644 --- a/src/action.rs +++ b/src/action.rs @@ -5,14 +5,15 @@ use std::path::PathBuf; -use crate::common::{self, FileType}; -use crate::linux::elf::ElfInfo; -use crate::mac::macho::MachoInfo; -use crate::utils; -use crate::windows::pdb::PDBInfo; +use dump_syms::common::{self, FileType}; +use dump_syms::linux::elf::ElfInfo; +use dump_syms::mac::macho::MachoInfo; +use dump_syms::utils; +use dump_syms::windows::pdb::PDBInfo; -use super::dumper::{self, Config}; +use dump_syms::dumper::{self, Config}; +#[allow(clippy::large_enum_variant)] pub(crate) enum Action<'a> { Dump(Config<'a>), ListArch, @@ -82,9 +83,8 @@ mod tests { copy(basic64, &tmp_file).unwrap(); let action = Action::Dump(Config { - output: tmp_out.to_str().unwrap(), + output: tmp_out.clone().into(), symbol_server: None, - store: None, debug_id: None, code_id: None, arch: common::get_compile_time_arch(), @@ -116,9 +116,8 @@ mod tests { copy(basic64, &tmp_file).unwrap(); let action = Action::Dump(Config { - output: tmp_out.to_str().unwrap(), + output: tmp_out.into(), symbol_server: None, - store: None, debug_id: None, code_id: None, arch: common::get_compile_time_arch(), @@ -148,9 +147,8 @@ mod tests { copy(basic64_dll, &tmp_dll).unwrap(); let action = Action::Dump(Config { - output: tmp_out.to_str().unwrap(), + output: tmp_out.clone().into(), symbol_server: None, - store: None, debug_id: None, code_id: None, arch: common::get_compile_time_arch(), @@ -179,9 +177,8 @@ mod tests { let tmp_out = tmp_dir.path().join("output.sym"); let action = Action::Dump(Config { - output: tmp_out.to_str().unwrap(), + output: tmp_out.clone().into(), symbol_server: None, - store: None, debug_id: None, code_id: None, arch: common::get_compile_time_arch(), @@ -214,9 +211,8 @@ mod tests { let tmp_out = tmp_dir.path().join("output.sym"); let action = Action::Dump(Config { - output: tmp_out.to_str().unwrap(), + output: tmp_out.clone().into(), symbol_server: None, - store: None, debug_id: None, code_id: None, arch: common::get_compile_time_arch(), @@ -256,9 +252,8 @@ mod tests { let tmp_out = tmp_dir.path().join("output.sym"); let action = Action::Dump(Config { - output: tmp_out.to_str().unwrap(), + output: tmp_out.clone().into(), symbol_server: None, - store: None, debug_id: None, code_id: None, arch: common::get_compile_time_arch(), diff --git a/src/cache.rs b/src/cache.rs index 99eb5987..a7fa3aa4 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -33,9 +33,7 @@ struct Job { impl Job { fn new(cache: Option, url: String) -> common::Result { - if Url::parse(&url).is_err() { - return Err(From::from(format!("Invalid url: {}", url))); - } + anyhow::ensure!(Url::parse(&url).is_ok(), "Invalid url: {}", url); Ok(Self { cache, url }) } } @@ -150,30 +148,6 @@ fn copy_in_cache(path: Option, data: &[u8]) -> bool { true } -fn get_base(file_name: &str) -> PathBuf { - // The file is stored at cache/xul.pdb/DEBUG_ID/xul.pd_ - // the xul.pdb represents the base - let path = PathBuf::from(file_name); - if let Some(e) = path.extension() { - let e = e.to_str().unwrap().to_lowercase(); - match e.as_str() { - "pd_" => path.with_extension("pdb"), - "ex_" => path.with_extension("exe"), - "dl_" => path.with_extension("dll"), - _ => path.clone(), - } - } else { - path.clone() - } -} - -pub fn get_path_for_sym(file_name: &str, id: &str) -> PathBuf { - let base = get_base(file_name); - let file_name = PathBuf::from(file_name); - let file_name = file_name.with_extension("sym"); - base.join(id).join(file_name) -} - fn search_in_cache( servers: &[SymbolServer], id: &str, @@ -295,7 +269,7 @@ pub fn search_file( _ => return (None, file_name), }; - let base = get_base(&file_name); + let base = utils::get_base(&file_name); // Start with the caches if let Some(path) = search_in_cache(servers, id, &base, &file_name) { diff --git a/src/common.rs b/src/common.rs index b5a29cdf..e1eabd23 100644 --- a/src/common.rs +++ b/src/common.rs @@ -5,16 +5,14 @@ use regex::Regex; use std::env::consts::ARCH; -use std::error; use std::io::Write; use std::result; use symbolic::common::{Arch, Name}; use symbolic::debuginfo::{peek, FileFormat}; -type Error = Box; -pub type Result = result::Result; +pub type Result = result::Result; -pub(crate) enum FileType { +pub enum FileType { Pdb, Pe, Elf, @@ -23,7 +21,7 @@ pub(crate) enum FileType { } impl FileType { - pub(crate) fn from_buf(buf: &[u8]) -> Self { + pub fn from_buf(buf: &[u8]) -> Self { match peek(buf, true /* check for fat binary */) { FileFormat::Pdb => Self::Pdb, FileFormat::Pe => Self::Pe, @@ -32,26 +30,30 @@ impl FileType { _ => Self::Unknown, } } +} + +impl std::str::FromStr for FileType { + type Err = std::convert::Infallible; - pub(crate) fn from_str(s: &str) -> Self { + fn from_str(s: &str) -> std::result::Result { let s = s.to_lowercase(); - match s.as_str() { + Ok(match s.as_str() { "pdb" => Self::Pdb, "elf" => Self::Elf, "macho" => Self::Macho, _ => Self::Unknown, - } + }) } } -pub(crate) trait Dumpable { +pub trait Dumpable { fn dump(&self, writer: W) -> Result<()>; fn get_name(&self) -> &str; fn get_debug_id(&self) -> &str; fn has_stack(&self) -> bool; } -pub(crate) trait Mergeable { +pub trait Mergeable { fn merge(left: Self, right: Self) -> Result where Self: Sized; @@ -61,7 +63,7 @@ pub(crate) trait LineFinalizer { fn finalize(&mut self, sym_rva: u32, sym_len: u32, map: &M); } -pub(crate) fn get_compile_time_arch() -> &'static str { +pub fn get_compile_time_arch() -> &'static str { use Arch::*; match ARCH { @@ -84,7 +86,7 @@ pub(crate) fn normalize_anonymous_namespace(text: &str) -> String { } pub(crate) fn fix_symbol_name<'a>(name: &'a Name<'a>) -> Name<'a> { - lazy_static! { + lazy_static::lazy_static! { static ref LLVM_NNN: Regex = Regex::new(r"\.llvm\.[0-9]+$").unwrap(); } let fixed = LLVM_NNN.replace(name.as_str(), ""); diff --git a/src/dumper.rs b/src/dumper.rs index 9346ab07..cba11c6b 100644 --- a/src/dumper.rs +++ b/src/dumper.rs @@ -4,9 +4,9 @@ // copied, modified, or distributed except according to those terms. use crossbeam::channel::{bounded, Receiver, Sender}; -use failure::Fail; use hashbrown::HashMap; use log::{error, info}; +use std::fmt; use std::fs; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -16,7 +16,6 @@ use std::thread; use symbolic::common::Arch; use symbolic::debuginfo::pe::PeObject; -use crate::cache; use crate::common::{self, Dumpable, FileType, Mergeable}; use crate::linux::elf::{ElfInfo, Platform}; use crate::mac::macho::MachoInfo; @@ -24,10 +23,58 @@ use crate::mapping::PathMappings; use crate::utils; use crate::windows::{self, pdb::PDBInfo, pdb::PEInfo}; -pub(crate) struct Config<'a> { - pub output: &'a str, +/// Different locations for file output +#[derive(Clone)] +pub enum FileOutput { + Path(PathBuf), + Stdout, + Stderr, +} + +impl From<&str> for FileOutput { + fn from(s: &str) -> Self { + if s == "-" { + Self::Stdout + } else { + Self::Path(s.into()) + } + } +} + +impl fmt::Display for FileOutput { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Path(p) => write!(f, "{}", p.display()), + Self::Stdout => f.write_str("stdout"), + Self::Stderr => f.write_str("stderr"), + } + } +} + +/// Defines how the final symbols are outputted +#[derive(Clone)] +pub enum Output { + File(FileOutput), + /// Store output symbols as FILENAME./DEBUG_ID/FILENAME.sym in the + /// specified directory, ie the symbol store format + Store(PathBuf), + /// Writes symbols to a file as well as storing them in the symbol store + /// format to the specified directory + FileAndStore { + file: FileOutput, + store_directory: PathBuf, + }, +} + +impl From for Output { + fn from(path: PathBuf) -> Self { + Self::File(FileOutput::Path(path)) + } +} + +pub struct Config<'a> { + pub output: Output, pub symbol_server: Option<&'a str>, - pub store: Option<&'a str>, pub debug_id: Option<&'a str>, pub code_id: Option<&'a str>, pub arch: &'a str, @@ -40,7 +87,7 @@ pub(crate) struct Config<'a> { pub mapping_file: Option<&'a str>, } -pub(crate) trait Creator: Mergeable + Dumpable + Sized { +pub trait Creator: Mergeable + Dumpable + Sized { fn get_dbg( arch: Arch, buf: &[u8], @@ -56,7 +103,7 @@ pub(crate) trait Creator: Mergeable + Dumpable + Sized { _filename: &str, _mapping: Option>, ) -> common::Result { - Err("Not implemented".into()) + anyhow::bail!("Not implemented") } } @@ -98,21 +145,27 @@ impl Creator for PDBInfo { } fn get_pe<'a>( - conf: &Config<'a>, - buf: &[u8], - path: &Path, - filename: &str, - mapping: Option>, + _conf: &Config<'a>, + _buf: &[u8], + _path: &Path, + _filename: &str, + _mapping: Option>, ) -> common::Result { - let symbol_server = cache::get_sym_servers(conf.symbol_server); - let res = windows::utils::get_pe_pdb_buf(path, buf, symbol_server.as_ref()); - - if let Some((pe, pdb_buf, pdb_name)) = res { - let pdb = Self::new(&pdb_buf, &pdb_name, filename, Some(pe), mapping)?; - Ok(pdb) - } else { - Err("No pdb file found".into()) + #[cfg(feature = "http")] + { + let symbol_server = crate::cache::get_sym_servers(_conf.symbol_server); + let res = windows::utils::get_pe_pdb_buf(_path, _buf, symbol_server.as_ref()); + + if let Some((pe, pdb_buf, pdb_name)) = res { + let pdb = Self::new(&pdb_buf, &pdb_name, _filename, Some(pe), _mapping)?; + Ok(pdb) + } else { + anyhow::bail!("No pdb file found") + } } + + #[cfg(not(feature = "http"))] + anyhow::bail!("HTTP symbol retrieval not enabled") } } @@ -124,7 +177,7 @@ impl Creator for PEInfo { _filename: &str, _mapping: Option>, ) -> common::Result { - Err("Not implemented".into()) + anyhow::bail!("Not implemented") } fn get_pe<'a>( @@ -141,61 +194,95 @@ impl Creator for PEInfo { } } -fn store, S2: AsRef>( - output: S1, - store: Option, - check_cfi: bool, - dumpable: D, -) -> common::Result<()> { - if check_cfi && !dumpable.has_stack() { - return Err("No CFI data".into()); - } +#[inline] +pub fn get_writer_for_sym(fo: &FileOutput) -> std::io::BufWriter> { + let output: Box = match fo { + FileOutput::Stdout => Box::new(std::io::stdout()), + FileOutput::Stderr => Box::new(std::io::stderr()), + FileOutput::Path(path) => { + let output = std::fs::File::create(path) + .unwrap_or_else(|_| panic!("Cannot open file {} for writing", path.display())); + Box::new(output) + } + }; + + std::io::BufWriter::new(output) +} + +fn store(output: &Output, check_cfi: bool, dumpable: D) -> common::Result<()> { + anyhow::ensure!(!check_cfi || dumpable.has_stack(), "No CFI data"); - let output = output.as_ref(); - let store = store.filter(|p| !p.as_ref().is_empty()).map(|p| { - PathBuf::from(p.as_ref()).join(cache::get_path_for_sym( + let sym_store_path = |dir: &Path| -> Option { + if dir.to_str()?.is_empty() { + return None; + } + + let mut pb = PathBuf::new(); + pb.push(dir); + pb.push(utils::get_path_for_sym( dumpable.get_name(), dumpable.get_debug_id(), - )) - }); - - if let Some(store) = store.as_ref() { + )); + Some(pb) + }; + + let (foutput, store) = match output { + Output::File(fo) => (Some(fo), None), + Output::Store(store) => (None, sym_store_path(store)), + Output::FileAndStore { + file, + store_directory, + } => (Some(file), sym_store_path(store_directory)), + }; + + if let Some(store) = store { fs::create_dir_all(store.parent().unwrap())?; - let store = store.to_str().unwrap(); - let output = utils::get_writer_for_sym(store); - if let Err(e) = dumpable.dump(output) { - return Err(e); - } - info!("Write symbols at {}", store); + + let fo = FileOutput::Path(store); + let output = get_writer_for_sym(&fo); + dumpable.dump(output)?; + + info!("Store symbols at {}", fo); } - if output != "-" || store.is_none() { - let output_stream = utils::get_writer_for_sym(output); - dumpable.dump(output_stream)?; - info!("Write symbols at {}", output); + if let Some(file) = foutput { + let writer = get_writer_for_sym(file); + dumpable.dump(writer)?; + + info!("Write symbols at {}", file); } Ok(()) } +#[cfg(feature = "http")] fn get_from_id( config: &Config, path: &Path, filename: String, ) -> common::Result<(Vec, String)> { if let Some(id) = config.debug_id.or(config.code_id) { - let symbol_server = cache::get_sym_servers(config.symbol_server); - let (buf, filename) = cache::search_file(filename, id, symbol_server.as_ref()); + let symbol_server = crate::cache::get_sym_servers(config.symbol_server); + let (buf, filename) = crate::cache::search_file(filename, id, symbol_server.as_ref()); return if let Some(buf) = buf { Ok((buf, filename)) } else { - Err(format!("Impossible to get file {} with id {}", filename, id).into()) + anyhow::bail!("Impossible to get file {} with id {}", filename, id) }; } Ok((utils::read_file(&path), filename)) } -pub(crate) fn single_file(config: &Config, filename: &str) -> common::Result<()> { +#[cfg(not(feature = "http"))] +fn get_from_id( + _config: &Config, + _path: &Path, + _filename: String, +) -> common::Result<(Vec, String)> { + anyhow::bail!("HTTP symbol retrieval not enabled") +} + +pub fn single_file(config: &Config, filename: &str) -> common::Result<()> { let path = Path::new(filename); let filename = utils::get_filename(path); @@ -207,40 +294,36 @@ pub(crate) fn single_file(config: &Config, filename: &str) -> common::Result<()> &config.mapping_file, )? .map(Arc::new); - let arch = Arch::from_str(config.arch).map_err(|e| e.compat())?; + let arch = Arch::from_str(config.arch)?; match FileType::from_buf(&buf) { FileType::Elf => store( - config.output, - config.store, + &config.output, config.check_cfi, ElfInfo::get_dbg(arch, &buf, path, &filename, file_mapping)?, ), FileType::Pdb => store( - config.output, - config.store, + &config.output, config.check_cfi, PDBInfo::get_dbg(arch, &buf, path, &filename, file_mapping)?, ), FileType::Pe => { if let Ok(pdb_info) = PDBInfo::get_pe(config, &buf, path, &filename, file_mapping) { - store(config.output, config.store, config.check_cfi, pdb_info) + store(&config.output, config.check_cfi, pdb_info) } else { store( - config.output, - config.store, + &config.output, config.check_cfi, PEInfo::get_pe(config, &buf, path, &filename, None)?, ) } } FileType::Macho => store( - config.output, - config.store, + &config.output, config.check_cfi, MachoInfo::get_dbg(arch, &buf, path, &filename, file_mapping)?, ), - FileType::Unknown => Err("Unknown file format".into()), + FileType::Unknown => anyhow::bail!("Unknown file format"), } } @@ -259,13 +342,12 @@ fn send_store_jobs( sender: &Sender>>, results: &mut HashMap, num_threads: usize, - output: &str, - store: &Option, + output: Output, check_cfi: bool, ) -> common::Result<()> { if results.len() == 1 { let (_, d) = results.drain().take(1).next().unwrap(); - self::store(&output, store.as_ref(), check_cfi, d)?; + self::store(&output, check_cfi, d)?; } else { for (_, d) in results.drain() { sender @@ -297,8 +379,7 @@ fn consumer( results: Arc>>, counter: Arc, num_threads: usize, - output: String, - store: Option, + output: Output, check_cfi: bool, ) -> common::Result<()> { while let Ok(job) = receiver.recv() { @@ -331,9 +412,7 @@ fn consumer( results.insert(info.get_debug_id().to_string(), info); } JobType::Dump(d) => { - let cwd = ".".to_string(); - let store = Some(store.as_ref().unwrap_or(&cwd)); - self::store(&output, store.as_ref(), check_cfi, d)?; + self::store(&output, check_cfi, d)?; continue; } } @@ -346,8 +425,7 @@ fn consumer( &sender, &mut results, num_threads, - &output, - &store, + output.clone(), check_cfi, )?; } else { @@ -358,7 +436,7 @@ fn consumer( Ok(()) } -pub(crate) fn several_files( +pub fn several_files( config: &Config, filenames: &[&str], ) -> common::Result<()> { @@ -369,7 +447,7 @@ pub(crate) fn several_files( &config.mapping_file, )? .map(Arc::new); - let arch = Arch::from_str(config.arch).map_err(|e| e.compat())?; + let arch = Arch::from_str(config.arch)?; let results = Arc::new(Mutex::new(HashMap::default())); let num_jobs = config.num_jobs.min(filenames.len()); let counter = Arc::new(AtomicUsize::new(filenames.len())); @@ -382,15 +460,15 @@ pub(crate) fn several_files( let receiver = receiver.clone(); let results = Arc::clone(&results); let counter = Arc::clone(&counter); - let output = config.output.to_string(); - let store = config.store.map(|s| s.to_string()); + let output = config.output.clone(); + let check_cfi = config.check_cfi; let t = thread::Builder::new() .name(format!("dump-syms {}", i)) .spawn(move || { consumer::( - arch, sender, receiver, results, counter, num_jobs, output, store, check_cfi, + arch, sender, receiver, results, counter, num_jobs, output, check_cfi, ) }) .unwrap(); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..9fe8b971 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,15 @@ +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +#[cfg(feature = "http")] +pub mod cache; +pub mod common; +pub mod dumper; +mod line; +pub mod linux; +pub mod mac; +pub mod mapping; +pub mod utils; +pub mod windows; diff --git a/src/linux/elf.rs b/src/linux/elf.rs index aec29942..fd11d63e 100644 --- a/src/linux/elf.rs +++ b/src/linux/elf.rs @@ -3,7 +3,6 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use failure::Fail; use hashbrown::HashMap; use log::{error, warn}; use std::collections::btree_map; @@ -295,7 +294,7 @@ impl Collector { o: &Object, source: &mut SourceFiles, ) -> common::Result<()> { - let ds = o.debug_session().map_err(|e| e.compat())?; + let ds = o.debug_session()?; let ds = if let ObjectDebugSession::Dwarf(ds) = ds { ds } else { @@ -364,7 +363,7 @@ impl ElfInfo { platform: Platform, mapping: Option>, ) -> common::Result { - let o = Object::parse(buf).map_err(|e| e.compat())?; + let o = Object::parse(buf)?; Self::from_object(&o, file_name, platform, mapping) } @@ -408,13 +407,12 @@ impl ElfInfo { impl Mergeable for ElfInfo { fn merge(left: ElfInfo, right: ElfInfo) -> common::Result { - if left.debug_id != right.debug_id { - return Err(format!( - "The files don't have the same debug id: {} and {}", - left.debug_id, right.debug_id - ) - .into()); - } + anyhow::ensure!( + left.debug_id == right.debug_id, + "The files don't have the same debug id: {} and {}", + left.debug_id, + right.debug_id + ); // Just to avoid to iterate on the bigger let (mut left, mut right) = if left.symbols.len() > right.symbols.len() { diff --git a/src/mac/macho.rs b/src/mac/macho.rs index a090ae6b..5855a15b 100644 --- a/src/mac/macho.rs +++ b/src/mac/macho.rs @@ -3,7 +3,6 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use failure::Fail; use std::fmt::{Display, Formatter}; use std::io::Write; use std::sync::Arc; @@ -35,7 +34,7 @@ impl MachoInfo { // Fat files may contain several objects for different architectures // So if there is only one object, then we don't care about the arch (as argument) // and if several then we use arch (by default it's compile-time arch). - let archive = Archive::parse(buf).map_err(|e| e.compat())?; + let archive = Archive::parse(buf)?; let object = if archive.object_count() == 1 { archive.object_by_index(0).unwrap() } else { @@ -50,18 +49,17 @@ impl MachoInfo { elf: ElfInfo::from_object(&object, file_name, Platform::Mac, mapping)?, }) } else { - Err(format!( + anyhow::bail!( "Cannot find a valid object for architecture {} in file {}", arch.name(), file_name - ) - .into()) + ); } } /// Print on screen the cpu arch for the different objects present in the fat file pub fn print_architectures(buf: &[u8], file_name: String) -> common::Result<()> { - let archive = Archive::parse(buf).map_err(|e| e.compat())?; + let archive = Archive::parse(buf)?; let archs = archive .objects() .map(|o| o.unwrap().arch().name()) diff --git a/src/main.rs b/src/main.rs index 65584930..2ce892a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,28 +3,17 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -mod action; -mod cache; -mod common; -mod dumper; -mod line; -mod linux; -mod mac; -mod mapping; -mod utils; -mod windows; - use clap::{crate_authors, crate_version, App, Arg}; use log::error; use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode}; use std::ops::Deref; use std::panic; -use crate::action::Action; -use crate::common::FileType; +mod action; -#[macro_use] -extern crate lazy_static; +use action::Action; +use dump_syms::common::{self, FileType}; +use dump_syms::dumper; fn main() { let matches = App::new("dump_syms") @@ -43,7 +32,6 @@ fn main() { .help("Output file or - for stdout") .short("o") .long("output") - .default_value("-") .takes_value(true), ) .arg( @@ -181,7 +169,7 @@ For example with --mapping-var="rev=123abc" --mapping-src="/foo/bar/(.*)" --mapp error!("A panic occurred at {}:{}: {}", filename, line, cause); })); - let output = matches.value_of("output").unwrap(); + let output = matches.value_of("output"); let filenames: Vec<_> = matches.values_of("filenames").unwrap().collect(); let symbol_server = matches.value_of("symbol-server"); let store = matches.value_of("store"); @@ -212,7 +200,7 @@ For example with --mapping-var="rev=123abc" --mapping-src="/foo/bar/(.*)" --mapp ); std::process::exit(1); } else { - let t = common::FileType::from_str(typ); + let t: common::FileType = typ.parse().unwrap(); match t { FileType::Elf | FileType::Macho | FileType::Pdb => t, _ => { @@ -228,10 +216,19 @@ For example with --mapping-var="rev=123abc" --mapping-src="/foo/bar/(.*)" --mapp let action = if matches.is_present("list_arch") { Action::ListArch } else { + let output = match (output, store) { + (Some(out), Some(store)) => dumper::Output::FileAndStore { + file: out.into(), + store_directory: store.into(), + }, + (Some(out), None) => dumper::Output::File(out.into()), + (None, Some(store)) => dumper::Output::Store(store.into()), + (None, None) => dumper::Output::File(dumper::FileOutput::Stdout), + }; + Action::Dump(dumper::Config { output, symbol_server, - store, debug_id, code_id, arch, diff --git a/src/mapping.rs b/src/mapping.rs index 77f9b39d..00a3a45a 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -112,7 +112,7 @@ impl PathMappingGenerator { } else if let Ok(group) = action.parse::() { ActionKind::Group(group) } else { - return Err(format!("Invalid action {} in mapping string", action).into()); + anyhow::bail!("Invalid action {} in mapping string", action); }; actions.push(Action { kind: action, @@ -211,9 +211,7 @@ impl PathMappings { if let Some(vars) = vars { for var in vars { let pair = var.splitn(2, '=').collect::>(); - if pair.len() != 2 { - return Err(format!("Invalid pair {}: must be var=value", var).into()); - } + anyhow::ensure!(pair.len() == 2, "Invalid pair {}: must be var=value", var); variables.insert(pair[0].to_string(), pair[1].to_string()); } } @@ -230,11 +228,10 @@ impl PathMappings { return Ok(()); } - if sources.as_ref().map_or(0, |v| v.len()) != destinations.as_ref().map_or(0, |v| v.len()) { - return Err( - "mapping-src and mapping-dest must have the same number of elements".into(), - ); - } + anyhow::ensure!( + sources.as_ref().map_or(0, |v| v.len()) == destinations.as_ref().map_or(0, |v| v.len()), + "mapping-src and mapping-dest must have the same number of elements" + ); let sources = sources.as_ref().unwrap(); let destinations = destinations.as_ref().unwrap(); diff --git a/src/utils.rs b/src/utils.rs index 60d24fd0..adc2cc16 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,7 +5,7 @@ use cab::Cabinet; use std::fs::{self, File, Metadata}; -use std::io::{self, BufWriter, Cursor, Read, Write}; +use std::io::{Cursor, Read}; use std::path::{Component, Path, PathBuf}; use crate::common; @@ -33,6 +33,42 @@ pub fn read_file>(path: P) -> Vec { .unwrap_or_else(|| panic!("Unable to read the cabinet file {}", path.to_str().unwrap())) } +pub(crate) fn get_base(file_name: &str) -> PathBuf { + // The file is stored at cache/xul.pdb/DEBUG_ID/xul.pd_ + // the xul.pdb represents the base + let mut path = PathBuf::from(file_name); + if let Some(e) = path.extension() { + let e = e.to_str().unwrap().to_lowercase(); + match e.as_str() { + "pd_" => { + path.set_extension("pdb"); + } + "ex_" => { + path.set_extension("exe"); + } + "dl_" => { + path.set_extension("dll"); + } + _ => {} + } + + path + } else { + path + } +} + +#[inline] +pub fn get_path_for_sym(file_name: &str, id: &str) -> PathBuf { + let mut pb = get_base(file_name); + + pb.push(id); + pb.push(file_name); + pb.set_extension("sym"); + + pb +} + pub fn get_mac_bundle>(metadata: &Metadata, path: P) -> Option<(Metadata, PathBuf)> { if metadata.is_dir() { // We may have a dSYM bundle @@ -129,18 +165,6 @@ fn get_cabinet_files(cab: &Cabinet>>, path: PathBuf) -> Option<( None } -pub fn get_writer_for_sym(file_name: &str) -> BufWriter> { - let output: Box = if file_name.is_empty() || file_name == "-" { - Box::new(io::stdout()) - } else { - let path = PathBuf::from(file_name); - let output = File::create(&path) - .unwrap_or_else(|_| panic!("Cannot open file {} for writing", path.to_str().unwrap())); - Box::new(output) - }; - BufWriter::new(output) -} - pub fn normalize_path>(path: P) -> PathBuf { // Copied from Cargo sources // https://github.com/rust-lang/cargo/blob/f534844c25cacc5e004404cea835ac85e35ca3fd/src/cargo/util/paths.rs#L60 diff --git a/src/windows/pdb.rs b/src/windows/pdb.rs index 2264c683..d7f6479c 100644 --- a/src/windows/pdb.rs +++ b/src/windows/pdb.rs @@ -3,7 +3,6 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use failure::Fail; use hashbrown::HashSet; use pdb::{ AddressMap, BlockSymbol, DebugInformation, FallibleIterator, MachineType, ModuleInfo, @@ -191,7 +190,7 @@ impl Collector { } } -pub(crate) struct PDBInfo { +pub struct PDBInfo { symbols: PDBSymbols, files: Vec, cpu: Cpu, @@ -259,10 +258,7 @@ fn get_stack_info(pdb_buf: Option<&[u8]>, pe: Option) -> String { let mut cfi_writer = AsciiCfiWriter::new(writer); if let Some(pe) = pe { if pe.has_unwind_info() { - cfi_writer - .process(&Object::Pe(pe)) - .map_err(|e| e.compat()) - .unwrap(); + cfi_writer.process(&Object::Pe(pe)).unwrap(); found_unwind_info = true; } } @@ -271,10 +267,7 @@ fn get_stack_info(pdb_buf: Option<&[u8]>, pe: Option) -> String { if let Some(pdb_buf) = pdb_buf { if let Ok(pdb) = PdbObject::parse(pdb_buf) { if pdb.has_unwind_info() { - cfi_writer - .process(&Object::Pdb(pdb)) - .map_err(|e| e.compat()) - .unwrap(); + cfi_writer.process(&Object::Pdb(pdb)).unwrap(); } } } @@ -585,7 +578,7 @@ impl Dumpable for PDBInfo { impl Mergeable for PDBInfo { fn merge(_left: PDBInfo, _right: PDBInfo) -> common::Result { - Err("PDB merge not implemented".into()) + anyhow::bail!("PDB merge not implemented") } } @@ -686,7 +679,7 @@ impl Dumpable for PEInfo { impl Mergeable for PEInfo { fn merge(_left: PEInfo, _right: PEInfo) -> common::Result { - Err("PE merge not implemented".into()) + anyhow::bail!("PE merge not implemented") } } diff --git a/src/windows/utils.rs b/src/windows/utils.rs index fd4f63ce..44407571 100644 --- a/src/windows/utils.rs +++ b/src/windows/utils.rs @@ -3,15 +3,16 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use log::warn; use std::path::Path; use symbolic::debuginfo::pe::PeObject; use uuid::Uuid; +#[cfg(feature = "http")] use crate::cache::{self, SymbolServer}; use crate::utils; use crate::windows::pdb::PDBInfo; +#[cfg(feature = "http")] fn try_to_find_pdb(path: &Path, pdb_filename: &str) -> Option> { // Just check that the file is in the same directory as the PE one let pdb = path.with_file_name(pdb_filename); @@ -34,6 +35,7 @@ fn try_to_find_pdb(path: &Path, pdb_filename: &str) -> Option> { None } +#[cfg(feature = "http")] fn os_specific_try_to_find_pdb(path: &Path, pdb_filename: &str) -> (Option>, String) { // We may have gotten either an OS native path, or a Windows path. // On Windows, they're both the same. On Unix, they are different, and in that case, @@ -54,6 +56,7 @@ fn os_specific_try_to_find_pdb(path: &Path, pdb_filename: &str) -> (Option( path: &Path, buf: &'a [u8], @@ -65,7 +68,7 @@ pub fn get_pe_pdb_buf<'a>( let pdb_filename = pdb_filename.into_owned(); let (pdb, pdb_name) = os_specific_try_to_find_pdb(path, &pdb_filename); if pdb_name.is_empty() { - warn!("Invalid pdb filename in PE file: \"{}\"", pdb_filename); + log::warn!("Invalid pdb filename in PE file: \"{}\"", pdb_filename); None } else if let Some(pdb_buf) = pdb { Some((pe, pdb_buf, pdb_name))