diff --git a/view/ihex/Cargo.lock b/view/bintxt/Cargo.lock similarity index 97% rename from view/ihex/Cargo.lock rename to view/bintxt/Cargo.lock index 55b1672762..beec7807b0 100644 --- a/view/ihex/Cargo.lock +++ b/view/bintxt/Cargo.lock @@ -279,6 +279,12 @@ 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" @@ -297,12 +303,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "view-ihex" +name = "view-bintxt" version = "0.1.0" dependencies = [ "binaryninja", "ihex", "log", + "srec", ] [[package]] diff --git a/view/srec/Cargo.toml b/view/bintxt/Cargo.toml similarity index 87% rename from view/srec/Cargo.toml rename to view/bintxt/Cargo.toml index 04f7facce8..ed6d4ed919 100644 --- a/view/srec/Cargo.toml +++ b/view/bintxt/Cargo.toml @@ -1,13 +1,14 @@ [package] -name = "view-srec" +name = "view-bintxt" version = "0.1.0" authors = ["Rubens Brandao "] edition = "2021" [dependencies] binaryninja = { path = "../../rust" } -srec = "0.2.0" +ihex = "3.0.0" log = "*" +srec = "0.2.0" [lib] crate-type = ["cdylib"] diff --git a/view/bintxt/src/ihex.rs b/view/bintxt/src/ihex.rs new file mode 100644 index 0000000000..5b210ff490 --- /dev/null +++ b/view/bintxt/src/ihex.rs @@ -0,0 +1,237 @@ +use binaryninja::binaryview::*; +use binaryninja::custombinaryview::*; +use binaryninja::rc::Ref; +use binaryninja::segment::SegmentBuilder; +use ihex::Record; + +use crate::segment_after_address; +use crate::segment_from_address; +use crate::sort_and_merge_segments; +use crate::MergedSegment; +use crate::UnmergedSegment; + +fn parse_ihex(string: &str) -> Result<(Vec, IHexViewData)> { + let mut reader = ihex::Reader::new(&string); + let mut unmerged_data: Vec = 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 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> { + let bytes = parent.len(); + 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::(&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 + } +} + +pub struct IHexView { + core: Ref, + segments: Vec, + start: Option, +} + +pub struct IHexViewData { + segments: Vec, + start: Option, +} + +#[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 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 { + 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), + ); + } + 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 new file mode 100644 index 0000000000..96cd1835a5 --- /dev/null +++ b/view/bintxt/src/lib.rs @@ -0,0 +1,131 @@ +mod ihex; +mod srec; +mod titxt; + +use binaryninja::segment::SegmentBuilder; +use ihex::*; +use srec::*; +use titxt::*; + +use std::ops::Range; + +#[no_mangle] +#[allow(non_snake_case)] +pub extern "C" fn CorePluginInit() -> bool { + binaryninja::logger::init(log::LevelFilter::Error).expect("Unable to initialize logger"); + + binaryninja::custombinaryview::register_view_type(c"ti-txt", c"TI-TXT", |core| { + TiTxtViewConstructor { core } + }); + + binaryninja::custombinaryview::register_view_type(c"srec", c"Motorola S-record", |core| { + SRecViewConstructor { core } + }); + + binaryninja::custombinaryview::register_view_type(c"ihex", c"Intel HEX", |core| { + IHexViewConstructor { core } + }); + + true +} + +struct UnmergedSegment { + address: u64, + data: Vec, +} + +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 { + self.address..self.end() + } + + fn data_range(&self) -> Range { + self.data_offset..self.data_offset + self.len + } + + fn end(&self) -> u64 { + self.address + self.len + } +} + +impl From for SegmentBuilder { + fn from(segment: MergedSegment) -> Self { + SegmentBuilder::new(segment.address_range()).parent_backing(segment.data_range()) + } +} + +struct MergedSegments { + data: Vec, + segments: Vec, +} + +fn sort_and_merge_segments(mut unmerged_data: Vec) -> Result { + // 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 = + Vec::with_capacity(unmerged_data.iter().map(|sector| sector.data.len()).sum()); + let mut segments: Vec = 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/srec/src/lib.rs b/view/bintxt/src/srec.rs similarity index 63% rename from view/srec/src/lib.rs rename to view/bintxt/src/srec.rs index d6dcca040a..3f77e704c8 100644 --- a/view/srec/src/lib.rs +++ b/view/bintxt/src/srec.rs @@ -1,6 +1,3 @@ -use core::cmp::Ordering; -use std::ops::Range; - use binaryninja::binaryview::{BinaryView, BinaryViewBase, BinaryViewExt}; use binaryninja::custombinaryview::{ BinaryViewType, BinaryViewTypeBase, CustomBinaryView, CustomBinaryViewType, CustomView, @@ -10,19 +7,14 @@ use binaryninja::rc::Ref; use binaryninja::segment::SegmentBuilder; use srec::Record; -pub struct SRecViewConstructor { - core: BinaryViewType, -} - -impl AsRef for SRecViewConstructor { - fn as_ref(&self) -> &BinaryViewType { - &self.core - } -} +use crate::{ + segment_after_address, segment_from_address, sort_and_merge_segments, MergedSegment, + UnmergedSegment, +}; struct SRecParser { reader: I, - sectors: Vec<(u32, Vec)>, + segments: Vec, sector_counter: u32, start: u32, } @@ -71,15 +63,18 @@ impl>> SRecParser { log::error!("Invalid second record type"); return Err(()); } - Record::S1(s) => (RecordLen::R16, s.address.into(), s.data), - Record::S2(s) => (RecordLen::R24, s.address.into(), s.data), - Record::S3(s) => (RecordLen::R32, s.address.into(), s.data), + 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.sectors.push((first_data_addr, first_data)); + 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) Records + // or Start Address (S7, S8, S9) Record let next = loop { let record = self .reader @@ -96,13 +91,13 @@ impl>> SRecParser { return Err(()); } Record::S1(s) if addr_len == RecordLen::R16 => { - self.add_record_data(s.address.into(), s.data) + self.add_record_data(u32::from(s.address).into(), s.data) } Record::S2(s) if addr_len == RecordLen::R24 => { - self.add_record_data(s.address.into(), s.data) + self.add_record_data(u32::from(s.address).into(), s.data) } Record::S3(s) if addr_len == RecordLen::R32 => { - self.add_record_data(s.address.into(), s.data) + self.add_record_data(u32::from(s.address).into(), s.data) } Record::S1(_) | Record::S2(_) | Record::S3(_) => { log::error!("Data record with invalid len"); @@ -159,18 +154,16 @@ impl>> SRecParser { Ok(()) } - fn add_record_data(&mut self, address: u32, value: Vec) { + fn add_record_data(&mut self, address: u64, data: Vec) { self.sector_counter += 1; - match self.sectors.last_mut() { + match self.segments.last_mut() { // check if the block is just extending the previous one, merge both - Some((last_address, last_data)) - if *last_address + u32::try_from(last_data.len()).unwrap() == address => - { - last_data.extend(value); + Some(last) if last.end() == address => { + last.data.extend(data); } // otherwise just add a new block _ => { - self.sectors.push((address, value)); + self.segments.push(UnmergedSegment { address, data }); } } } @@ -188,60 +181,31 @@ impl>> SRecParser { fn parse_srec(data: &str) -> Result<(Vec, SRecViewData), ()> { let mut parser = SRecParser { reader: srec::reader::read_records(&data), - sectors: vec![], + segments: vec![], sector_counter: 0, start: 0, }; parser.parse()?; - let mut unmerged_sectors = parser.sectors; - let start = parser.start; - - // condensate the blocks - // sort blocks by address and len - unmerged_sectors.sort_unstable_by(|(addr_a, data_a), (addr_b, data_b)| { - // order by address - match addr_a.cmp(addr_b) { - std::cmp::Ordering::Equal => {} - x => return x, - }; - // if save address, put the biggest first, so it's easy to error later - data_a.len().cmp(&data_b.len()) - }); - // make sure they don't overlap and merge then if they extend each other - let mut data: Vec = Vec::with_capacity( - unmerged_sectors - .iter() - .map(|(_addr, chunk)| chunk.len()) - .sum(), - ); - let mut segments: Vec = Vec::with_capacity(unmerged_sectors.len()); - for (chunk_addr, chunk_data) in unmerged_sectors.into_iter() { - match segments.last_mut() { - // if have a last segment and the current chunk just extend it, merge both - Some(last) if chunk_addr == last.end() => { - last.len += chunk_data.len(); - } - // the same sector overlap, then the data was defined multiple times. - Some(last) if chunk_addr < last.end() => { - log::error!("Chunks of data overlap"); - return Err(()); - } - // otherwise just create a new segment - _ => { - segments.push(SRecViewSegment { - address: chunk_addr, - len: chunk_data.len(), - data_offset: data.len(), - }); - } - } - data.extend(chunk_data); - } + let segments = sort_and_merge_segments(parser.segments)?; + Ok(( + segments.data, + SRecViewData { + segments: segments.segments, + start: parser.start, + }, + )) +} - Ok((data, SRecViewData { segments, start })) +pub struct SRecViewConstructor { + pub core: BinaryViewType, } +impl AsRef for SRecViewConstructor { + fn as_ref(&self) -> &BinaryViewType { + &self.core + } +} impl CustomBinaryViewType for SRecViewConstructor { fn create_custom_view<'builder>( &self, @@ -295,39 +259,12 @@ impl BinaryViewTypeBase for SRecViewConstructor { pub struct SRecView { core: Ref, - segments: Vec, + segments: Vec, start: u32, } -pub struct SRecViewSegment { - address: u32, - len: usize, - data_offset: usize, -} - -impl SRecViewSegment { - fn address_range(&self) -> Range { - self.address.into()..u64::from(self.address) + u64::try_from(self.len).unwrap() - } - - fn data_range(&self) -> Range { - let start = usize::try_from(self.data_offset).unwrap(); - let end = start + self.len; - start..end - } - - fn data_range_u64(&self) -> Range { - let range = self.data_range(); - range.start.try_into().unwrap()..range.end.try_into().unwrap() - } - - fn end(&self) -> u32 { - self.address + u32::try_from(self.len).unwrap() - } -} - pub struct SRecViewData { - segments: Vec, + segments: Vec, start: u32, } @@ -337,21 +274,6 @@ impl AsRef for SRecView { } } -impl SRecView { - fn sector_from_address(&self, offset: u64) -> Option<&SRecViewSegment> { - self.segments - .binary_search_by(|sector| { - let range = sector.address_range(); - if range.contains(&offset) { - return Ordering::Equal; - } - offset.cmp(&range.start) - }) - .ok() - .map(|idx| &self.segments[idx]) - } -} - unsafe impl CustomBinaryView for SRecView { type Args = SRecViewData; @@ -370,8 +292,7 @@ unsafe impl CustomBinaryView for SRecView { for segment in self.segments.iter() { self.add_segment( - SegmentBuilder::new(segment.address_range()) - .parent_backing(segment.data_range_u64()) + SegmentBuilder::from(*segment) .executable(true) .readable(true) .contains_data(true) @@ -396,32 +317,10 @@ impl BinaryViewBase for SRecView { } fn offset_valid(&self, offset: u64) -> bool { - self.sector_from_address(offset).is_some() + segment_from_address(&self.segments, offset).is_some() } fn next_valid_offset_after(&self, offset: u64) -> u64 { - let Ok(offset) = u32::try_from(offset) else { - return offset; - }; - let sector = self.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() + segment_after_address(&self.segments, offset) } } - -#[no_mangle] -#[allow(non_snake_case)] -pub extern "C" fn CorePluginInit() -> bool { - binaryninja::logger::init(log::LevelFilter::Error).expect("Unable to initialize logger"); - binaryninja::custombinaryview::register_view_type(c"srec", c"Motorola S-record", |core| { - SRecViewConstructor { core } - }); - true -} diff --git a/view/titxt/src/lib.rs b/view/bintxt/src/titxt.rs similarity index 51% rename from view/titxt/src/lib.rs rename to view/bintxt/src/titxt.rs index 1f0470391c..6a56a82673 100644 --- a/view/titxt/src/lib.rs +++ b/view/bintxt/src/titxt.rs @@ -1,6 +1,3 @@ -use core::cmp::Ordering; -use std::ops::Range; - use binaryninja::binaryview::{BinaryView, BinaryViewBase, BinaryViewExt}; use binaryninja::custombinaryview::{ BinaryViewType, BinaryViewTypeBase, CustomBinaryView, CustomBinaryViewType, CustomView, @@ -9,20 +6,10 @@ use binaryninja::custombinaryview::{ use binaryninja::rc::Ref; use binaryninja::segment::SegmentBuilder; -pub struct TiTxtViewConstructor { - core: BinaryViewType, -} - -impl AsRef for TiTxtViewConstructor { - fn as_ref(&self) -> &BinaryViewType { - &self.core - } -} - -struct TiTxtSection { - address: u16, - data: Vec, -} +use crate::{ + segment_after_address, segment_from_address, sort_and_merge_segments, MergedSegment, + MergedSegments, UnmergedSegment, +}; fn hex_to_byte(char: u8) -> Option { match char { @@ -63,7 +50,47 @@ fn take_newline(input: &[u8]) -> Option<&[u8]> { } } -fn parse_section(input: &[u8]) -> Result<(TiTxtSection, &[u8]), ()> { +// 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]), ()> { + // 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 { + // 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 = @@ -72,21 +99,17 @@ fn parse_section(input: &[u8]) -> Result<(TiTxtSection, &[u8]), ()> { // get one or more bytes let mut data = vec![]; let rest = loop { - let (byte, rest) = take_byte(input).ok_or_else(|| log::error!("Unable to parse byte"))?; + 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; - data.push(byte); - - // bytes are separated by space or new line - if input[0] == b' ' { - input = &input[1..]; - } else { - let rest = take_newline(input) - .ok_or_else(|| log::error!("Unable to find Address delimiter"))?; - input = rest; - } match input { - // if after a byte we find a 'q', then we found the end of file + // 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 @@ -98,55 +121,47 @@ fn parse_section(input: &[u8]) -> Result<(TiTxtSection, &[u8]), ()> { // found the next sector [b'@', ..] => break input, - // just get the next byte + // 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 _ => {} } }; - Ok((TiTxtSection { address, data }, rest)) + let segment = UnmergedSegment { + address: address.into(), + data, + }; + Ok((segment, rest)) } -fn parse_ti_txt(data: &[u8]) -> Result<(Vec, TiTxtViewData), ()> { +fn parse_ti_txt(data: &[u8]) -> Result { let mut current_data = data; - let mut unmerged_data = vec![]; + let mut unmerged_segments = vec![]; while !current_data.is_empty() { - let (section, rest) = parse_section(current_data)?; + let (section, rest) = parse_sections(current_data)?; current_data = rest; - unmerged_data.push(section); + unmerged_segments.push(section); } + sort_and_merge_segments(unmerged_segments) +} - // condensate the blocks, sort blocks by address and len - unmerged_data.sort_unstable_by_key(|sector| sector.address); - - // make sure they don't overlap and merge then if they extend each other - let mut data: Vec = - Vec::with_capacity(unmerged_data.iter().map(|sector| sector.data.len()).sum()); - let mut segments: Vec = Vec::with_capacity(unmerged_data.len()); - for chunk in unmerged_data.into_iter() { - match segments.last_mut() { - // if have a last segment and the current chunk just extend it, merge both - Some(last) if chunk.address == last.end() => { - last.len += chunk.data.len(); - } - // the same sector overlap, then the data was defined multiple times. - Some(last) if chunk.address < last.end() => { - log::error!("Chunks of data overlap"); - return Err(()); - } - // otherwise just create a new segment - _ => { - segments.push(TiTxtViewSegment { - address: chunk.address, - len: chunk.data.len(), - data_offset: data.len(), - }); - } - } - data.extend(chunk.data); - } +pub struct TiTxtViewConstructor { + pub core: BinaryViewType, +} - Ok((data, TiTxtViewData { segments })) +impl AsRef for TiTxtViewConstructor { + fn as_ref(&self) -> &BinaryViewType { + &self.core + } } impl CustomBinaryViewType for TiTxtViewConstructor { @@ -162,10 +177,10 @@ impl CustomBinaryViewType for TiTxtViewConstructor { log::error!("IHex file is too small"); return Err(()); } - let (data, sectors) = parse_ti_txt(&buf)?; + let sectors = parse_ti_txt(&buf)?; - let parent_bin = BinaryView::from_data(&parent.file(), &data)?; - builder.create::(&parent_bin, sectors) + let parent_bin = BinaryView::from_data(&parent.file(), §ors.data)?; + builder.create::(&parent_bin, sectors.segments) } } @@ -190,38 +205,7 @@ impl BinaryViewTypeBase for TiTxtViewConstructor { pub struct TiTxtView { core: Ref, - segments: Vec, -} - -pub struct TiTxtViewSegment { - address: u16, - len: usize, - data_offset: usize, -} - -impl TiTxtViewSegment { - fn address_range(&self) -> Range { - self.address.into()..u64::from(self.address) + u64::try_from(self.len).unwrap() - } - - fn data_range(&self) -> Range { - let start = usize::try_from(self.data_offset).unwrap(); - let end = start + self.len; - start..end - } - - fn data_range_u64(&self) -> Range { - let range = self.data_range(); - range.start.try_into().unwrap()..range.end.try_into().unwrap() - } - - fn end(&self) -> u16 { - self.address + u16::try_from(self.len).unwrap() - } -} - -pub struct TiTxtViewData { - segments: Vec, + segments: Vec, } impl AsRef for TiTxtView { @@ -230,23 +214,8 @@ impl AsRef for TiTxtView { } } -impl TiTxtView { - fn sector_from_address(&self, offset: u64) -> Option<&TiTxtViewSegment> { - self.segments - .binary_search_by(|sector| { - let range = sector.address_range(); - if range.contains(&offset) { - return Ordering::Equal; - } - offset.cmp(&range.start) - }) - .ok() - .map(|idx| &self.segments[idx]) - } -} - unsafe impl CustomBinaryView for TiTxtView { - type Args = TiTxtViewData; + type Args = Vec; fn new(handle: &BinaryView, _args: &Self::Args) -> Result { Ok(Self { @@ -256,13 +225,12 @@ unsafe impl CustomBinaryView for TiTxtView { }) } - fn init(&mut self, TiTxtViewData { segments }: Self::Args) -> Result<(), ()> { + fn init(&mut self, segments: Self::Args) -> Result<(), ()> { self.segments = segments; for segment in self.segments.iter() { self.add_segment( - SegmentBuilder::new(segment.address_range()) - .parent_backing(segment.data_range_u64()) + SegmentBuilder::from(*segment) .executable(true) .readable(true) .contains_data(true) @@ -275,6 +243,7 @@ unsafe impl CustomBinaryView for TiTxtView { 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) } @@ -287,32 +256,10 @@ impl BinaryViewBase for TiTxtView { } fn offset_valid(&self, offset: u64) -> bool { - self.sector_from_address(offset).is_some() + segment_from_address(&self.segments, offset).is_some() } fn next_valid_offset_after(&self, offset: u64) -> u64 { - let Ok(offset) = u16::try_from(offset) else { - return offset; - }; - let sector = self.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() + segment_after_address(&self.segments, offset) } } - -#[no_mangle] -#[allow(non_snake_case)] -pub extern "C" fn CorePluginInit() -> bool { - binaryninja::logger::init(log::LevelFilter::Error).expect("Unable to initialize logger"); - binaryninja::custombinaryview::register_view_type(c"ti-txt", c"TI-TXT", |core| { - TiTxtViewConstructor { core } - }); - true -} diff --git a/view/ihex/Cargo.toml b/view/ihex/Cargo.toml deleted file mode 100644 index a2d7074a4e..0000000000 --- a/view/ihex/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "view-ihex" -version = "0.1.0" -authors = ["Rubens Brandao "] -edition = "2021" - -[dependencies] -binaryninja = { path = "../../rust" } -ihex = "3.0.0" -log = "*" - -[lib] -crate-type = ["cdylib"] - -[profile.release] -panic = "abort" -lto = true -debug = 1 diff --git a/view/ihex/src/lib.rs b/view/ihex/src/lib.rs deleted file mode 100644 index ef666f6f18..0000000000 --- a/view/ihex/src/lib.rs +++ /dev/null @@ -1,349 +0,0 @@ -use core::cmp::Ordering; -use std::ops::Range; - -use binaryninja::binaryview::*; -use binaryninja::custombinaryview::*; -use binaryninja::rc::Ref; -use binaryninja::segment::SegmentBuilder; - -pub struct IHexViewConstructor { - core: BinaryViewType, -} - -impl AsRef 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> { - let bytes = parent.len(); - 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 mut reader = ihex::Reader::new_with_options( - &string, - ihex::ReaderOptions { - stop_after_first_error: true, - stop_after_eof: true, - }, - ); - let mut unmerged_data = 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)) => { - u32::from(offset) * 16 + u32::from(data_offset) - } - Some(IHexOffset::Linear(offset)) => { - u32::from(offset) << 16 | u32::from(data_offset) - } - None => data_offset.into(), - }; - // check if the block is just extending the previous one - if unmerged_data - .last() - .map(|(last_address, last_data): &(u32, Vec)| { - usize::try_from(*last_address).unwrap() + last_data.len() - }) - == Some(usize::try_from(address).unwrap()) - { - let (_last_address, last_data) = unmerged_data.last_mut().unwrap(); - last_data.extend(value); - } else { - // otherwise just add a new block - unmerged_data.push((address, value)); - } - } - ihex::Record::StartSegmentAddress { cs, ip } => { - if start.is_some() { - log::error!("Multiple Start Address defined"); - return Err(()); - } - start = Some(IHexStart::Segment { 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(()); - } - - // condensate the blocks - // sort blocks by address and len - unmerged_data.sort_unstable_by(|(addr_a, data_a), (addr_b, data_b)| { - // order by address - match addr_a.cmp(addr_b) { - std::cmp::Ordering::Equal => {} - x => return x, - }; - // if save address, put the biggest first, so it's easy to error later - data_a.len().cmp(&data_b.len()) - }); - // make sure they don't overlap and merge then if they extend each other - let mut data: Vec = - Vec::with_capacity(unmerged_data.iter().map(|(_addr, chunk)| chunk.len()).sum()); - let mut segments: Vec = Vec::with_capacity(unmerged_data.len()); - for (chunk_addr, chunk_data) in unmerged_data.into_iter() { - match segments.last_mut() { - // if have a last segment and the current chunk just extend it, merge both - Some(last) if chunk_addr == last.end() => { - last.len += chunk_data.len(); - } - // the same sector overlap, then the data was defined multiple times. - Some(last) if chunk_addr < last.end() => { - log::error!("Chunks of data overlap"); - return Err(()); - } - // otherwise just create a new segment - _ => { - segments.push(IHexViewSegment { - address: chunk_addr, - len: chunk_data.len(), - data_offset: data.len(), - }); - } - } - data.extend(chunk_data); - } - - let parent_bin = BinaryView::from_data(&parent.file(), &data)?; - builder.create::(&parent_bin, IHexViewData { segments, start }) - } -} - -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() { - // // General-purpose: - // "hex" | "mcs" | "int" | "ihex" | "ihe" | "ihx" => Some(true), - // // Platform-specific: - // "h80" | "h86" | "a43" | "a90" => Some(true), - // // Binary or Intel hex: - // "obj" | "obl" | "obh" | "rom" | "eep" => Some(true), - // // TODO: Split, banked, or paged: - // //.hxl–.hxh,[8] .h00–.h15, .p00–.pff[9] - // _ => None, - // }) - // .flatten(); - - // The smallest valid record is EOF ":00000001FF", 11 bytes - if data.len() < 11 { - return false; - } - let mut first_bytes = [0u8; 11]; - let read_bytes = data.read(&mut first_bytes, 0); - if read_bytes < 11 { - return false; - } - - // first byte need to be equal to ':'. - if first_bytes[0] != b':' { - return false; - } - - // the next bytes can be any hex char - if first_bytes[1..] - .iter() - .any(|byte| !byte.is_ascii_hexdigit()) - { - return false; - } - - true - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct IHexView { - core: Ref, - segments: Vec, - start: Option, -} - -pub struct IHexViewSegment { - address: u32, - len: usize, - data_offset: usize, -} - -impl IHexViewSegment { - fn address_range(&self) -> Range { - self.address.into()..u64::from(self.address) + u64::try_from(self.len).unwrap() - } - - fn data_range(&self) -> Range { - let start = self.data_offset; - let end = start + self.len; - start..end - } - - fn data_range_u64(&self) -> Range { - let range = self.data_range(); - range.start.try_into().unwrap()..range.end.try_into().unwrap() - } - - fn end(&self) -> u32 { - self.address + u32::try_from(self.len).unwrap() - } -} - -pub struct IHexViewData { - segments: Vec, - start: Option, -} - -#[derive(Clone, Copy, Debug)] -pub enum IHexStart { - Segment { cs: u16, ip: u16 }, - Linear(u32), -} - -#[derive(Clone, Copy, Debug)] -pub enum IHexOffset { - Segment(u16), - Linear(u16), -} - -impl AsRef for IHexView { - fn as_ref(&self) -> &BinaryView { - &self.core - } -} - -impl IHexView { - fn sector_from_address(&self, offset: u64) -> Option<&IHexViewSegment> { - self.segments - .binary_search_by(|sector| { - let range = sector.address_range(); - if range.contains(&offset) { - return Ordering::Equal; - } - offset.cmp(&range.start) - }) - .ok() - .map(|idx| &self.segments[idx]) - } -} - -unsafe impl CustomBinaryView for IHexView { - type Args = IHexViewData; - - fn new(handle: &BinaryView, _args: &Self::Args) -> Result { - 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::new(segment.address_range()) - .parent_backing(segment.data_range_u64()) - .executable(true) - .readable(true) - .contains_data(true) - .contains_code(true), - ); - } - 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 { - self.sector_from_address(offset).is_some() - } - - fn next_valid_offset_after(&self, offset: u64) -> u64 { - let Ok(offset) = u32::try_from(offset) else { - return offset; - }; - let sector = self.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() - } -} - -#[no_mangle] -#[allow(non_snake_case)] -pub extern "C" fn CorePluginInit() -> bool { - binaryninja::logger::init(log::LevelFilter::Error).expect("Unable to initialize logger"); - binaryninja::custombinaryview::register_view_type(c"ihex", c"Intel HEX", |core| { - IHexViewConstructor { core } - }); - true -} diff --git a/view/srec/Cargo.lock b/view/srec/Cargo.lock deleted file mode 100644 index 67fd3e03a2..0000000000 --- a/view/srec/Cargo.lock +++ /dev/null @@ -1,391 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[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", - "lazy_static", - "libc", - "log", -] - -[[package]] -name = "binaryninjacore-sys" -version = "0.1.0" -dependencies = [ - "bindgen", -] - -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", - "which", -] - -[[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 = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[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 = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[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 = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[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.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -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 = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[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-srec" -version = "0.1.0" -dependencies = [ - "binaryninja", - "log", - "srec", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[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/titxt/Cargo.lock b/view/titxt/Cargo.lock deleted file mode 100644 index 944187683e..0000000000 --- a/view/titxt/Cargo.lock +++ /dev/null @@ -1,384 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[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", - "lazy_static", - "libc", - "log", -] - -[[package]] -name = "binaryninjacore-sys" -version = "0.1.0" -dependencies = [ - "bindgen", -] - -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", - "which", -] - -[[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 = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[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 = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[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 = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[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.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -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 = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[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-titxt" -version = "0.1.0" -dependencies = [ - "binaryninja", - "log", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[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/titxt/Cargo.toml b/view/titxt/Cargo.toml deleted file mode 100644 index 820924011f..0000000000 --- a/view/titxt/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "view-titxt" -version = "0.1.0" -authors = ["Rubens Brandao "] -edition = "2021" - -[dependencies] -binaryninja = { path = "../../rust" } -log = "*" - -[lib] -crate-type = ["cdylib"] - -[profile.release] -panic = "abort" -lto = true -debug = 1