Compare commits

..

5 Commits

Author SHA1 Message Date
dab79d96a1 Version v3.0.0-beta.9 2025-05-27 21:32:57 -06:00
a57e5db983 WASM API updates, support symbol mapping 2025-05-27 21:31:29 -06:00
LagoLunatic
d0afd3b83e Fix scroll hotkeys not working in data diff view (#208) 2025-05-27 09:27:00 -06:00
Anghelo Carvajal
a367af612b Make encoding_rs an optional dependency (#205) 2025-05-17 23:14:15 -06:00
LagoLunatic
22052ea10b Data diff view: Show bytes with relocations as ?? instead of 00 (#204)
* Data diff view: Show bytes with relocations as `xx`

* xx -> ??
2025-05-14 21:12:59 -06:00
9 changed files with 222 additions and 138 deletions

8
Cargo.lock generated
View File

@@ -3373,7 +3373,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-cli" name = "objdiff-cli"
version = "3.0.0-beta.8" version = "3.0.0-beta.9"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"argp", "argp",
@@ -3396,7 +3396,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-core" name = "objdiff-core"
version = "3.0.0-beta.8" version = "3.0.0-beta.9"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arm-attr", "arm-attr",
@@ -3450,7 +3450,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-gui" name = "objdiff-gui"
version = "3.0.0-beta.8" version = "3.0.0-beta.9"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cfg-if", "cfg-if",
@@ -3486,7 +3486,7 @@ dependencies = [
[[package]] [[package]]
name = "objdiff-wasm" name = "objdiff-wasm"
version = "3.0.0-beta.8" version = "3.0.0-beta.9"
dependencies = [ dependencies = [
"log", "log",
"objdiff-core", "objdiff-core",

View File

@@ -14,7 +14,7 @@ strip = "debuginfo"
codegen-units = 1 codegen-units = 1
[workspace.package] [workspace.package]
version = "3.0.0-beta.8" version = "3.0.0-beta.9"
authors = ["Luke Street <luke@street.dev>"] authors = ["Luke Street <luke@street.dev>"]
edition = "2024" edition = "2024"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@@ -41,6 +41,7 @@ any-arch = [
"dep:regex", "dep:regex",
"dep:similar", "dep:similar",
"dep:syn", "dep:syn",
"dep:encoding_rs"
] ]
bindings = [ bindings = [
"dep:prost", "dep:prost",
@@ -171,7 +172,7 @@ notify-debouncer-full = { version = "0.5.0", optional = true }
shell-escape = { version = "0.1", optional = true } shell-escape = { version = "0.1", optional = true }
tempfile = { version = "3.19", optional = true } tempfile = { version = "3.19", optional = true }
time = { version = "0.3", optional = true } time = { version = "0.3", optional = true }
encoding_rs = "0.8.35" encoding_rs = { version = "0.8.35", optional = true }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", optional = true } winapi = { version = "0.3", optional = true }

View File

@@ -147,14 +147,20 @@ pub(crate) fn data_row_ui(
cur_addr += diff.len; cur_addr += diff.len;
} else { } else {
for byte in &diff.data { for byte in &diff.data {
let mut byte_text = format!("{byte:02x} ");
let mut byte_color = base_color; let mut byte_color = base_color;
if let Some(reloc_diff) = reloc_diffs.iter().find(|reloc_diff| { if let Some(reloc_diff) = reloc_diffs
reloc_diff.kind != DataDiffKind::None .iter()
&& reloc_diff.range.contains(&cur_addr_actual) .find(|reloc_diff| reloc_diff.range.contains(&cur_addr_actual))
}) { {
byte_color = get_color_for_diff_kind(reloc_diff.kind, appearance); if *byte == 0 {
// Display 00 data bytes with a relocation as ?? instead.
byte_text = "?? ".to_string();
}
if reloc_diff.kind != DataDiffKind::None {
byte_color = get_color_for_diff_kind(reloc_diff.kind, appearance);
}
} }
let byte_text = format!("{byte:02x} ");
write_text(byte_text.as_str(), byte_color, &mut job, appearance.code_font.clone()); write_text(byte_text.as_str(), byte_color, &mut job, appearance.code_font.clone());
cur_addr += 1; cur_addr += 1;
cur_addr_actual += 1; cur_addr_actual += 1;

View File

@@ -499,6 +499,7 @@ pub fn diff_view_ui(
(state.current_view, left_ctx.obj, right_ctx.obj, left_ctx.section, right_ctx.section) (state.current_view, left_ctx.obj, right_ctx.obj, left_ctx.section, right_ctx.section)
{ {
// Joint diff view // Joint diff view
hotkeys::check_scroll_hotkeys(ui, true);
let left_total_bytes = let left_total_bytes =
left_section_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); left_section_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len);
let right_total_bytes = let right_total_bytes =

View File

@@ -1,12 +1,12 @@
{ {
"name": "objdiff-wasm", "name": "objdiff-wasm",
"version": "3.0.0-beta.8", "version": "3.0.0-beta.9",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "objdiff-wasm", "name": "objdiff-wasm",
"version": "3.0.0-beta.8", "version": "3.0.0-beta.9",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.3", "@biomejs/biome": "^1.9.3",

View File

@@ -1,6 +1,6 @@
{ {
"name": "objdiff-wasm", "name": "objdiff-wasm",
"version": "3.0.0-beta.8", "version": "3.0.0-beta.9",
"description": "A local diffing tool for decompilation projects.", "description": "A local diffing tool for decompilation projects.",
"author": { "author": {
"name": "Luke Street", "name": "Luke Street",

View File

@@ -24,14 +24,14 @@ wit_bindgen::generate!({
use exports::objdiff::core::{ use exports::objdiff::core::{
diff::{ diff::{
DiffConfigBorrow, DiffResult, Guest as GuestDiff, GuestDiffConfig, GuestObject, DiffConfigBorrow, DiffResult, Guest as GuestDiff, GuestDiffConfig, GuestObject,
GuestObjectDiff, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow, GuestObjectDiff, MappingConfig, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow,
SymbolFlags, SymbolInfo, SymbolKind, SymbolRef,
}, },
display::{ display::{
ContextItem, ContextItemCopy, ContextItemNavigate, DiffText, DiffTextColor, DiffTextOpcode, ContextItem, ContextItemCopy, ContextItemNavigate, DiffText, DiffTextColor, DiffTextOpcode,
DiffTextSegment, DiffTextSymbol, DisplayConfig, Guest as GuestDisplay, HoverItem, DiffTextSegment, DiffTextSymbol, DisplayConfig, Guest as GuestDisplay, HoverItem,
HoverItemColor, HoverItemText, InstructionDiffKind, InstructionDiffRow, SectionDisplay, HoverItemColor, HoverItemText, InstructionDiffKind, InstructionDiffRow, SectionDisplay,
SectionDisplaySymbol, SymbolDisplay, SymbolFilter, SymbolFlags, SymbolKind, SymbolDisplay, SymbolFilter, SymbolNavigationKind,
SymbolNavigationKind, SymbolRef,
}, },
}; };
@@ -59,15 +59,17 @@ impl GuestDiff for Component {
left: Option<ObjectBorrow>, left: Option<ObjectBorrow>,
right: Option<ObjectBorrow>, right: Option<ObjectBorrow>,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
mapping_config: MappingConfig,
) -> Result<DiffResult, String> { ) -> Result<DiffResult, String> {
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let mapping_config = diff::MappingConfig::from(mapping_config);
log::debug!("Running diff with config: {:?}", diff_config); log::debug!("Running diff with config: {:?}", diff_config);
let result = diff::diff_objs( let result = diff::diff_objs(
left.as_ref().map(|o| o.get::<ResourceObject>().0.as_ref()), left.as_ref().map(|o| o.get::<ResourceObject>().0.as_ref()),
right.as_ref().map(|o| o.get::<ResourceObject>().0.as_ref()), right.as_ref().map(|o| o.get::<ResourceObject>().0.as_ref()),
None, None,
&diff_config, &diff_config,
&diff::MappingConfig::default(), &mapping_config,
) )
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
Ok(DiffResult { Ok(DiffResult {
@@ -134,48 +136,47 @@ impl GuestDisplay for Component {
name: d.name, name: d.name,
size: d.size, size: d.size,
match_percent: d.match_percent, match_percent: d.match_percent,
symbols: d symbols: d.symbols.into_iter().map(to_symbol_ref).collect(),
.symbols
.into_iter()
.map(|s| SectionDisplaySymbol {
symbol: s.symbol as SymbolRef,
is_mapping_symbol: s.is_mapping_symbol,
})
.collect(),
}) })
.collect() .collect()
} }
fn display_symbol( fn display_symbol(diff: ObjectDiffBorrow, symbol_ref: SymbolRef) -> SymbolDisplay {
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
) -> SymbolDisplay {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize; let symbol_display = from_symbol_ref(symbol_ref);
let Some(symbol) = obj.symbols.get(symbol_idx) else { let Some(symbol) = obj.symbols.get(symbol_display.symbol) else {
return SymbolDisplay { name: "<unknown>".to_string(), ..Default::default() }; return SymbolDisplay {
info: SymbolInfo { name: "<unknown>".to_string(), ..Default::default() },
..Default::default()
};
}; };
let symbol_diff = if symbol_display.is_mapping_symbol { let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff obj_diff
.mapping_symbols .mapping_symbols
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_display.symbol)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
} else { } else {
obj_diff.symbols.get(symbol_idx) obj_diff.symbols.get(symbol_display.symbol)
}; };
SymbolDisplay { SymbolDisplay {
name: symbol.name.clone(), info: SymbolInfo {
demangled_name: symbol.demangled_name.clone(), id: to_symbol_ref(symbol_display),
address: symbol.address, name: symbol.name.clone(),
size: symbol.size, demangled_name: symbol.demangled_name.clone(),
kind: SymbolKind::from(symbol.kind), address: symbol.address,
section: symbol.section.map(|s| s as u32), size: symbol.size,
flags: SymbolFlags::from(symbol.flags), kind: SymbolKind::from(symbol.kind),
align: symbol.align.map(|a| a.get()), section: symbol.section.map(|s| s as u32),
virtual_address: symbol.virtual_address, section_name: symbol
.section
.and_then(|s| obj.sections.get(s).map(|sec| sec.name.clone())),
flags: SymbolFlags::from(symbol.flags),
align: symbol.align.map(|a| a.get()),
virtual_address: symbol.virtual_address,
},
target_symbol: symbol_diff.and_then(|sd| sd.target_symbol.map(|s| s as u32)), target_symbol: symbol_diff.and_then(|sd| sd.target_symbol.map(|s| s as u32)),
match_percent: symbol_diff.and_then(|sd| sd.match_percent), match_percent: symbol_diff.and_then(|sd| sd.match_percent),
diff_score: symbol_diff.and_then(|sd| sd.diff_score), diff_score: symbol_diff.and_then(|sd| sd.diff_score),
@@ -185,22 +186,22 @@ impl GuestDisplay for Component {
fn display_instruction_row( fn display_instruction_row(
diff: ObjectDiffBorrow, diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol, symbol_ref: SymbolRef,
row_index: u32, row_index: u32,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
) -> InstructionDiffRow { ) -> InstructionDiffRow {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize; let symbol_display = from_symbol_ref(symbol_ref);
let symbol_diff = if symbol_display.is_mapping_symbol { let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff obj_diff
.mapping_symbols .mapping_symbols
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_display.symbol)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
} else { } else {
obj_diff.symbols.get(symbol_idx) obj_diff.symbols.get(symbol_display.symbol)
}; };
let Some(row) = symbol_diff.and_then(|sd| sd.instruction_rows.get(row_index as usize)) let Some(row) = symbol_diff.and_then(|sd| sd.instruction_rows.get(row_index as usize))
else { else {
@@ -208,7 +209,7 @@ impl GuestDisplay for Component {
}; };
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let mut segments = Vec::with_capacity(16); let mut segments = Vec::with_capacity(16);
diff::display::display_row(obj, symbol_idx, row, &diff_config, |segment| { diff::display::display_row(obj, symbol_display.symbol, row, &diff_config, |segment| {
segments.push(DiffTextSegment::from(segment)); segments.push(DiffTextSegment::from(segment));
Ok(()) Ok(())
}) })
@@ -216,26 +217,22 @@ impl GuestDisplay for Component {
InstructionDiffRow { segments, diff_kind: InstructionDiffKind::from(row.kind) } InstructionDiffRow { segments, diff_kind: InstructionDiffKind::from(row.kind) }
} }
fn symbol_context( fn symbol_context(diff: ObjectDiffBorrow, symbol_ref: SymbolRef) -> Vec<ContextItem> {
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
) -> Vec<ContextItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let symbol_display = from_symbol_ref(symbol_ref);
diff::display::symbol_context(obj, symbol_display.symbol as usize) diff::display::symbol_context(obj, symbol_display.symbol as usize)
.into_iter() .into_iter()
.map(|item| ContextItem::from(item)) .map(|item| ContextItem::from(item))
.collect() .collect()
} }
fn symbol_hover( fn symbol_hover(diff: ObjectDiffBorrow, symbol_ref: SymbolRef) -> Vec<HoverItem> {
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let addend = 0; // TODO let addend = 0; // TODO
let override_color = None; // TODO: colorize replaced/deleted/inserted relocations let override_color = None; // TODO: colorize replaced/deleted/inserted relocations
let symbol_display = from_symbol_ref(symbol_ref);
diff::display::symbol_hover(obj, symbol_display.symbol as usize, addend, override_color) diff::display::symbol_hover(obj, symbol_display.symbol as usize, addend, override_color)
.into_iter() .into_iter()
.map(|item| HoverItem::from(item)) .map(|item| HoverItem::from(item))
@@ -244,22 +241,22 @@ impl GuestDisplay for Component {
fn instruction_context( fn instruction_context(
diff: ObjectDiffBorrow, diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol, symbol_ref: SymbolRef,
row_index: u32, row_index: u32,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
) -> Vec<ContextItem> { ) -> Vec<ContextItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize; let symbol_display = from_symbol_ref(symbol_ref);
let symbol_diff = if symbol_display.is_mapping_symbol { let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff obj_diff
.mapping_symbols .mapping_symbols
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_display.symbol)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
} else { } else {
obj_diff.symbols.get(symbol_idx) obj_diff.symbols.get(symbol_display.symbol)
}; };
let Some(ins_ref) = symbol_diff let Some(ins_ref) = symbol_diff
.and_then(|sd| sd.instruction_rows.get(row_index as usize)) .and_then(|sd| sd.instruction_rows.get(row_index as usize))
@@ -268,7 +265,7 @@ impl GuestDisplay for Component {
return Vec::new(); return Vec::new();
}; };
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else { let Some(resolved) = obj.resolve_instruction_ref(symbol_display.symbol, ins_ref) else {
return vec![ContextItem::Copy(ContextItemCopy { return vec![ContextItem::Copy(ContextItemCopy {
value: "Failed to resolve instruction".to_string(), value: "Failed to resolve instruction".to_string(),
label: Some("error".to_string()), label: Some("error".to_string()),
@@ -291,22 +288,22 @@ impl GuestDisplay for Component {
fn instruction_hover( fn instruction_hover(
diff: ObjectDiffBorrow, diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol, symbol_ref: SymbolRef,
row_index: u32, row_index: u32,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
) -> Vec<HoverItem> { ) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize; let symbol_display = from_symbol_ref(symbol_ref);
let symbol_diff = if symbol_display.is_mapping_symbol { let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff obj_diff
.mapping_symbols .mapping_symbols
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_display.symbol)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
} else { } else {
obj_diff.symbols.get(symbol_idx) obj_diff.symbols.get(symbol_display.symbol)
}; };
let Some(ins_ref) = symbol_diff let Some(ins_ref) = symbol_diff
.and_then(|sd| sd.instruction_rows.get(row_index as usize)) .and_then(|sd| sd.instruction_rows.get(row_index as usize))
@@ -315,7 +312,7 @@ impl GuestDisplay for Component {
return Vec::new(); return Vec::new();
}; };
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else { let Some(resolved) = obj.resolve_instruction_ref(symbol_display.symbol, ins_ref) else {
return vec![HoverItem::Text(HoverItemText { return vec![HoverItem::Text(HoverItemText {
label: "Error".to_string(), label: "Error".to_string(),
value: "Failed to resolve instruction".to_string(), value: "Failed to resolve instruction".to_string(),
@@ -497,20 +494,56 @@ impl GuestObject for ResourceObject {
} }
impl GuestObjectDiff for ResourceObjectDiff { impl GuestObjectDiff for ResourceObjectDiff {
fn find_symbol(&self, name: String, section_name: Option<String>) -> Option<SymbolRef> { fn find_symbol(&self, name: String, section_name: Option<String>) -> Option<SymbolInfo> {
let obj = self.0.as_ref(); let obj = self.0.as_ref();
obj.symbols let symbol_idx = obj.symbols.iter().position(|s| {
.iter() s.name == name
.position(|s| { && match section_name.as_deref() {
s.name == name Some(section_name) => {
&& match section_name.as_deref() { s.section.is_some_and(|n| obj.sections[n].name == section_name)
Some(section_name) => {
s.section.is_some_and(|n| obj.sections[n].name == section_name)
}
None => true,
} }
}) None => true,
.map(|i| i as SymbolRef) }
})?;
let symbol = obj.symbols.get(symbol_idx)?;
Some(SymbolInfo {
id: symbol_idx as SymbolRef,
name: symbol.name.clone(),
demangled_name: symbol.demangled_name.clone(),
address: symbol.address,
size: symbol.size,
kind: SymbolKind::from(symbol.kind),
section: symbol.section.map(|s| s as u32),
section_name: symbol
.section
.and_then(|s| obj.sections.get(s).map(|sec| sec.name.clone())),
flags: SymbolFlags::from(symbol.flags),
align: symbol.align.map(|a| a.get()),
virtual_address: symbol.virtual_address,
})
}
fn get_symbol(&self, symbol_ref: SymbolRef) -> Option<SymbolInfo> {
let obj = self.0.as_ref();
let symbol_display = from_symbol_ref(symbol_ref);
let Some(symbol) = obj.symbols.get(symbol_display.symbol) else {
return None;
};
Some(SymbolInfo {
id: to_symbol_ref(symbol_display),
name: symbol.name.clone(),
demangled_name: symbol.demangled_name.clone(),
address: symbol.address,
size: symbol.size,
kind: SymbolKind::from(symbol.kind),
section: symbol.section.map(|s| s as u32),
section_name: symbol
.section
.and_then(|s| obj.sections.get(s).map(|sec| sec.name.clone())),
flags: SymbolFlags::from(symbol.flags),
align: symbol.align.map(|a| a.get()),
virtual_address: symbol.virtual_address,
})
} }
} }
@@ -580,18 +613,28 @@ impl Default for SymbolFlags {
fn default() -> Self { Self::empty() } fn default() -> Self { Self::empty() }
} }
impl Default for SymbolDisplay { impl Default for SymbolInfo {
fn default() -> Self { fn default() -> Self {
Self { Self {
id: u32::MAX,
name: Default::default(), name: Default::default(),
demangled_name: Default::default(), demangled_name: Default::default(),
address: Default::default(), address: Default::default(),
size: Default::default(), size: Default::default(),
kind: Default::default(), kind: Default::default(),
section: Default::default(), section: Default::default(),
section_name: Default::default(),
flags: Default::default(), flags: Default::default(),
align: Default::default(), align: Default::default(),
virtual_address: Default::default(), virtual_address: Default::default(),
}
}
}
impl Default for SymbolDisplay {
fn default() -> Self {
Self {
info: Default::default(),
target_symbol: Default::default(), target_symbol: Default::default(),
match_percent: Default::default(), match_percent: Default::default(),
diff_score: Default::default(), diff_score: Default::default(),
@@ -600,4 +643,30 @@ impl Default for SymbolDisplay {
} }
} }
impl From<MappingConfig> for diff::MappingConfig {
fn from(config: MappingConfig) -> Self {
Self {
mappings: config.mappings.into_iter().collect(),
selecting_left: config.selecting_left,
selecting_right: config.selecting_right,
}
}
}
fn from_symbol_ref(symbol_ref: SymbolRef) -> diff::display::SectionDisplaySymbol {
diff::display::SectionDisplaySymbol {
symbol: (symbol_ref & !(1 << 31)) as usize,
is_mapping_symbol: (symbol_ref & (1 << 31)) != 0,
}
}
fn to_symbol_ref(display_symbol: diff::display::SectionDisplaySymbol) -> SymbolRef {
if display_symbol.is_mapping_symbol {
// Use the highest bit to indicate a mapping symbol
display_symbol.symbol as u32 | (1 << 31)
} else {
display_symbol.symbol as u32
}
}
export!(Component); export!(Component);

View File

@@ -24,58 +24,8 @@ interface diff {
hash: func() -> u64; hash: func() -> u64;
} }
resource object-diff {
find-symbol: func(
name: string,
section-name: option<string>
) -> option<u32>;
}
record diff-result {
left: option<object-diff>,
right: option<object-diff>,
}
run-diff: func(
left: option<borrow<object>>,
right: option<borrow<object>>,
config: borrow<diff-config>,
) -> result<diff-result, string>;
}
interface display {
use diff.{
object,
object-diff,
diff-config
};
type symbol-ref = u32; type symbol-ref = u32;
record display-config {
show-hidden-symbols: bool,
show-mapped-symbols: bool,
reverse-fn-order: bool,
}
record symbol-filter {
regex: option<string>,
mapping: option<symbol-ref>,
}
record section-display-symbol {
symbol: symbol-ref,
is-mapping-symbol: bool,
}
record section-display {
id: string,
name: string,
size: u64,
match-percent: option<f32>,
symbols: list<section-display-symbol>,
}
enum symbol-kind { enum symbol-kind {
unknown, unknown,
function, function,
@@ -94,17 +44,74 @@ interface display {
ignored, ignored,
} }
record symbol-display { record symbol-info {
id: symbol-ref,
name: string, name: string,
demangled-name: option<string>, demangled-name: option<string>,
address: u64, address: u64,
size: u64, size: u64,
kind: symbol-kind, kind: symbol-kind,
section: option<u32>, section: option<u32>,
section-name: option<string>,
%flags: symbol-flags, %flags: symbol-flags,
align: option<u32>, align: option<u32>,
virtual-address: option<u64>, virtual-address: option<u64>,
}
resource object-diff {
find-symbol: func(
name: string,
section-name: option<string>
) -> option<symbol-info>;
get-symbol: func(
id: u32
) -> option<symbol-info>;
}
record diff-result {
left: option<object-diff>,
right: option<object-diff>,
}
run-diff: func(
left: option<borrow<object>>,
right: option<borrow<object>>,
config: borrow<diff-config>,
mapping: mapping-config,
) -> result<diff-result, string>;
}
interface display {
use diff.{
object,
object-diff,
diff-config,
symbol-info,
symbol-ref
};
record display-config {
show-hidden-symbols: bool,
show-mapped-symbols: bool,
reverse-fn-order: bool,
}
record symbol-filter {
regex: option<string>,
mapping: option<symbol-ref>,
}
record section-display {
id: string,
name: string,
size: u64,
match-percent: option<f32>,
symbols: list<symbol-ref>,
}
record symbol-display {
info: symbol-info,
target-symbol: option<symbol-ref>, target-symbol: option<symbol-ref>,
match-percent: option<f32>, match-percent: option<f32>,
diff-score: option<tuple<u64, u64>>, diff-score: option<tuple<u64, u64>>,
@@ -232,36 +239,36 @@ interface display {
display-symbol: func( display-symbol: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: symbol-ref,
) -> symbol-display; ) -> symbol-display;
display-instruction-row: func( display-instruction-row: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: symbol-ref,
row-index: u32, row-index: u32,
config: borrow<diff-config>, config: borrow<diff-config>,
) -> instruction-diff-row; ) -> instruction-diff-row;
symbol-context: func( symbol-context: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: symbol-ref,
) -> list<context-item>; ) -> list<context-item>;
symbol-hover: func( symbol-hover: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: symbol-ref,
) -> list<hover-item>; ) -> list<hover-item>;
instruction-context: func( instruction-context: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: symbol-ref,
row-index: u32, row-index: u32,
config: borrow<diff-config>, config: borrow<diff-config>,
) -> list<context-item>; ) -> list<context-item>;
instruction-hover: func( instruction-hover: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: symbol-ref,
row-index: u32, row-index: u32,
config: borrow<diff-config>, config: borrow<diff-config>,
) -> list<hover-item>; ) -> list<hover-item>;