Compare commits

..

5 Commits

Author SHA1 Message Date
2f778932a4 Version 0.3.1 2023-02-06 17:40:42 -05:00
42601b4750 Update cwdemangle 2023-02-06 17:40:42 -05:00
636a8e00c5 Fix diffing across mismatched .text sections 2023-02-06 17:40:42 -05:00
Nick Condron
cd46be7726 Simplify common_symbols by using iterators (#28) 2023-01-26 00:19:20 -05:00
Nick Condron
019493f944 Remove LevEditType::Keep variant (#27) 2023-01-22 13:20:50 -05:00
5 changed files with 86 additions and 110 deletions

6
Cargo.lock generated
View File

@@ -620,9 +620,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]]
name = "cwdemangle"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6db639f6653b14e5d248de711796d8a082a19bfd242a2bba03051074cd3498e"
checksum = "b58d34a3a03cfe0a4ebfd03aeda6ee8a0f2e99bd3308476a8a89815add3ec373"
dependencies = [
"argh",
]
@@ -2189,7 +2189,7 @@ dependencies = [
[[package]]
name = "objdiff"
version = "0.3.0"
version = "0.3.1"
dependencies = [
"anyhow",
"byteorder",

View File

@@ -1,6 +1,6 @@
[package]
name = "objdiff"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
rust-version = "1.65"
authors = ["Luke Street <luke@street.dev>"]
@@ -25,7 +25,7 @@ anyhow = "1.0.68"
bytes = "1.3.0"
cfg-if = "1.0.0"
const_format = "0.2.30"
cwdemangle = "0.1.4"
cwdemangle = "0.1.5"
eframe = { version = "0.20.1", features = ["persistence"] }
egui = "0.20.1"
egui_extras = "0.20.0"

View File

@@ -133,7 +133,6 @@ pub fn diff_code(
right_diff.push(ObjInsDiff::default());
cur_left = left_iter.next();
}
LevEditType::Keep => unreachable!(),
}
} else {
break;
@@ -363,20 +362,26 @@ fn compare_ins(
Ok(result)
}
fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut ObjSymbol> {
symbols.iter_mut().find(|s| s.name == name)
fn find_section_and_symbol(obj: &ObjInfo, name: &str) -> Option<(usize, usize)> {
for (section_idx, section) in obj.sections.iter().enumerate() {
let symbol_idx = match section.symbols.iter().position(|symbol| symbol.name == name) {
Some(symbol_idx) => symbol_idx,
None => continue,
};
return Some((section_idx, symbol_idx));
}
None
}
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> {
for left_section in &mut left.sections {
let Some(right_section) = right.sections.iter_mut().find(|s| s.name == left_section.name) else {
continue;
};
if left_section.kind == ObjSectionKind::Code {
for left_symbol in &mut left_section.symbols {
if let Some(right_symbol) =
find_symbol(&mut right_section.symbols, &left_symbol.name)
if let Some((right_section_idx, right_symbol_idx)) =
find_section_and_symbol(right, &left_symbol.name)
{
let right_section = &mut right.sections[right_section_idx];
let right_symbol = &mut right_section.symbols[right_symbol_idx];
left_symbol.diff_symbol = Some(right_symbol.name.clone());
right_symbol.diff_symbol = Some(left_symbol.name.clone());
diff_code(
@@ -400,22 +405,29 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
)?;
}
}
for right_symbol in &mut right_section.symbols {
if right_symbol.instructions.is_empty() {
no_diff_code(
left.architecture,
&right_section.data,
right_symbol,
&right_section.relocations,
&left.line_info,
)?;
}
} else {
let Some(right_section) = right.sections.iter_mut().find(|s| s.name == left_section.name) else {
continue;
};
if left_section.kind == ObjSectionKind::Data {
diff_data(left_section, right_section);
// diff_data_symbols(left_section, right_section)?;
} else if left_section.kind == ObjSectionKind::Bss {
diff_bss_symbols(&mut left_section.symbols, &mut right_section.symbols)?;
}
}
}
for right_section in right.sections.iter_mut().filter(|s| s.kind == ObjSectionKind::Code) {
for right_symbol in &mut right_section.symbols {
if right_symbol.instructions.is_empty() {
no_diff_code(
right.architecture,
&right_section.data,
right_symbol,
&right_section.relocations,
&right.line_info,
)?;
}
} else if left_section.kind == ObjSectionKind::Data {
diff_data(left_section, right_section);
// diff_data_symbols(left_section, right_section)?;
} else if left_section.kind == ObjSectionKind::Bss {
diff_bss_symbols(&mut left_section.symbols, &mut right_section.symbols)?;
}
}
diff_bss_symbols(&mut left.common, &mut right.common)?;
@@ -424,7 +436,7 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
fn diff_bss_symbols(left_symbols: &mut [ObjSymbol], right_symbols: &mut [ObjSymbol]) -> Result<()> {
for left_symbol in left_symbols {
if let Some(right_symbol) = find_symbol(right_symbols, &left_symbol.name) {
if let Some(right_symbol) = right_symbols.iter_mut().find(|s| s.name == left_symbol.name) {
left_symbol.diff_symbol = Some(right_symbol.name.clone());
right_symbol.diff_symbol = Some(left_symbol.name.clone());
let percent = if left_symbol.size == right_symbol.size { 100.0 } else { 50.0 };
@@ -511,13 +523,12 @@ fn diff_data(left: &mut ObjSection, right: &mut ObjSection) {
let mut right_diff = Vec::<ObjDataDiff>::new();
let mut left_cur = 0usize;
let mut right_cur = 0usize;
let mut cur_op = LevEditType::Keep;
let mut cur_op = LevEditType::Replace;
let mut cur_left_data = Vec::<u8>::new();
let mut cur_right_data = Vec::<u8>::new();
for op in edit_ops {
if cur_op != op.op_type || left_cur < op.first_start || right_cur < op.second_start {
match cur_op {
LevEditType::Keep => {}
LevEditType::Replace => {
let left_data = take(&mut cur_left_data);
let right_data = take(&mut cur_right_data);
@@ -603,7 +614,6 @@ fn diff_data(left: &mut ObjSection, right: &mut ObjSection) {
cur_left_data.push(left.data[left_cur]);
left_cur += 1;
}
LevEditType::Keep => unreachable!(),
}
cur_op = op.op_type;
}
@@ -627,7 +637,6 @@ fn diff_data(left: &mut ObjSection, right: &mut ObjSection) {
// TODO: merge with above
match cur_op {
LevEditType::Keep => {}
LevEditType::Replace => {
let left_data = take(&mut cur_left_data);
let right_data = take(&mut cur_right_data);

View File

@@ -27,7 +27,6 @@
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum LevEditType {
Keep,
Replace,
Insert,
Delete,
@@ -77,19 +76,10 @@ where T: PartialEq {
cache_matrix[current + 1 + p] = x;
}
}
editops_from_cost_matrix(
first_string,
second_string,
matrix_columns,
matrix_rows,
prefix_len,
cache_matrix,
)
editops_from_cost_matrix::<T>(matrix_columns, matrix_rows, prefix_len, cache_matrix)
}
fn editops_from_cost_matrix<T>(
string1: &[T],
string2: &[T],
len1: usize,
len2: usize,
prefix_len: usize,
@@ -98,77 +88,57 @@ fn editops_from_cost_matrix<T>(
where
T: PartialEq,
{
let mut ops = Vec::with_capacity(cache_matrix[len1 * len2 - 1]);
let mut dir = 0;
let mut ops: Vec<LevEditOp> = vec![];
ops.reserve(cache_matrix[len1 * len2 - 1]);
let mut i = len1 - 1;
let mut j = len2 - 1;
let mut p = len1 * len2 - 1;
// let string1_chars: Vec<char> = string1.chars().collect();
// let string2_chars: Vec<char> = string2.chars().collect();
//TODO this is still pretty ugly
while i > 0 || j > 0 {
let current_value = cache_matrix[p];
let op_type;
// More than one operation can be possible at a time. We use `dir` to
// decide when ambiguous.
let is_insert = j > 0 && current_value == cache_matrix[p - 1] + 1;
let is_delete = i > 0 && current_value == cache_matrix[p - len2] + 1;
let is_replace = i > 0 && j > 0 && current_value == cache_matrix[p - len2 - 1] + 1;
if dir == -1 && j > 0 && current_value == cache_matrix[p - 1] + 1 {
op_type = LevEditType::Insert;
} else if dir == 1 && i > 0 && current_value == cache_matrix[p - len2] + 1 {
op_type = LevEditType::Delete;
} else if i > 0
&& j > 0
&& current_value == cache_matrix[p - len2 - 1]
&& string1[i - 1] == string2[j - 1]
{
op_type = LevEditType::Keep;
} else if i > 0 && j > 0 && current_value == cache_matrix[p - len2 - 1] + 1 {
op_type = LevEditType::Replace;
}
/* we can't turn directly from -1 to 1, in this case it would be better
* to go diagonally, but check it (dir == 0) */
else if dir == 0 && j > 0 && current_value == cache_matrix[p - 1] + 1 {
op_type = LevEditType::Insert;
} else if dir == 0 && i > 0 && current_value == cache_matrix[p - len2] + 1 {
op_type = LevEditType::Delete;
} else {
panic!("something went terribly wrong");
}
match op_type {
LevEditType::Insert => {
j -= 1;
p -= 1;
dir = -1;
}
LevEditType::Delete => {
i -= 1;
p -= len2;
dir = 1;
}
LevEditType::Replace => {
i -= 1;
j -= 1;
p -= len2 + 1;
dir = 0;
}
LevEditType::Keep => {
i -= 1;
j -= 1;
p -= len2 + 1;
dir = 0;
/* LevEditKeep does not has to be stored */
continue;
}
let (op_type, new_dir) = match (dir, is_insert, is_delete, is_replace) {
(_, false, false, false) => (None, 0),
(-1, true, _, _) => (Some(LevEditType::Insert), -1),
(1, _, true, _) => (Some(LevEditType::Delete), 1),
(_, _, _, true) => (Some(LevEditType::Replace), 0),
(0, true, _, _) => (Some(LevEditType::Insert), -1),
(0, _, true, _) => (Some(LevEditType::Delete), 1),
_ => panic!("something went terribly wrong"),
};
let edit_op =
LevEditOp { op_type, first_start: i + prefix_len, second_start: j + prefix_len };
ops.insert(0, edit_op);
match new_dir {
-1 => {
j -= 1;
p -= 1;
}
1 => {
i -= 1;
p -= len2;
}
0 => {
i -= 1;
j -= 1;
p -= len2 + 1;
}
_ => panic!("something went terribly wrong"),
};
dir = new_dir;
if let Some(op_type) = op_type {
ops.insert(0, LevEditOp {
op_type,
first_start: i + prefix_len,
second_start: j + prefix_len,
});
}
}
ops

View File

@@ -126,13 +126,10 @@ fn symbols_by_section(obj_file: &File<'_>, section: &ObjSection) -> Result<Vec<O
}
fn common_symbols(obj_file: &File<'_>) -> Result<Vec<ObjSymbol>> {
let mut result = Vec::<ObjSymbol>::new();
for symbol in obj_file.symbols() {
if symbol.is_common() {
result.push(to_obj_symbol(obj_file, &symbol, 0)?);
}
}
Ok(result)
obj_file.symbols()
.filter(Symbol::is_common)
.map(|symbol| to_obj_symbol(obj_file, &symbol, 0))
.collect::<Result<Vec<ObjSymbol>>>()
}
fn find_section_symbol(