diff options
| author | Brian Potchik <brian@vector35.com> | 2025-02-13 13:36:54 -0500 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2025-02-13 13:36:54 -0500 |
| commit | c99986fc66366ff205783add30401d341517b0e0 (patch) | |
| tree | 18cdf2392fc376221a7be39f947cd917e9a186cd /view/bintxt/src/titxt.rs | |
| parent | 3434b6a83ef7a424998b9bc1f95fc484dbf8d2de (diff) | |
Remove bintxt.
Diffstat (limited to 'view/bintxt/src/titxt.rs')
| -rw-r--r-- | view/bintxt/src/titxt.rs | 267 |
1 files changed, 0 insertions, 267 deletions
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(), §ors.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) - } -} |
