diff options
| author | Josh Ferrell <josh@vector35.com> | 2024-10-08 14:22:06 -0400 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2024-10-08 14:22:06 -0400 |
| commit | d6946973f49e6d6b181ed0efb6d40c23c8afdb7d (patch) | |
| tree | 3fa1a1af0a44aaf5fead1cc38a69b995d91f6d9c /rust | |
| parent | a81692cde97ba3a0b51b5fc43d2680a973a0e329 (diff) | |
Add support for zstd compressed DWARF, simplify handling of zlib compressed DWARF, improve DWARF error handling
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/Cargo.lock | 56 | ||||
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/src/lib.rs | 10 | ||||
| -rw-r--r-- | rust/examples/dwarf/shared/Cargo.toml | 2 | ||||
| -rw-r--r-- | rust/examples/dwarf/shared/src/lib.rs | 63 |
4 files changed, 100 insertions, 31 deletions
diff --git a/rust/Cargo.lock b/rust/Cargo.lock index e922d98e..2484a7ba 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -171,6 +171,17 @@ dependencies = [ ] [[package]] +name = "cc" +version = "1.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -361,6 +372,8 @@ version = "0.1.0" dependencies = [ "binaryninja", "gimli", + "thiserror", + "zstd", ] [[package]] @@ -532,6 +545,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -764,6 +786,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1214,3 +1242,31 @@ dependencies = [ "quote", "syn 2.0.52", ] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/rust/examples/dwarf/dwarf_import/src/lib.rs b/rust/examples/dwarf/dwarf_import/src/lib.rs index 114084a1..13c18a8c 100644 --- a/rust/examples/dwarf/dwarf_import/src/lib.rs +++ b/rust/examples/dwarf/dwarf_import/src/lib.rs @@ -385,7 +385,15 @@ fn parse_dwarf( let endian = get_endian(view); let mut section_reader = |section_id: SectionId| -> _ { create_section_reader(section_id, view, endian, dwo_file) }; - let mut dwarf = Dwarf::load(&mut section_reader).unwrap(); + + let mut dwarf = match Dwarf::load(&mut section_reader) { + Ok(x) => x, + Err(e) => { + error!("Failed to load DWARF info: {}", e); + return Err(()); + } + }; + if dwo_file { dwarf.file_type = DwarfFileType::Dwo; } diff --git a/rust/examples/dwarf/shared/Cargo.toml b/rust/examples/dwarf/shared/Cargo.toml index c5b9a978..ac20aac1 100644 --- a/rust/examples/dwarf/shared/Cargo.toml +++ b/rust/examples/dwarf/shared/Cargo.toml @@ -7,3 +7,5 @@ edition = "2021" [dependencies] binaryninja = {path="../../../"} gimli = "0.31" +zstd = "0.13.2" +thiserror = "1.0" diff --git a/rust/examples/dwarf/shared/src/lib.rs b/rust/examples/dwarf/shared/src/lib.rs index 7a957c6b..23baa42c 100644 --- a/rust/examples/dwarf/shared/src/lib.rs +++ b/rust/examples/dwarf/shared/src/lib.rs @@ -12,22 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -use gimli::{EndianRcSlice, Endianity, Error, RunTimeEndian, SectionId}; - -use binaryninja::binaryninjacore_sys::*; +use gimli::{EndianRcSlice, Endianity, RunTimeEndian, SectionId}; use binaryninja::{ binaryview::{BinaryView, BinaryViewBase, BinaryViewExt}, - databuffer::DataBuffer, Endianness, settings::Settings, }; -use std::{ffi::CString, rc::Rc}; +use std::rc::Rc; ////////////////////// // Dwarf Validation +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("unknown section compression method {0:#x}")] + UnknownCompressionMethod(u32), + + #[error("{0}")] + GimliError(#[from] gimli::Error), + + #[error("{0}")] + IoError(#[from] std::io::Error), +} + pub fn is_non_dwo_dwarf(view: &BinaryView) -> bool { view.section_by_name(".debug_info").is_ok() || view.section_by_name("__debug_info").is_ok() } @@ -134,32 +143,26 @@ pub fn create_section_reader<'a, Endian: 'a + Endianity>( let offset = section.start() + compressed_header_size as u64; let len = section.len() - compressed_header_size; - if let Ok(buffer) = view.read_buffer(offset, len) { - use std::ptr; - let transform_name = - CString::new("Zlib").unwrap().into_bytes_with_nul(); - let transform = - unsafe { BNGetTransformByName(transform_name.as_ptr() as *mut _) }; - - // Omega broke - let raw_buf: *mut BNDataBuffer = - unsafe { BNCreateDataBuffer(ptr::null_mut(), 0) }; - if unsafe { - BNDecode( - transform, - std::mem::transmute(buffer), - raw_buf, - ptr::null_mut(), - 0, - ) - } { - let output_buffer: DataBuffer = - unsafe { std::mem::transmute(raw_buf) }; + let ch_type_vec = view.read_vec(section.start(), 4); + let ch_type = endian.read_u32(&ch_type_vec); - return Ok(EndianRcSlice::new( - output_buffer.get_data().into(), - endian, - )); + if let Ok(buffer) = view.read_buffer(offset, len) { + match ch_type { + 1 => { + return Ok(EndianRcSlice::new( + buffer.zlib_decompress().get_data().into(), + endian, + )); + }, + 2 => { + return Ok(EndianRcSlice::new( + zstd::decode_all(buffer.get_data())?.as_slice().into(), + endian + )); + }, + x => { + return Err(Error::UnknownCompressionMethod(x)); + } } } } |
