Skip to content

Commit d9efa97

Browse files
committed
Initial work on data diffing
1 parent ff9b378 commit d9efa97

File tree

7 files changed

+489
-16
lines changed

7 files changed

+489
-16
lines changed

src/app.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,18 @@ use crate::{
2020
Job, JobResult, JobState,
2121
},
2222
views::{
23-
config::config_ui, function_diff::function_diff_ui, jobs::jobs_ui,
23+
config::config_ui, data_diff::data_diff_ui, function_diff::function_diff_ui, jobs::jobs_ui,
2424
symbol_diff::symbol_diff_ui,
2525
},
2626
};
2727

28+
#[allow(clippy::enum_variant_names)]
2829
#[derive(Default, Eq, PartialEq)]
2930
pub enum View {
3031
#[default]
3132
SymbolDiff,
3233
FunctionDiff,
34+
DataDiff,
3335
}
3436

3537
#[derive(Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
@@ -197,6 +199,16 @@ impl eframe::App for App {
197199
.push(queue_build(config.clone(), view_state.diff_config.clone()));
198200
}
199201
});
202+
} else if view_state.current_view == View::DataDiff
203+
&& matches!(&view_state.build, Some(b) if b.first_status.success && b.second_status.success)
204+
{
205+
egui::CentralPanel::default().show(ctx, |ui| {
206+
if data_diff_ui(ui, view_state) {
207+
view_state
208+
.jobs
209+
.push(queue_build(config.clone(), view_state.diff_config.clone()));
210+
}
211+
});
200212
} else {
201213
egui::SidePanel::left("side_panel").show(ctx, |ui| {
202214
config_ui(ui, config, view_state);

src/diff.rs

Lines changed: 192 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use std::collections::BTreeMap;
1+
use std::{collections::BTreeMap, mem::take};
22

33
use anyhow::Result;
44

55
use crate::{
66
app::DiffConfig,
77
editops::{editops_find, LevEditType},
88
obj::{
9-
mips, ppc, ObjArchitecture, ObjInfo, ObjInsArg, ObjInsArgDiff, ObjInsBranchFrom,
10-
ObjInsBranchTo, ObjInsDiff, ObjInsDiffKind, ObjReloc, ObjSection, ObjSectionKind,
11-
ObjSymbol, ObjSymbolFlags,
9+
mips, ppc, ObjArchitecture, ObjDataDiff, ObjDataDiffKind, ObjInfo, ObjInsArg,
10+
ObjInsArgDiff, ObjInsBranchFrom, ObjInsBranchTo, ObjInsDiff, ObjInsDiffKind, ObjReloc,
11+
ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlags,
1212
},
1313
};
1414

@@ -340,13 +340,13 @@ fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut O
340340
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> {
341341
for left_section in &mut left.sections {
342342
if let Some(right_section) = find_section(right, &left_section.name) {
343-
for left_symbol in &mut left_section.symbols {
344-
if let Some(right_symbol) =
345-
find_symbol(&mut right_section.symbols, &left_symbol.name)
346-
{
347-
left_symbol.diff_symbol = Some(right_symbol.name.clone());
348-
right_symbol.diff_symbol = Some(left_symbol.name.clone());
349-
if left_section.kind == ObjSectionKind::Code {
343+
if left_section.kind == ObjSectionKind::Code {
344+
for left_symbol in &mut left_section.symbols {
345+
if let Some(right_symbol) =
346+
find_symbol(&mut right_section.symbols, &left_symbol.name)
347+
{
348+
left_symbol.diff_symbol = Some(right_symbol.name.clone());
349+
right_symbol.diff_symbol = Some(left_symbol.name.clone());
350350
diff_code(
351351
left.architecture,
352352
&left_section.data,
@@ -358,8 +358,189 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
358358
)?;
359359
}
360360
}
361+
} else if left_section.kind == ObjSectionKind::Data {
362+
diff_data(left_section, right_section);
361363
}
362364
}
363365
}
364366
Ok(())
365367
}
368+
369+
fn diff_data(left: &mut ObjSection, right: &mut ObjSection) {
370+
let edit_ops = editops_find(&left.data, &right.data);
371+
if edit_ops.is_empty() && !left.data.is_empty() {
372+
left.data_diff = vec![ObjDataDiff {
373+
data: left.data.clone(),
374+
kind: ObjDataDiffKind::None,
375+
len: left.data.len(),
376+
}];
377+
right.data_diff = vec![ObjDataDiff {
378+
data: right.data.clone(),
379+
kind: ObjDataDiffKind::None,
380+
len: right.data.len(),
381+
}];
382+
return;
383+
}
384+
385+
let mut left_diff = Vec::<ObjDataDiff>::new();
386+
let mut right_diff = Vec::<ObjDataDiff>::new();
387+
let mut left_cur = 0usize;
388+
let mut right_cur = 0usize;
389+
let mut cur_op = LevEditType::Keep;
390+
let mut cur_left_data = Vec::<u8>::new();
391+
let mut cur_right_data = Vec::<u8>::new();
392+
for op in edit_ops {
393+
if left_cur < op.first_start {
394+
left_diff.push(ObjDataDiff {
395+
data: left.data[left_cur..op.first_start].to_vec(),
396+
kind: ObjDataDiffKind::None,
397+
len: op.first_start - left_cur,
398+
});
399+
left_cur = op.first_start;
400+
}
401+
if right_cur < op.second_start {
402+
right_diff.push(ObjDataDiff {
403+
data: right.data[right_cur..op.second_start].to_vec(),
404+
kind: ObjDataDiffKind::None,
405+
len: op.second_start - right_cur,
406+
});
407+
right_cur = op.second_start;
408+
}
409+
if cur_op != op.op_type {
410+
match cur_op {
411+
LevEditType::Keep => {}
412+
LevEditType::Replace => {
413+
let left_data = take(&mut cur_left_data);
414+
let right_data = take(&mut cur_right_data);
415+
let left_data_len = left_data.len();
416+
let right_data_len = right_data.len();
417+
left_diff.push(ObjDataDiff {
418+
data: left_data,
419+
kind: ObjDataDiffKind::Replace,
420+
len: left_data_len,
421+
});
422+
right_diff.push(ObjDataDiff {
423+
data: right_data,
424+
kind: ObjDataDiffKind::Replace,
425+
len: right_data_len,
426+
});
427+
}
428+
LevEditType::Insert => {
429+
let right_data = take(&mut cur_right_data);
430+
let right_data_len = right_data.len();
431+
left_diff.push(ObjDataDiff {
432+
data: vec![],
433+
kind: ObjDataDiffKind::Insert,
434+
len: right_data_len,
435+
});
436+
right_diff.push(ObjDataDiff {
437+
data: right_data,
438+
kind: ObjDataDiffKind::Insert,
439+
len: right_data_len,
440+
});
441+
}
442+
LevEditType::Delete => {
443+
let left_data = take(&mut cur_left_data);
444+
let left_data_len = left_data.len();
445+
left_diff.push(ObjDataDiff {
446+
data: left_data,
447+
kind: ObjDataDiffKind::Delete,
448+
len: left_data_len,
449+
});
450+
right_diff.push(ObjDataDiff {
451+
data: vec![],
452+
kind: ObjDataDiffKind::Delete,
453+
len: left_data_len,
454+
});
455+
}
456+
}
457+
}
458+
match op.op_type {
459+
LevEditType::Replace => {
460+
cur_left_data.push(left.data[left_cur]);
461+
cur_right_data.push(right.data[right_cur]);
462+
left_cur += 1;
463+
right_cur += 1;
464+
}
465+
LevEditType::Insert => {
466+
cur_right_data.push(right.data[right_cur]);
467+
right_cur += 1;
468+
}
469+
LevEditType::Delete => {
470+
cur_left_data.push(left.data[left_cur]);
471+
left_cur += 1;
472+
}
473+
LevEditType::Keep => unreachable!(),
474+
}
475+
cur_op = op.op_type;
476+
}
477+
// if left_cur < left.data.len() {
478+
// let len = left.data.len() - left_cur;
479+
// left_diff.push(ObjDataDiff {
480+
// data: left.data[left_cur..].to_vec(),
481+
// kind: ObjDataDiffKind::Delete,
482+
// len,
483+
// });
484+
// right_diff.push(ObjDataDiff { data: vec![], kind: ObjDataDiffKind::Delete, len });
485+
// } else if right_cur < right.data.len() {
486+
// let len = right.data.len() - right_cur;
487+
// left_diff.push(ObjDataDiff { data: vec![], kind: ObjDataDiffKind::Insert, len });
488+
// right_diff.push(ObjDataDiff {
489+
// data: right.data[right_cur..].to_vec(),
490+
// kind: ObjDataDiffKind::Insert,
491+
// len,
492+
// });
493+
// }
494+
495+
// TODO: merge with above
496+
match cur_op {
497+
LevEditType::Keep => {}
498+
LevEditType::Replace => {
499+
let left_data = take(&mut cur_left_data);
500+
let right_data = take(&mut cur_right_data);
501+
let left_data_len = left_data.len();
502+
let right_data_len = right_data.len();
503+
left_diff.push(ObjDataDiff {
504+
data: left_data,
505+
kind: ObjDataDiffKind::Replace,
506+
len: left_data_len,
507+
});
508+
right_diff.push(ObjDataDiff {
509+
data: right_data,
510+
kind: ObjDataDiffKind::Replace,
511+
len: right_data_len,
512+
});
513+
}
514+
LevEditType::Insert => {
515+
let right_data = take(&mut cur_right_data);
516+
let right_data_len = right_data.len();
517+
left_diff.push(ObjDataDiff {
518+
data: vec![],
519+
kind: ObjDataDiffKind::Insert,
520+
len: right_data_len,
521+
});
522+
right_diff.push(ObjDataDiff {
523+
data: right_data,
524+
kind: ObjDataDiffKind::Insert,
525+
len: right_data_len,
526+
});
527+
}
528+
LevEditType::Delete => {
529+
let left_data = take(&mut cur_left_data);
530+
let left_data_len = left_data.len();
531+
left_diff.push(ObjDataDiff {
532+
data: left_data,
533+
kind: ObjDataDiffKind::Delete,
534+
len: left_data_len,
535+
});
536+
right_diff.push(ObjDataDiff {
537+
data: vec![],
538+
kind: ObjDataDiffKind::Delete,
539+
len: left_data_len,
540+
});
541+
}
542+
}
543+
544+
left.data_diff = left_diff;
545+
right.data_diff = right_diff;
546+
}

src/obj/elf.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ fn filter_sections(obj_file: &File<'_>) -> Result<Vec<ObjSection>> {
9191
index: section.index().0,
9292
symbols: Vec::new(),
9393
relocations: Vec::new(),
94+
data_diff: vec![],
95+
match_percent: 0.0,
9496
});
9597
}
9698
result.sort_by(|a, b| a.name.cmp(&b.name));

src/obj/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ pub struct ObjSection {
3232
pub index: usize,
3333
pub symbols: Vec<ObjSymbol>,
3434
pub relocations: Vec<ObjReloc>,
35+
36+
// Diff
37+
pub data_diff: Vec<ObjDataDiff>,
38+
pub match_percent: f32,
3539
}
3640
#[derive(Debug, Clone)]
3741
pub enum ObjInsArg {
@@ -92,6 +96,20 @@ pub struct ObjInsDiff {
9296
/// Arg diffs
9397
pub arg_diff: Vec<Option<ObjInsArgDiff>>,
9498
}
99+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
100+
pub enum ObjDataDiffKind {
101+
#[default]
102+
None,
103+
Replace,
104+
Delete,
105+
Insert,
106+
}
107+
#[derive(Debug, Clone, Default)]
108+
pub struct ObjDataDiff {
109+
pub data: Vec<u8>,
110+
pub kind: ObjDataDiffKind,
111+
pub len: usize,
112+
}
95113
#[derive(Debug, Clone)]
96114
pub struct ObjSymbol {
97115
pub name: String,

0 commit comments

Comments
 (0)