diff --git a/objdiff-cli/src/cmd/diff.rs b/objdiff-cli/src/cmd/diff.rs index a52d34b..ef6faac 100644 --- a/objdiff-cli/src/cmd/diff.rs +++ b/objdiff-cli/src/cmd/diff.rs @@ -19,7 +19,6 @@ use crossterm::{ }, }; use objdiff_core::{ - bindings::diff::DiffResult, build::{ BuildConfig, BuildStatus, watcher::{Watcher, create_watcher}, @@ -28,7 +27,7 @@ use objdiff_core::{ ProjectConfig, ProjectObject, ProjectObjectMetadata, build_globset, path::{check_path_buf, platform_path, platform_path_serde_option}, }, - diff::{self, DiffObjConfig, MappingConfig, ObjectDiff}, + diff::{DiffObjConfig, MappingConfig, ObjectDiff}, jobs::{ Job, JobQueue, JobResult, objdiff::{ObjDiffConfig, start_build}, @@ -40,10 +39,7 @@ use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf}; use crate::{ cmd::apply_config_args, - util::{ - output::{OutputFormat, write_output}, - term::crossterm_panic_handler, - }, + util::term::crossterm_panic_handler, views::{EventControlFlow, EventResult, UiView, function_diff::FunctionDiffUi}, }; @@ -63,12 +59,6 @@ pub struct Args { #[argp(option, short = 'u')] /// Unit name within project unit: Option, - #[argp(option, short = 'o', from_str_fn(platform_path))] - /// Output file (one-shot mode) ("-" for stdout) - output: Option, - #[argp(option)] - /// Output format (json, json-pretty, proto) (default: json) - format: Option, #[argp(positional)] /// Function symbol to diff symbol: Option, @@ -171,11 +161,7 @@ pub fn run(args: Args) -> Result<()> { _ => bail!("Either target and base or project and unit must be specified"), }; - if let Some(output) = &args.output { - run_oneshot(&args, output, target_path.as_deref(), base_path.as_deref()) - } else { - run_interactive(args, target_path, base_path, project_config) - } + run_interactive(args, target_path, base_path, project_config) } fn build_config_from_args(args: &Args) -> Result<(DiffObjConfig, MappingConfig)> { @@ -194,28 +180,6 @@ fn build_config_from_args(args: &Args) -> Result<(DiffObjConfig, MappingConfig)> Ok((diff_config, mapping_config)) } -fn run_oneshot( - args: &Args, - output: &Utf8PlatformPath, - target_path: Option<&Utf8PlatformPath>, - base_path: Option<&Utf8PlatformPath>, -) -> Result<()> { - let output_format = OutputFormat::from_option(args.format.as_deref())?; - let (diff_config, mapping_config) = build_config_from_args(args)?; - let target = target_path - .map(|p| obj::read::read(p.as_ref(), &diff_config).with_context(|| format!("Loading {p}"))) - .transpose()?; - let base = base_path - .map(|p| obj::read::read(p.as_ref(), &diff_config).with_context(|| format!("Loading {p}"))) - .transpose()?; - let result = - diff::diff_objs(target.as_ref(), base.as_ref(), None, &diff_config, &mapping_config)?; - let left = target.as_ref().and_then(|o| result.left.as_ref().map(|d| (o, d))); - let right = base.as_ref().and_then(|o| result.right.as_ref().map(|d| (o, d))); - write_output(&DiffResult::new(left, right), Some(output), output_format)?; - Ok(()) -} - pub struct AppState { pub jobs: JobQueue, pub waker: Arc, diff --git a/objdiff-core/protos/diff.proto b/objdiff-core/protos/diff.proto deleted file mode 100644 index c1ad7df..0000000 --- a/objdiff-core/protos/diff.proto +++ /dev/null @@ -1,165 +0,0 @@ -syntax = "proto3"; - -package objdiff.diff; - -// A symbol -message Symbol { - // Name of the symbol - string name = 1; - // Demangled name of the symbol - optional string demangled_name = 2; - // Symbol address - uint64 address = 3; - // Symbol size - uint64 size = 4; - // Bitmask of SymbolFlag - uint32 flags = 5; -} - -// Symbol visibility flags -enum SymbolFlag { - SYMBOL_NONE = 0; - SYMBOL_GLOBAL = 1; - SYMBOL_LOCAL = 2; - SYMBOL_WEAK = 4; - SYMBOL_COMMON = 8; - SYMBOL_HIDDEN = 16; -} - -// A single parsed instruction -message Instruction { - // Instruction address - uint64 address = 1; - // Instruction size - uint32 size = 2; - // Instruction opcode - uint32 opcode = 3; - // Instruction mnemonic - string mnemonic = 4; - // Instruction formatted string - string formatted = 5; - // Original (unsimplified) instruction string - optional string original = 6; - // Instruction arguments - repeated Argument arguments = 7; - // Instruction relocation - optional Relocation relocation = 8; - // Instruction branch destination - optional uint64 branch_dest = 9; - // Instruction line number - optional uint32 line_number = 10; -} - -// An instruction argument -message Argument { - oneof value { - // Plain text - string plain_text = 1; - // Value - ArgumentValue argument = 2; - // Relocation - ArgumentRelocation relocation = 3; - // Branch destination - uint64 branch_dest = 4; - } -} - -// An instruction argument value -message ArgumentValue { - oneof value { - // Signed integer - int64 signed = 1; - // Unsigned integer - uint64 unsigned = 2; - // Opaque value - string opaque = 3; - } -} - -// Marker type for relocation arguments -message ArgumentRelocation { -} - -message Relocation { - uint32 type = 1; - string type_name = 2; - RelocationTarget target = 3; -} - -message RelocationTarget { - uint32 symbol_index = 1; - int64 addend = 2; -} - -message InstructionDiffRow { - DiffKind diff_kind = 1; - optional Instruction instruction = 2; - optional InstructionBranchFrom branch_from = 3; - optional InstructionBranchTo branch_to = 4; - repeated ArgumentDiff arg_diff = 5; -} - -message ArgumentDiff { - optional uint32 diff_index = 1; -} - -enum DiffKind { - DIFF_NONE = 0; - DIFF_REPLACE = 1; - DIFF_DELETE = 2; - DIFF_INSERT = 3; - DIFF_OP_MISMATCH = 4; - DIFF_ARG_MISMATCH = 5; -} - -message InstructionBranchFrom { - repeated uint32 instruction_index = 1; - uint32 branch_index = 2; -} - -message InstructionBranchTo { - uint32 instruction_index = 1; - uint32 branch_index = 2; -} - -message SymbolDiff { - Symbol symbol = 1; - repeated InstructionDiffRow instruction_rows = 2; - optional float match_percent = 3; - // The symbol index in the _other_ object that this symbol was diffed against - optional uint32 target_symbol = 5; -} - -message DataDiff { - DiffKind kind = 1; - bytes data = 2; - // May be larger than data - uint64 size = 3; -} - -message SectionDiff { - string name = 1; - SectionKind kind = 2; - uint64 size = 3; - uint64 address = 4; - reserved 5; - repeated DataDiff data = 6; - optional float match_percent = 7; -} - -enum SectionKind { - SECTION_UNKNOWN = 0; - SECTION_TEXT = 1; - SECTION_DATA = 2; - SECTION_BSS = 3; -} - -message ObjectDiff { - repeated SectionDiff sections = 1; - repeated SymbolDiff symbols = 2; -} - -message DiffResult { - optional ObjectDiff left = 1; - optional ObjectDiff right = 2; -} diff --git a/objdiff-core/protos/proto_descriptor.bin b/objdiff-core/protos/proto_descriptor.bin index 3004765..8b3ce1e 100644 Binary files a/objdiff-core/protos/proto_descriptor.bin and b/objdiff-core/protos/proto_descriptor.bin differ diff --git a/objdiff-core/src/bindings/diff.rs b/objdiff-core/src/bindings/diff.rs deleted file mode 100644 index 959ec8c..0000000 --- a/objdiff-core/src/bindings/diff.rs +++ /dev/null @@ -1,242 +0,0 @@ -#![allow(clippy::needless_lifetimes)] // Generated serde code - -use crate::{diff, obj}; - -// Protobuf diff types -include!(concat!(env!("OUT_DIR"), "/objdiff.diff.rs")); -#[cfg(feature = "serde")] -include!(concat!(env!("OUT_DIR"), "/objdiff.diff.serde.rs")); - -impl DiffResult { - pub fn new( - _left: Option<(&obj::Object, &diff::ObjectDiff)>, - _right: Option<(&obj::Object, &diff::ObjectDiff)>, - ) -> Self { - Self { - // TODO - // left: left.map(|(obj, diff)| ObjectDiff::new(obj, diff)), - // right: right.map(|(obj, diff)| ObjectDiff::new(obj, diff)), - left: None, - right: None, - } - } -} - -// impl ObjectDiff { -// pub fn new(obj: &obj::Object, diff: &diff::ObjectDiff) -> Self { -// Self { -// sections: diff -// .sections -// .iter() -// .enumerate() -// .map(|(i, d)| SectionDiff::new(obj, i, d)) -// .collect(), -// } -// } -// } -// -// impl SectionDiff { -// pub fn new(obj: &obj::Object, section_index: usize, section_diff: &diff::SectionDiff) -> Self { -// let section = &obj.sections[section_index]; -// let symbols = section_diff.symbols.iter().map(|d| SymbolDiff::new(obj, d)).collect(); -// let data = section_diff.data_diff.iter().map(|d| DataDiff::new(obj, d)).collect(); -// // TODO: section_diff.reloc_diff -// Self { -// name: section.name.to_string(), -// kind: SectionKind::from(section.kind) as i32, -// size: section.size, -// address: section.address, -// symbols, -// data, -// match_percent: section_diff.match_percent, -// } -// } -// } -// -// impl From for SectionKind { -// fn from(value: obj::SectionKind) -> Self { -// match value { -// obj::SectionKind::Code => SectionKind::SectionText, -// obj::SectionKind::Data => SectionKind::SectionData, -// obj::SectionKind::Bss => SectionKind::SectionBss, -// // TODO common -// } -// } -// } -// -// impl SymbolDiff { -// pub fn new(object: &obj::Object, symbol_diff: &diff::SymbolDiff) -> Self { -// let symbol = object.symbols[symbol_diff.symbol_index]; -// let instructions = symbol_diff -// .instruction_rows -// .iter() -// .map(|ins_diff| InstructionDiff::new(object, ins_diff)) -// .collect(); -// Self { -// symbol: Some(Symbol::new(symbol)), -// instructions, -// match_percent: symbol_diff.match_percent, -// target: symbol_diff.target_symbol.map(SymbolRef::from), -// } -// } -// } -// -// impl DataDiff { -// pub fn new(_object: &obj::Object, data_diff: &diff::DataDiff) -> Self { -// Self { -// kind: DiffKind::from(data_diff.kind) as i32, -// data: data_diff.data.clone(), -// size: data_diff.len as u64, -// } -// } -// } -// -// impl Symbol { -// pub fn new(value: &ObjSymbol) -> Self { -// Self { -// name: value.name.to_string(), -// demangled_name: value.demangled_name.clone(), -// address: value.address, -// size: value.size, -// flags: symbol_flags(value.flags), -// } -// } -// } -// -// fn symbol_flags(value: ObjSymbolFlagSet) -> u32 { -// let mut flags = 0u32; -// if value.0.contains(ObjSymbolFlags::Global) { -// flags |= SymbolFlag::SymbolGlobal as u32; -// } -// if value.0.contains(ObjSymbolFlags::Local) { -// flags |= SymbolFlag::SymbolLocal as u32; -// } -// if value.0.contains(ObjSymbolFlags::Weak) { -// flags |= SymbolFlag::SymbolWeak as u32; -// } -// if value.0.contains(ObjSymbolFlags::Common) { -// flags |= SymbolFlag::SymbolCommon as u32; -// } -// if value.0.contains(ObjSymbolFlags::Hidden) { -// flags |= SymbolFlag::SymbolHidden as u32; -// } -// flags -// } -// -// impl Instruction { -// pub fn new(object: &obj::Object, instruction: &ObjIns) -> Self { -// Self { -// address: instruction.address, -// size: instruction.size as u32, -// opcode: instruction.op as u32, -// mnemonic: instruction.mnemonic.to_string(), -// formatted: instruction.formatted.clone(), -// arguments: instruction.args.iter().map(Argument::new).collect(), -// relocation: instruction.reloc.as_ref().map(|reloc| Relocation::new(object, reloc)), -// branch_dest: instruction.branch_dest, -// line_number: instruction.line, -// original: instruction.orig.clone(), -// } -// } -// } -// -// impl Argument { -// pub fn new(value: &ObjInsArg) -> Self { -// Self { -// value: Some(match value { -// ObjInsArg::PlainText(s) => argument::Value::PlainText(s.to_string()), -// ObjInsArg::Arg(v) => argument::Value::Argument(ArgumentValue::new(v)), -// ObjInsArg::Reloc => argument::Value::Relocation(ArgumentRelocation {}), -// ObjInsArg::BranchDest(dest) => argument::Value::BranchDest(*dest), -// }), -// } -// } -// } -// -// impl ArgumentValue { -// pub fn new(value: &ObjInsArgValue) -> Self { -// Self { -// value: Some(match value { -// ObjInsArgValue::Signed(v) => argument_value::Value::Signed(*v), -// ObjInsArgValue::Unsigned(v) => argument_value::Value::Unsigned(*v), -// ObjInsArgValue::Opaque(v) => argument_value::Value::Opaque(v.to_string()), -// }), -// } -// } -// } -// -// impl Relocation { -// pub fn new(object: &obj::Object, reloc: &ObjReloc) -> Self { -// Self { -// r#type: match reloc.flags { -// object::RelocationFlags::Elf { r_type } => r_type, -// object::RelocationFlags::MachO { r_type, .. } => r_type as u32, -// object::RelocationFlags::Coff { typ } => typ as u32, -// object::RelocationFlags::Xcoff { r_rtype, .. } => r_rtype as u32, -// _ => unreachable!(), -// }, -// type_name: object.arch.display_reloc(reloc.flags).into_owned(), -// target: Some(RelocationTarget { -// symbol: Some(Symbol::new(&reloc.target)), -// addend: reloc.addend, -// }), -// } -// } -// } -// -// impl InstructionDiff { -// pub fn new(object: &obj::Object, instruction_diff: &ObjInsDiff) -> Self { -// Self { -// instruction: instruction_diff.ins.as_ref().map(|ins| Instruction::new(object, ins)), -// diff_kind: DiffKind::from(instruction_diff.kind) as i32, -// branch_from: instruction_diff.branch_from.as_ref().map(InstructionBranchFrom::new), -// branch_to: instruction_diff.branch_to.as_ref().map(InstructionBranchTo::new), -// arg_diff: instruction_diff.arg_diff.iter().map(ArgumentDiff::new).collect(), -// } -// } -// } -// -// impl ArgumentDiff { -// pub fn new(value: &Option) -> Self { -// Self { diff_index: value.as_ref().map(|v| v.idx as u32) } -// } -// } -// -// impl From for DiffKind { -// fn from(value: ObjInsDiffKind) -> Self { -// match value { -// ObjInsDiffKind::None => DiffKind::DiffNone, -// ObjInsDiffKind::OpMismatch => DiffKind::DiffOpMismatch, -// ObjInsDiffKind::ArgMismatch => DiffKind::DiffArgMismatch, -// ObjInsDiffKind::Replace => DiffKind::DiffReplace, -// ObjInsDiffKind::Delete => DiffKind::DiffDelete, -// ObjInsDiffKind::Insert => DiffKind::DiffInsert, -// } -// } -// } -// -// impl From for DiffKind { -// fn from(value: ObjDataDiffKind) -> Self { -// match value { -// ObjDataDiffKind::None => DiffKind::DiffNone, -// ObjDataDiffKind::Replace => DiffKind::DiffReplace, -// ObjDataDiffKind::Delete => DiffKind::DiffDelete, -// ObjDataDiffKind::Insert => DiffKind::DiffInsert, -// } -// } -// } -// -// impl InstructionBranchFrom { -// pub fn new(value: &ObjInsBranchFrom) -> Self { -// Self { -// instruction_index: value.ins_idx.iter().map(|&x| x as u32).collect(), -// branch_index: value.branch_idx as u32, -// } -// } -// } -// -// impl InstructionBranchTo { -// pub fn new(value: &ObjInsBranchTo) -> Self { -// Self { instruction_index: value.ins_idx as u32, branch_index: value.branch_idx as u32 } -// } -// } diff --git a/objdiff-core/src/bindings/mod.rs b/objdiff-core/src/bindings/mod.rs index 4b67b72..7352eef 100644 --- a/objdiff-core/src/bindings/mod.rs +++ b/objdiff-core/src/bindings/mod.rs @@ -1,3 +1 @@ -#[cfg(feature = "any-arch")] -pub mod diff; pub mod report;