summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2024-10-08 14:22:06 -0400
committerJosh Ferrell <josh@vector35.com>2024-10-08 14:22:06 -0400
commitd6946973f49e6d6b181ed0efb6d40c23c8afdb7d (patch)
tree3fa1a1af0a44aaf5fead1cc38a69b995d91f6d9c /rust
parenta81692cde97ba3a0b51b5fc43d2680a973a0e329 (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.lock56
-rw-r--r--rust/examples/dwarf/dwarf_import/src/lib.rs10
-rw-r--r--rust/examples/dwarf/shared/Cargo.toml2
-rw-r--r--rust/examples/dwarf/shared/src/lib.rs63
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));
+ }
}
}
}