summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2025-02-13 13:36:54 -0500
committerBrian Potchik <brian@vector35.com>2025-02-13 13:36:54 -0500
commitc99986fc66366ff205783add30401d341517b0e0 (patch)
tree18cdf2392fc376221a7be39f947cd917e9a186cd
parent3434b6a83ef7a424998b9bc1f95fc484dbf8d2de (diff)
Remove bintxt.
-rw-r--r--view/bintxt/CMakeLists.txt113
-rw-r--r--view/bintxt/Cargo.lock317
-rw-r--r--view/bintxt/Cargo.toml15
-rw-r--r--view/bintxt/build.rs15
-rw-r--r--view/bintxt/src/ihex.rs257
-rw-r--r--view/bintxt/src/lib.rs133
-rw-r--r--view/bintxt/src/srec.rs329
-rw-r--r--view/bintxt/src/titxt.rs267
8 files changed, 0 insertions, 1446 deletions
diff --git a/view/bintxt/CMakeLists.txt b/view/bintxt/CMakeLists.txt
deleted file mode 100644
index c3ce3b74..00000000
--- a/view/bintxt/CMakeLists.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
-
-project(view_bintext)
-
-file(GLOB PLUGIN_SOURCES CONFIGURE_DEPENDS
- ../../binaryninjacore.h
- ${PROJECT_SOURCE_DIR}/Cargo.toml
- ${PROJECT_SOURCE_DIR}/src/*.rs)
-
-if(CMAKE_BUILD_TYPE MATCHES Debug)
- set(TARGET_DIR ${PROJECT_BINARY_DIR}/target/debug)
- set(CARGO_OPTS --target-dir=${PROJECT_BINARY_DIR}/target)
-else()
- set(TARGET_DIR ${PROJECT_BINARY_DIR}/target/release)
- set(CARGO_OPTS --target-dir=${PROJECT_BINARY_DIR}/target --release)
-endif()
-
-if(FORCE_COLORED_OUTPUT)
- set(CARGO_OPTS ${CARGO_OPTS} --color always)
-endif()
-
-set(CARGO_FEATURES "")
-set(OUTPUT_FILE_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}view_bintxt${CMAKE_SHARED_LIBRARY_SUFFIX})
-set(OUTPUT_PDB_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}view_bintxt.pdb)
-set(OUTPUT_FILE_PATH ${BN_CORE_PLUGIN_DIR}/${OUTPUT_FILE_NAME})
-set(OUTPUT_PDB_PATH ${BN_CORE_PLUGIN_DIR}/${OUTPUT_PDB_NAME})
-
-set(BINJA_LIB_DIR ${BN_INSTALL_BIN_DIR})
-
-add_custom_target(view_bintext ALL DEPENDS ${OUTPUT_FILE_PATH})
-add_dependencies(view_bintext binaryninjaapi)
-get_target_property(BN_API_SOURCE_DIR binaryninjaapi SOURCE_DIR)
-list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake")
-find_package(BinaryNinjaCore REQUIRED)
-
-set_property(TARGET view_bintext PROPERTY OUTPUT_FILE_PATH ${OUTPUT_FILE_PATH})
-
-# Add the whole api to the depends too
-file(GLOB_RECURSE API_SOURCES CONFIGURE_DEPENDS
- ${BN_API_SOURCE_DIR}/rust/src/*.rs
- ${BN_API_SOURCE_DIR}/rust/binaryninjacore-sys/src/*.rs)
-
-find_program(RUSTUP_PATH rustup REQUIRED HINTS ~/.cargo/bin)
-set(RUSTUP_COMMAND ${RUSTUP_PATH} run ${CARGO_STABLE_VERSION} cargo)
-
-if(APPLE)
- if(UNIVERSAL)
- if(CMAKE_BUILD_TYPE MATCHES Debug)
- set(AARCH64_LIB_PATH ${PROJECT_BINARY_DIR}/target/aarch64-apple-darwin/debug/${OUTPUT_FILE_NAME})
- set(X86_64_LIB_PATH ${PROJECT_BINARY_DIR}/target/x86_64-apple-darwin/debug/${OUTPUT_FILE_NAME})
- else()
- set(AARCH64_LIB_PATH ${PROJECT_BINARY_DIR}/target/aarch64-apple-darwin/release/${OUTPUT_FILE_NAME})
- set(X86_64_LIB_PATH ${PROJECT_BINARY_DIR}/target/x86_64-apple-darwin/release/${OUTPUT_FILE_NAME})
- endif()
-
- add_custom_command(
- OUTPUT ${OUTPUT_FILE_PATH}
- COMMAND ${CMAKE_COMMAND} -E env
- MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BINJA_LIB_DIR}
- ${RUSTUP_COMMAND} clean --target=aarch64-apple-darwin ${CARGO_OPTS}
- COMMAND ${CMAKE_COMMAND} -E env
- MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BINJA_LIB_DIR}
- ${RUSTUP_COMMAND} clean --target=x86_64-apple-darwin ${CARGO_OPTS}
- COMMAND ${CMAKE_COMMAND} -E env
- MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BINJA_LIB_DIR}
- ${RUSTUP_COMMAND} build --target=aarch64-apple-darwin ${CARGO_OPTS} ${CARGO_FEATURES}
- COMMAND ${CMAKE_COMMAND} -E env
- MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BINJA_LIB_DIR}
- ${RUSTUP_COMMAND} build --target=x86_64-apple-darwin ${CARGO_OPTS} ${CARGO_FEATURES}
- COMMAND lipo -create ${AARCH64_LIB_PATH} ${X86_64_LIB_PATH} -output ${OUTPUT_FILE_PATH}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}
- )
- else()
- if(CMAKE_BUILD_TYPE MATCHES Debug)
- set(LIB_PATH ${PROJECT_BINARY_DIR}/target/debug/${OUTPUT_FILE_NAME})
- else()
- set(LIB_PATH ${PROJECT_BINARY_DIR}/target/release/${OUTPUT_FILE_NAME})
- endif()
-
- add_custom_command(
- OUTPUT ${OUTPUT_FILE_PATH}
- COMMAND ${CMAKE_COMMAND} -E env
- MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BINJA_LIB_DIR}
- ${RUSTUP_COMMAND} clean ${CARGO_OPTS}
- COMMAND ${CMAKE_COMMAND} -E env
- MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BINJA_LIB_DIR}
- ${RUSTUP_COMMAND} build ${CARGO_OPTS} ${CARGO_FEATURES}
- COMMAND ${CMAKE_COMMAND} -E copy ${LIB_PATH} ${OUTPUT_FILE_PATH}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}
- )
- endif()
-elseif(WIN32)
- add_custom_command(
- OUTPUT ${OUTPUT_FILE_PATH}
- COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BINJA_LIB_DIR} ${RUSTUP_COMMAND} clean ${CARGO_OPTS}
- COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BINJA_LIB_DIR} ${RUSTUP_COMMAND} build ${CARGO_OPTS} ${CARGO_FEATURES}
- COMMAND ${CMAKE_COMMAND} -E copy ${TARGET_DIR}/${OUTPUT_FILE_NAME} ${OUTPUT_FILE_PATH}
- COMMAND ${CMAKE_COMMAND} -E copy ${TARGET_DIR}/${OUTPUT_PDB_NAME} ${OUTPUT_PDB_PATH}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}
- )
-else()
- add_custom_command(
- OUTPUT ${OUTPUT_FILE_PATH}
- COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BINJA_LIB_DIR} ${RUSTUP_COMMAND} clean ${CARGO_OPTS}
- COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BINJA_LIB_DIR} ${RUSTUP_COMMAND} build ${CARGO_OPTS} ${CARGO_FEATURES}
- COMMAND ${CMAKE_COMMAND} -E copy ${TARGET_DIR}/${OUTPUT_FILE_NAME} ${OUTPUT_FILE_PATH}
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES}
- )
-endif()
diff --git a/view/bintxt/Cargo.lock b/view/bintxt/Cargo.lock
deleted file mode 100644
index 1e862160..00000000
--- a/view/bintxt/Cargo.lock
+++ /dev/null
@@ -1,317 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "binaryninja"
-version = "0.1.0"
-dependencies = [
- "binaryninjacore-sys",
- "log",
-]
-
-[[package]]
-name = "binaryninjacore-sys"
-version = "0.1.0"
-dependencies = [
- "bindgen",
- "proc-macro2",
-]
-
-[[package]]
-name = "bindgen"
-version = "0.71.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
-dependencies = [
- "bitflags",
- "cexpr",
- "clang-sys",
- "itertools",
- "log",
- "prettyplease",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash",
- "shlex",
- "syn",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
-
-[[package]]
-name = "cexpr"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "clang-sys"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "either"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
-
-[[package]]
-name = "glob"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
-
-[[package]]
-name = "ihex"
-version = "3.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2"
-
-[[package]]
-name = "itertools"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.155"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
-
-[[package]]
-name = "libloading"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
-dependencies = [
- "cfg-if",
- "windows-targets",
-]
-
-[[package]]
-name = "log"
-version = "0.4.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
-
-[[package]]
-name = "memchr"
-version = "2.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-
-[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "regex"
-version = "1.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
-
-[[package]]
-name = "rustc-hash"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
-
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "srec"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17c3a0538ec242e3cd333cdcdc8b720faa2fa0a9d7f444cf1ff63e7d3303adfb"
-
-[[package]]
-name = "syn"
-version = "2.0.72"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
-
-[[package]]
-name = "view_bintxt"
-version = "0.1.0"
-dependencies = [
- "binaryninja",
- "ihex",
- "log",
- "srec",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/view/bintxt/Cargo.toml b/view/bintxt/Cargo.toml
deleted file mode 100644
index 47740dbd..00000000
--- a/view/bintxt/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "view_bintxt"
-version = "0.1.0"
-authors = ["Rubens Brandao <git@rubens.io>"]
-edition = "2021"
-
-[dependencies]
-binaryninja.workspace = true
-binaryninjacore-sys.workspace = true
-ihex = "3.0.0"
-log = "0.4"
-srec = "0.2.0"
-
-[lib]
-crate-type = ["cdylib"] \ No newline at end of file
diff --git a/view/bintxt/build.rs b/view/bintxt/build.rs
deleted file mode 100644
index ed6cec7d..00000000
--- a/view/bintxt/build.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-fn main() {
- let link_path = std::env::var_os("DEP_BINARYNINJACORE_PATH")
- .expect("DEP_BINARYNINJACORE_PATH not specified");
-
- println!("cargo::rustc-link-lib=dylib=binaryninjacore");
- println!("cargo::rustc-link-search={}", link_path.to_str().unwrap());
-
- #[cfg(not(target_os = "windows"))]
- {
- println!(
- "cargo::rustc-link-arg=-Wl,-rpath,{0},-L{0}",
- link_path.to_string_lossy()
- );
- }
-}
diff --git a/view/bintxt/src/ihex.rs b/view/bintxt/src/ihex.rs
deleted file mode 100644
index b1cbfb80..00000000
--- a/view/bintxt/src/ihex.rs
+++ /dev/null
@@ -1,257 +0,0 @@
-use crate::segment_after_address;
-use crate::segment_from_address;
-use crate::sort_and_merge_segments;
-use crate::MergedSegment;
-use crate::UnmergedSegment;
-use binaryninja::binary_view::*;
-use binaryninja::custom_binary_view::*;
-use binaryninja::platform::Platform;
-use binaryninja::rc::Ref;
-use binaryninja::segment::SegmentBuilder;
-use binaryninja::settings::{QueryOptions, Settings};
-use ihex::Record;
-
-fn parse_ihex(string: &str) -> Result<(Vec<u8>, IHexViewData)> {
- let mut reader = ihex::Reader::new(&string);
- let mut unmerged_data: Vec<UnmergedSegment> = vec![];
- let mut start = None;
- let mut offset = None;
- while let Some(record) = reader.next() {
- let record = record.map_err(|e| {
- log::error!("Unable to parse record: {e}");
- ()
- })?;
- match record {
- ihex::Record::EndOfFile => break,
- ihex::Record::Data {
- offset: data_offset,
- value,
- } => {
- let address = match offset {
- Some(IHexOffset::Segment(offset)) => {
- u64::from(offset) * 16 + u64::from(data_offset)
- }
- Some(IHexOffset::Linear(offset)) => {
- u64::from(offset) << 16 | u64::from(data_offset)
- }
- None => data_offset.into(),
- };
- // check if the block is just extending the previous one
- match unmerged_data.last_mut() {
- // check if the block is just extending the previous one, merge both
- Some(last) if last.end() == address => last.data.extend(value),
- // otherwise just add a new block
- _ => unmerged_data.push(UnmergedSegment {
- address,
- data: value,
- }),
- }
- }
- ihex::Record::StartSegmentAddress { cs, ip } => {
- if start.is_some() {
- log::error!("Multiple Start Address defined");
- return Err(());
- }
- start = Some(IHexStart::Segment { _cs: cs, ip });
- }
- ihex::Record::StartLinearAddress(offset) => {
- if start.is_some() {
- log::error!("Multiple Start Address defined");
- return Err(());
- }
- start = Some(IHexStart::Linear(offset));
- }
- ihex::Record::ExtendedSegmentAddress(segment_offset) => {
- offset = Some(IHexOffset::Segment(segment_offset))
- }
- ihex::Record::ExtendedLinearAddress(linear_offset) => {
- offset = Some(IHexOffset::Linear(linear_offset))
- }
- }
- }
- // can't have other record after the EoF record
- if reader.next().is_some() {
- log::error!("Found record after EoF record");
- return Err(());
- }
-
- let merged = sort_and_merge_segments(unmerged_data)?;
- Ok((
- merged.data,
- IHexViewData {
- segments: merged.segments,
- start,
- },
- ))
-}
-
-pub struct IHexViewConstructor {
- pub core: BinaryViewType,
-}
-
-impl AsRef<BinaryViewType> for IHexViewConstructor {
- fn as_ref(&self) -> &BinaryViewType {
- &self.core
- }
-}
-
-impl CustomBinaryViewType for IHexViewConstructor {
- fn create_custom_view<'builder>(
- &self,
- parent: &BinaryView,
- builder: CustomViewBuilder<'builder, Self>,
- ) -> Result<CustomView<'builder>> {
- let bytes = parent.len() as usize;
- let mut buf = vec![0; bytes];
- let bytes_read = parent.read(&mut buf, 0);
- if bytes_read != bytes {
- log::error!("IHex file is too small");
- return Err(());
- }
- let string = String::from_utf8(buf).map_err(|_| {
- log::error!("File contains invalid UTF8 characters");
- })?;
-
- let (data, segments) = parse_ihex(&string)?;
-
- let parent_bin = BinaryView::from_data(&parent.file(), &data)?;
- builder.create::<IHexView>(&parent_bin, segments)
- }
-}
-
-impl BinaryViewTypeBase for IHexViewConstructor {
- fn is_valid_for(&self, data: &BinaryView) -> bool {
- // TODO check filename and identify the type if necessary
- //let filename = data.file().filename();
- //let filename = std::path::Path::new(filename.as_str());
- //let filetype = filename
- // .extension()
- // .map(|ext| match ext.to_string_lossy().as_ref() {
- // // General-purpose:
- // "hex" | "mcs" | "int" | "ihex" | "ihe" | "ihx" => true,
- // // Platform-specific:
- // "h80" | "h86" | "a43" | "a90" => Some(true),
- // // Binary or Intel hex:
- // "obj" | "obl" | "obh" | "rom" | "eep" => true,
- // // TODO: Split, banked, or paged:
- // //.hxl–.hxh,[8] .h00–.h15, .p00–.pff[9]
- // _ => false,
- // });
-
- // The biggest possible record is data record with 255 bytes: 268 bytes
- let mut first_bytes = [0u8; 384];
- let read_bytes = data.read(&mut first_bytes, 0);
- let data = String::from_utf8_lossy(&first_bytes[0..read_bytes]);
- let Some(line) = data.lines().next() else {
- return false;
- };
- Record::from_record_string(line).is_ok()
- }
-
- fn is_deprecated(&self) -> bool {
- false
- }
-
- fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
- self.default_load_settings_for_data(&data).map(|s| {
- s.update_bool_property("loader.platform", "readOnly", false);
- s.update_bool_property("loader.imageBase", "readOnly", false);
- s.update_bool_property("loader.segments", "readOnly", false);
- s
- })
- }
-}
-
-pub struct IHexView {
- core: Ref<BinaryView>,
- segments: Vec<MergedSegment>,
- start: Option<IHexStart>,
-}
-
-pub struct IHexViewData {
- segments: Vec<MergedSegment>,
- start: Option<IHexStart>,
-}
-
-#[derive(Clone, Copy, Debug)]
-enum IHexStart {
- Segment { _cs: u16, ip: u16 },
- Linear(u32),
-}
-
-#[derive(Clone, Copy, Debug)]
-enum IHexOffset {
- Segment(u16),
- Linear(u16),
-}
-
-impl AsRef<BinaryView> for IHexView {
- fn as_ref(&self) -> &BinaryView {
- &self.core
- }
-}
-
-unsafe impl CustomBinaryView for IHexView {
- type Args = IHexViewData;
-
- fn new(handle: &BinaryView, _args: &Self::Args) -> Result<Self> {
- Ok(Self {
- core: handle.to_owned(),
- // NOTE dummy values, final values are added on init
- start: None,
- segments: vec![],
- })
- }
-
- fn init(&mut self, IHexViewData { start, segments }: Self::Args) -> Result<()> {
- self.start = start;
- self.segments = segments;
-
- for segment in self.segments.iter() {
- self.add_segment(
- SegmentBuilder::from(*segment)
- .executable(true)
- .readable(true)
- .contains_data(true)
- .contains_code(true),
- );
- }
-
- // TODO: Because we detached from the raw view this setting will never be set.
- let mut settings_query_opts = QueryOptions::new_with_view(&self.core);
- let _ = self.core.load_settings(self.type_name()).map(|s| {
- let platform_name = s.get_string_with_opts("loader.platform", &mut settings_query_opts);
- if let Some(platform) = Platform::by_name(platform_name) {
- self.set_default_platform(&platform);
- }
- });
-
- Ok(())
- }
-}
-
-impl BinaryViewBase for IHexView {
- fn entry_point(&self) -> u64 {
- match self.start {
- Some(IHexStart::Linear(addr)) => addr.into(),
- Some(IHexStart::Segment { _cs, ip }) => ip.into(),
- None => self.start(),
- }
- }
-
- fn default_endianness(&self) -> binaryninja::Endianness {
- binaryninja::Endianness::LittleEndian
- }
-
- fn address_size(&self) -> usize {
- 4
- }
-
- fn offset_valid(&self, offset: u64) -> bool {
- segment_from_address(&self.segments, offset).is_some()
- }
-
- fn next_valid_offset_after(&self, offset: u64) -> u64 {
- segment_after_address(&self.segments, offset)
- }
-}
diff --git a/view/bintxt/src/lib.rs b/view/bintxt/src/lib.rs
deleted file mode 100644
index 4627c654..00000000
--- a/view/bintxt/src/lib.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-mod ihex;
-mod srec;
-mod titxt;
-
-use binaryninja::segment::SegmentBuilder;
-use ihex::*;
-use srec::*;
-use titxt::*;
-
-use binaryninja::logger::Logger;
-use log::LevelFilter;
-use std::ops::Range;
-
-#[no_mangle]
-#[allow(non_snake_case)]
-pub extern "C" fn CorePluginInit() -> bool {
- Logger::new("BINTXT").with_level(LevelFilter::Info).init();
-
- binaryninja::custom_binary_view::register_view_type(c"ti-txt", c"TI-TXT", |core| {
- TiTxtViewConstructor { core }
- });
-
- binaryninja::custom_binary_view::register_view_type(c"srec", c"Motorola S-record", |core| {
- SRecViewConstructor { core }
- });
-
- binaryninja::custom_binary_view::register_view_type(c"ihex", c"Intel HEX", |core| {
- IHexViewConstructor { core }
- });
-
- true
-}
-
-struct UnmergedSegment {
- address: u64,
- data: Vec<u8>,
-}
-
-impl UnmergedSegment {
- fn end(&self) -> u64 {
- self.address + u64::try_from(self.data.len()).unwrap()
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct MergedSegment {
- address: u64,
- len: u64,
- data_offset: u64,
-}
-
-impl MergedSegment {
- fn address_range(&self) -> Range<u64> {
- self.address..self.end()
- }
-
- fn data_range(&self) -> Range<u64> {
- self.data_offset..self.data_offset + self.len
- }
-
- fn end(&self) -> u64 {
- self.address + self.len
- }
-}
-
-impl From<MergedSegment> for SegmentBuilder {
- fn from(segment: MergedSegment) -> Self {
- SegmentBuilder::new(segment.address_range()).parent_backing(segment.data_range())
- }
-}
-
-struct MergedSegments {
- data: Vec<u8>,
- segments: Vec<MergedSegment>,
-}
-
-fn sort_and_merge_segments(mut unmerged_data: Vec<UnmergedSegment>) -> Result<MergedSegments, ()> {
- // sort segments by address and len, so we can detect overlaps
- unmerged_data.sort_unstable_by_key(|segment| (segment.address, segment.data.len()));
-
- let mut data: Vec<u8> =
- Vec::with_capacity(unmerged_data.iter().map(|sector| sector.data.len()).sum());
- let mut segments: Vec<MergedSegment> = Vec::with_capacity(unmerged_data.len());
- for segment in unmerged_data.into_iter() {
- // add the data to the data poll
- let data_offset = u64::try_from(data.len()).unwrap();
- let segment_len = u64::try_from(segment.data.len()).unwrap();
- data.extend(segment.data);
- match segments.last_mut() {
- // if have a last segment and the current chunk just extend it, merge both
- Some(last) if segment.address == last.end() => last.len += segment_len,
- // the same sector overlap, then the data was defined multiple times.
- Some(last) if segment.address < last.end() => {
- log::error!("Chunks of data overlap");
- return Err(());
- }
- // otherwise just create a new segment
- _ => segments.push(MergedSegment {
- address: segment.address,
- len: segment_len,
- data_offset,
- }),
- }
- }
-
- Ok(MergedSegments { data, segments })
-}
-
-fn segment_from_address(segments: &[MergedSegment], offset: u64) -> Option<&MergedSegment> {
- segments
- .binary_search_by(|segment| {
- let range = segment.address_range();
- if range.contains(&offset) {
- return core::cmp::Ordering::Equal;
- }
- offset.cmp(&range.start)
- })
- .ok()
- .map(|idx| &segments[idx])
-}
-
-fn segment_after_address(segments: &[MergedSegment], offset: u64) -> u64 {
- let sector = segments.iter().find_map(|sector| {
- if sector.address >= offset {
- Some(sector.address)
- } else if sector.end() < offset {
- Some(offset)
- } else {
- None
- }
- });
- sector.unwrap_or(offset).into()
-}
diff --git a/view/bintxt/src/srec.rs b/view/bintxt/src/srec.rs
deleted file mode 100644
index beba98b0..00000000
--- a/view/bintxt/src/srec.rs
+++ /dev/null
@@ -1,329 +0,0 @@
-use binaryninja::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt};
-use binaryninja::custom_binary_view::{
- BinaryViewType, BinaryViewTypeBase, CustomBinaryView, CustomBinaryViewType, CustomView,
- CustomViewBuilder,
-};
-use binaryninja::rc::Ref;
-use binaryninja::segment::SegmentBuilder;
-use srec::Record;
-
-use crate::{
- segment_after_address, segment_from_address, sort_and_merge_segments, MergedSegment,
- UnmergedSegment,
-};
-
-struct SRecParser<I> {
- reader: I,
- segments: Vec<UnmergedSegment>,
- sector_counter: u32,
- start: u32,
-}
-
-#[derive(Clone, Copy, PartialEq, Eq)]
-enum RecordLen {
- R16,
- R24,
- R32,
-}
-
-impl<I: Iterator<Item = Result<Record, srec::ReaderError>>> SRecParser<I> {
- fn parse(&mut self) -> Result<(), ()> {
- // first sector need to be the header
- let header = self.reader.next();
- let header = header
- .ok_or_else(|| {
- log::error!("Missing header record");
- })?
- .map_err(|e| {
- log::error!("Unable to parse header record: {e}");
- })?;
-
- let Record::S0(_header_info) = header else {
- log::error!("Invalid first record");
- return Err(());
- };
-
- // parse the first data record
- let second_record = self
- .reader
- .next()
- .ok_or_else(|| {
- log::error!("Missing first data record");
- })?
- .map_err(|e| {
- log::error!("Unable to parse first data record: {e}");
- })?;
- let (addr_len, first_data_addr, first_data) = match second_record {
- Record::S0(_)
- | Record::S5(_)
- | Record::S6(_)
- | Record::S7(_)
- | Record::S8(_)
- | Record::S9(_) => {
- log::error!("Invalid second record type");
- return Err(());
- }
- Record::S1(s) => (RecordLen::R16, u32::from(s.address).into(), s.data),
- Record::S2(s) => (RecordLen::R24, u32::from(s.address).into(), s.data),
- Record::S3(s) => (RecordLen::R32, u32::from(s.address).into(), s.data),
- };
- self.sector_counter = 1;
- self.segments.push(UnmergedSegment {
- address: first_data_addr,
- data: first_data,
- });
-
- // parse zero or more data after the first until hit a Count (S5, S6)
- // or Start Address (S7, S8, S9) Record
- let next = loop {
- let record = self
- .reader
- .next()
- .ok_or_else(|| {
- log::error!("Final record can't be data");
- })?
- .map_err(|e| {
- log::error!("Unable to parse record: {e}");
- })?;
- match record {
- Record::S0(_) => {
- log::error!("Multiple header records");
- return Err(());
- }
- Record::S1(s) if addr_len == RecordLen::R16 => {
- self.add_record_data(u32::from(s.address).into(), s.data)
- }
- Record::S2(s) if addr_len == RecordLen::R24 => {
- self.add_record_data(u32::from(s.address).into(), s.data)
- }
- Record::S3(s) if addr_len == RecordLen::R32 => {
- self.add_record_data(u32::from(s.address).into(), s.data)
- }
- Record::S1(_) | Record::S2(_) | Record::S3(_) => {
- log::error!("Data record with invalid len");
- return Err(());
- }
- other @ (Record::S5(_)
- | Record::S6(_)
- | Record::S7(_)
- | Record::S8(_)
- | Record::S9(_)) => break other,
- }
- };
-
- // S5/S6 is an opional last-but-one record
- let last = match next {
- Record::S0(_) | Record::S1(_) | Record::S2(_) | Record::S3(_) => {
- unreachable!()
- }
- Record::S5(s) => {
- self.check_count_record(s.into())?;
- self.reader.next()
- }
- Record::S6(s) => {
- self.check_count_record(s.into())?;
- self.reader.next()
- }
- s @ (Record::S7(_) | Record::S8(_) | Record::S9(_)) => Some(Ok(s)),
- };
-
- // the last record need to be S7 | S8 | S9
- let last = last
- .ok_or_else(|| {
- log::error!("Missing last record");
- })?
- .map_err(|e| {
- log::error!("Unable to parse last record: {e}");
- })?;
- match last {
- Record::S7(s) => self.start = s.into(),
- Record::S8(s) => self.start = s.into(),
- Record::S9(s) => self.start = s.into(),
- _ => {
- log::error!("Invalid last record type");
- return Err(());
- }
- }
-
- // can't have any record after S7 | S8 | S9
- if let Some(_s) = self.reader.next() {
- log::error!("Records found after the last");
- return Err(());
- }
-
- Ok(())
- }
-
- fn add_record_data(&mut self, address: u64, data: Vec<u8>) {
- self.sector_counter += 1;
- match self.segments.last_mut() {
- // check if the block is just extending the previous one, merge both
- Some(last) if last.end() == address => {
- last.data.extend(data);
- }
- // otherwise just add a new block
- _ => {
- self.segments.push(UnmergedSegment { address, data });
- }
- }
- }
-
- fn check_count_record(&self, value: u32) -> Result<(), ()> {
- if value != self.sector_counter {
- log::error!("Invalid number of records");
- Err(())
- } else {
- Ok(())
- }
- }
-}
-
-fn parse_srec(data: &str) -> Result<(Vec<u8>, SRecViewData), ()> {
- let mut parser = SRecParser {
- reader: srec::reader::read_records(&data),
- segments: vec![],
- sector_counter: 0,
- start: 0,
- };
- parser.parse()?;
-
- let segments = sort_and_merge_segments(parser.segments)?;
- Ok((
- segments.data,
- SRecViewData {
- segments: segments.segments,
- start: parser.start,
- },
- ))
-}
-
-pub struct SRecViewConstructor {
- pub core: BinaryViewType,
-}
-
-impl AsRef<BinaryViewType> for SRecViewConstructor {
- fn as_ref(&self) -> &BinaryViewType {
- &self.core
- }
-}
-impl CustomBinaryViewType for SRecViewConstructor {
- fn create_custom_view<'builder>(
- &self,
- parent: &BinaryView,
- builder: CustomViewBuilder<'builder, Self>,
- ) -> Result<CustomView<'builder>, ()> {
- let bytes = parent.len() as usize;
- let mut buf = vec![0; bytes];
- let bytes_read = parent.read(&mut buf, 0);
- if bytes_read != bytes {
- log::error!("IHex file is too small");
- return Err(());
- }
- let string = String::from_utf8(buf).map_err(|_| {
- log::error!("File contains invalid UTF8 characters");
- })?;
- let (data, regs) = parse_srec(&string)?;
-
- let parent_bin = BinaryView::from_data(&parent.file(), &data)?;
- builder.create::<SRecView>(&parent_bin, regs)
- }
-}
-
-impl BinaryViewTypeBase for SRecViewConstructor {
- fn is_valid_for(&self, data: &BinaryView) -> bool {
- // TODO check filename and identify the type if necessary
- //let filename = data.file().filename();
- //let filename = std::path::Path::new(filename.as_str());
- //let filetype = filename
- // .extension()
- // .map(|ext| match ext.to_string_lossy().as_ref() {
- // "s19" | "s28" | "s37" | "s" | "s1" | "s2" | "s3" | "sx" | "srec" | "exo"
- // | "mot" | "mxt" => true,
- // _ => false,
- // });
-
- // The biggest possible record line is 269
- const READ_LEN: usize = 384;
- let mut first_bytes = [0u8; READ_LEN];
- let read_bytes = data.read(&mut first_bytes, 0);
- let line = String::from_utf8_lossy(&first_bytes[0..read_bytes]);
- if !line.is_ascii() {
- return false;
- }
- let first_record: Result<Record, _> = line.parse();
- // first record need to be and S0
- matches!(first_record, Ok(Record::S0(_)))
- }
-
- fn is_deprecated(&self) -> bool {
- false
- }
-}
-
-pub struct SRecView {
- core: Ref<BinaryView>,
- segments: Vec<MergedSegment>,
- start: u32,
-}
-
-pub struct SRecViewData {
- segments: Vec<MergedSegment>,
- start: u32,
-}
-
-impl AsRef<BinaryView> for SRecView {
- fn as_ref(&self) -> &BinaryView {
- &self.core
- }
-}
-
-unsafe impl CustomBinaryView for SRecView {
- type Args = SRecViewData;
-
- fn new(handle: &BinaryView, _args: &Self::Args) -> Result<Self, ()> {
- Ok(Self {
- core: handle.to_owned(),
- // NOTE dummy values, final values are added on init
- start: 0,
- segments: vec![],
- })
- }
-
- fn init(&mut self, SRecViewData { start, segments }: Self::Args) -> Result<(), ()> {
- self.start = start;
- self.segments = segments;
-
- for segment in self.segments.iter() {
- self.add_segment(
- SegmentBuilder::from(*segment)
- .executable(true)
- .readable(true)
- .contains_data(true)
- .contains_code(true),
- );
- }
- Ok(())
- }
-}
-
-impl BinaryViewBase for SRecView {
- fn entry_point(&self) -> u64 {
- self.start.into()
- }
-
- fn default_endianness(&self) -> binaryninja::Endianness {
- binaryninja::Endianness::LittleEndian
- }
-
- fn address_size(&self) -> usize {
- 4
- }
-
- fn offset_valid(&self, offset: u64) -> bool {
- segment_from_address(&self.segments, offset).is_some()
- }
-
- fn next_valid_offset_after(&self, offset: u64) -> u64 {
- segment_after_address(&self.segments, offset)
- }
-}
diff --git a/view/bintxt/src/titxt.rs b/view/bintxt/src/titxt.rs
deleted file mode 100644
index d9b766e4..00000000
--- a/view/bintxt/src/titxt.rs
+++ /dev/null
@@ -1,267 +0,0 @@
-use binaryninja::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt};
-use binaryninja::custom_binary_view::{
- BinaryViewType, BinaryViewTypeBase, CustomBinaryView, CustomBinaryViewType, CustomView,
- CustomViewBuilder,
-};
-use binaryninja::rc::Ref;
-use binaryninja::segment::SegmentBuilder;
-
-use crate::{
- segment_after_address, segment_from_address, sort_and_merge_segments, MergedSegment,
- MergedSegments, UnmergedSegment,
-};
-
-fn hex_to_byte(char: u8) -> Option<u8> {
- match char {
- b'0'..=b'9' => Some(char - b'0'),
- b'a'..=b'f' => Some(0xa + (char - b'a')),
- b'A'..=b'F' => Some(0xA + (char - b'A')),
- _ => None,
- }
-}
-
-fn take_address(input: &[u8]) -> Result<(u16, &[u8]), ()> {
- let [b'@', b1, b2, b3, b4, rest @ ..] = input else {
- return Err(());
- };
- let b1 = hex_to_byte(*b1).map(u16::from).ok_or(())?;
- let b2 = hex_to_byte(*b2).map(u16::from).ok_or(())?;
- let b3 = hex_to_byte(*b3).map(u16::from).ok_or(())?;
- let b4 = hex_to_byte(*b4).map(u16::from).ok_or(())?;
- let value = b1 << 12 | b2 << 8 | b3 << 4 | b4;
- Ok((value, rest))
-}
-
-fn take_byte(input: &[u8]) -> Option<(u8, &[u8])> {
- let [b1, b2, rest @ ..] = input else {
- return None;
- };
- let b1 = hex_to_byte(*b1)?;
- let b2 = hex_to_byte(*b2)?;
- let value = b1 << 4 | b2;
- Some((value, rest))
-}
-
-fn take_newline(input: &[u8]) -> Option<&[u8]> {
- match input {
- [b'\r', b'\n', rest @ ..] => Some(rest),
- [b'\n', rest @ ..] => Some(rest),
- _ => None,
- }
-}
-
-// take 0 or more newlines
-fn take_newlines(mut input: &[u8]) -> (usize, &[u8]) {
- let mut counter = 0;
- while let Some(rest) = take_newline(input) {
- input = rest;
- counter += 1;
- }
- (counter, input)
-}
-
-fn take_byte_line(input: &[u8]) -> Result<(Vec<u8>, &[u8]), ()> {
- // a line can be 16 bytes long, or less in case it's the last line
- let mut current_input = input;
- let mut bytes = Vec::with_capacity(16);
-
- // line need to have at least one line
- for _i in 0..16 {
- let (byte, rest) =
- take_byte(current_input).ok_or_else(|| log::error!("Unable to parse byte"))?;
- current_input = rest;
- bytes.push(byte);
-
- match current_input {
- // space with newline ends this line
- [b' ', b'\r', b'\n', rest @ ..] | [b' ', b'\n', rest @ ..] => return Ok((bytes, rest)),
- // bytes are separated by space
- [b' ', rest @ ..] => current_input = rest,
- // newline ends this line
- [b'\r', b'\n', rest @ ..] | [b'\n', rest @ ..] => return Ok((bytes, rest)),
- // other chars are forbidden
- _ => {
- log::error!("Invalid character on data bytes");
- return Err(());
- }
- }
- }
- // can't have more then 16 bytes
- log::error!("Bytes line is too long");
- Err(())
-}
-
-fn parse_sections(input: &[u8]) -> Result<(UnmergedSegment, &[u8]), ()> {
- // get the address part of the section
- let (address, input) =
- take_address(input).map_err(|_| log::error!("Unable to parse Address"))?;
- let mut input =
- take_newline(input).ok_or_else(|| log::error!("Unable to find Address delimiter"))?;
-
- // get one or more bytes
- let mut data = vec![];
- let rest = loop {
- let (line, rest) = take_byte_line(input)?;
- let line_len = line.len();
- data.extend(line);
- input = rest;
-
- // allow sections to be separated by multiple spaces
- let (new_lines, rest) = take_newlines(input);
- input = rest;
-
- match input {
- // if after a line we find a 'q', then we found the end of file
- b"q" | b"q\n" | b"q\r\n" => break &[][..],
-
- // end of file, but with data after
- [b'q', ..] => {
- log::error!("Found data after the end section");
- return Err(());
- }
-
- // found the next sector
- [b'@', ..] => break input,
-
- // NOTE: only the last line is allowed to be less then 16 bytes,
- // if less then 16 it's the end of a sector, so we need
- // find a new sector or end of file
- // NOTE: bytes can't be separated by multiple lines, only sections can
- _ if line_len != 16 || new_lines > 0 => {
- log::error!("Unable to find end of section");
- return Err(());
- }
-
- // line is followed by other line of bytes
- _ => {}
- }
- };
-
- let segment = UnmergedSegment {
- address: address.into(),
- data,
- };
- Ok((segment, rest))
-}
-
-fn parse_ti_txt(data: &[u8]) -> Result<MergedSegments, ()> {
- let mut current_data = data;
- let mut unmerged_segments = vec![];
- while !current_data.is_empty() {
- let (section, rest) = parse_sections(current_data)?;
- current_data = rest;
-
- unmerged_segments.push(section);
- }
- sort_and_merge_segments(unmerged_segments)
-}
-
-pub struct TiTxtViewConstructor {
- pub core: BinaryViewType,
-}
-
-impl AsRef<BinaryViewType> for TiTxtViewConstructor {
- fn as_ref(&self) -> &BinaryViewType {
- &self.core
- }
-}
-
-impl CustomBinaryViewType for TiTxtViewConstructor {
- fn create_custom_view<'builder>(
- &self,
- parent: &BinaryView,
- builder: CustomViewBuilder<'builder, Self>,
- ) -> Result<CustomView<'builder>, ()> {
- let bytes = parent.len() as usize;
- let mut buf = vec![0; bytes];
- let bytes_read = parent.read(&mut buf, 0);
- if bytes_read != bytes {
- log::error!("IHex file is too small");
- return Err(());
- }
- let sectors = parse_ti_txt(&buf)?;
-
- let parent_bin = BinaryView::from_data(&parent.file(), &sectors.data)?;
- builder.create::<TiTxtView>(&parent_bin, sectors.segments)
- }
-}
-
-impl BinaryViewTypeBase for TiTxtViewConstructor {
- fn is_valid_for(&self, data: &BinaryView) -> bool {
- let mut first_bytes = [0u8; 16];
- let read_bytes = data.read(&mut first_bytes, 0);
-
- let [b'@', b1, b2, b3, b4, b'\r' | b'\n', ..] = first_bytes[0..read_bytes] else {
- return false;
- };
- b1.is_ascii_hexdigit()
- && b2.is_ascii_hexdigit()
- && b3.is_ascii_hexdigit()
- && b4.is_ascii_hexdigit()
- }
-
- fn is_deprecated(&self) -> bool {
- false
- }
-}
-
-pub struct TiTxtView {
- core: Ref<BinaryView>,
- segments: Vec<MergedSegment>,
-}
-
-impl AsRef<BinaryView> for TiTxtView {
- fn as_ref(&self) -> &BinaryView {
- &self.core
- }
-}
-
-unsafe impl CustomBinaryView for TiTxtView {
- type Args = Vec<MergedSegment>;
-
- fn new(handle: &BinaryView, _args: &Self::Args) -> Result<Self, ()> {
- Ok(Self {
- core: handle.to_owned(),
- // NOTE dummy value, final values are added on init
- segments: vec![],
- })
- }
-
- fn init(&mut self, segments: Self::Args) -> Result<(), ()> {
- self.segments = segments;
-
- for segment in self.segments.iter() {
- self.add_segment(
- SegmentBuilder::from(*segment)
- .executable(true)
- .readable(true)
- .contains_data(true)
- .contains_code(true),
- );
- }
- Ok(())
- }
-}
-
-impl BinaryViewBase for TiTxtView {
- fn entry_point(&self) -> u64 {
- // NOTE: TI TXT don't have any entry point information
- self.segments.first().map(|s| s.address.into()).unwrap_or(0)
- }
-
- fn default_endianness(&self) -> binaryninja::Endianness {
- binaryninja::Endianness::LittleEndian
- }
-
- fn address_size(&self) -> usize {
- 4
- }
-
- fn offset_valid(&self, offset: u64) -> bool {
- segment_from_address(&self.segments, offset).is_some()
- }
-
- fn next_valid_offset_after(&self, offset: u64) -> u64 {
- segment_after_address(&self.segments, offset)
- }
-}