1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
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()
}
|