Skip to content

Commit a57e5db

Browse files
committed
WASM API updates, support symbol mapping
1 parent d0afd3b commit a57e5db

File tree

2 files changed

+186
-110
lines changed

2 files changed

+186
-110
lines changed

objdiff-wasm/src/api.rs

Lines changed: 135 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ wit_bindgen::generate!({
2424
use exports::objdiff::core::{
2525
diff::{
2626
DiffConfigBorrow, DiffResult, Guest as GuestDiff, GuestDiffConfig, GuestObject,
27-
GuestObjectDiff, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow,
27+
GuestObjectDiff, MappingConfig, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow,
28+
SymbolFlags, SymbolInfo, SymbolKind, SymbolRef,
2829
},
2930
display::{
3031
ContextItem, ContextItemCopy, ContextItemNavigate, DiffText, DiffTextColor, DiffTextOpcode,
3132
DiffTextSegment, DiffTextSymbol, DisplayConfig, Guest as GuestDisplay, HoverItem,
3233
HoverItemColor, HoverItemText, InstructionDiffKind, InstructionDiffRow, SectionDisplay,
33-
SectionDisplaySymbol, SymbolDisplay, SymbolFilter, SymbolFlags, SymbolKind,
34-
SymbolNavigationKind, SymbolRef,
34+
SymbolDisplay, SymbolFilter, SymbolNavigationKind,
3535
},
3636
};
3737

@@ -59,15 +59,17 @@ impl GuestDiff for Component {
5959
left: Option<ObjectBorrow>,
6060
right: Option<ObjectBorrow>,
6161
diff_config: DiffConfigBorrow,
62+
mapping_config: MappingConfig,
6263
) -> Result<DiffResult, String> {
6364
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
65+
let mapping_config = diff::MappingConfig::from(mapping_config);
6466
log::debug!("Running diff with config: {:?}", diff_config);
6567
let result = diff::diff_objs(
6668
left.as_ref().map(|o| o.get::<ResourceObject>().0.as_ref()),
6769
right.as_ref().map(|o| o.get::<ResourceObject>().0.as_ref()),
6870
None,
6971
&diff_config,
70-
&diff::MappingConfig::default(),
72+
&mapping_config,
7173
)
7274
.map_err(|e| e.to_string())?;
7375
Ok(DiffResult {
@@ -134,48 +136,47 @@ impl GuestDisplay for Component {
134136
name: d.name,
135137
size: d.size,
136138
match_percent: d.match_percent,
137-
symbols: d
138-
.symbols
139-
.into_iter()
140-
.map(|s| SectionDisplaySymbol {
141-
symbol: s.symbol as SymbolRef,
142-
is_mapping_symbol: s.is_mapping_symbol,
143-
})
144-
.collect(),
139+
symbols: d.symbols.into_iter().map(to_symbol_ref).collect(),
145140
})
146141
.collect()
147142
}
148143

149-
fn display_symbol(
150-
diff: ObjectDiffBorrow,
151-
symbol_display: SectionDisplaySymbol,
152-
) -> SymbolDisplay {
144+
fn display_symbol(diff: ObjectDiffBorrow, symbol_ref: SymbolRef) -> SymbolDisplay {
153145
let obj_diff = diff.get::<ResourceObjectDiff>();
154146
let obj = obj_diff.0.as_ref();
155147
let obj_diff = &obj_diff.1;
156-
let symbol_idx = symbol_display.symbol as usize;
157-
let Some(symbol) = obj.symbols.get(symbol_idx) else {
158-
return SymbolDisplay { name: "<unknown>".to_string(), ..Default::default() };
148+
let symbol_display = from_symbol_ref(symbol_ref);
149+
let Some(symbol) = obj.symbols.get(symbol_display.symbol) else {
150+
return SymbolDisplay {
151+
info: SymbolInfo { name: "<unknown>".to_string(), ..Default::default() },
152+
..Default::default()
153+
};
159154
};
160155
let symbol_diff = if symbol_display.is_mapping_symbol {
161156
obj_diff
162157
.mapping_symbols
163158
.iter()
164-
.find(|s| s.symbol_index == symbol_idx)
159+
.find(|s| s.symbol_index == symbol_display.symbol)
165160
.map(|s| &s.symbol_diff)
166161
} else {
167-
obj_diff.symbols.get(symbol_idx)
162+
obj_diff.symbols.get(symbol_display.symbol)
168163
};
169164
SymbolDisplay {
170-
name: symbol.name.clone(),
171-
demangled_name: symbol.demangled_name.clone(),
172-
address: symbol.address,
173-
size: symbol.size,
174-
kind: SymbolKind::from(symbol.kind),
175-
section: symbol.section.map(|s| s as u32),
176-
flags: SymbolFlags::from(symbol.flags),
177-
align: symbol.align.map(|a| a.get()),
178-
virtual_address: symbol.virtual_address,
165+
info: SymbolInfo {
166+
id: to_symbol_ref(symbol_display),
167+
name: symbol.name.clone(),
168+
demangled_name: symbol.demangled_name.clone(),
169+
address: symbol.address,
170+
size: symbol.size,
171+
kind: SymbolKind::from(symbol.kind),
172+
section: symbol.section.map(|s| s as u32),
173+
section_name: symbol
174+
.section
175+
.and_then(|s| obj.sections.get(s).map(|sec| sec.name.clone())),
176+
flags: SymbolFlags::from(symbol.flags),
177+
align: symbol.align.map(|a| a.get()),
178+
virtual_address: symbol.virtual_address,
179+
},
179180
target_symbol: symbol_diff.and_then(|sd| sd.target_symbol.map(|s| s as u32)),
180181
match_percent: symbol_diff.and_then(|sd| sd.match_percent),
181182
diff_score: symbol_diff.and_then(|sd| sd.diff_score),
@@ -185,57 +186,53 @@ impl GuestDisplay for Component {
185186

186187
fn display_instruction_row(
187188
diff: ObjectDiffBorrow,
188-
symbol_display: SectionDisplaySymbol,
189+
symbol_ref: SymbolRef,
189190
row_index: u32,
190191
diff_config: DiffConfigBorrow,
191192
) -> InstructionDiffRow {
192193
let obj_diff = diff.get::<ResourceObjectDiff>();
193194
let obj = obj_diff.0.as_ref();
194195
let obj_diff = &obj_diff.1;
195-
let symbol_idx = symbol_display.symbol as usize;
196+
let symbol_display = from_symbol_ref(symbol_ref);
196197
let symbol_diff = if symbol_display.is_mapping_symbol {
197198
obj_diff
198199
.mapping_symbols
199200
.iter()
200-
.find(|s| s.symbol_index == symbol_idx)
201+
.find(|s| s.symbol_index == symbol_display.symbol)
201202
.map(|s| &s.symbol_diff)
202203
} else {
203-
obj_diff.symbols.get(symbol_idx)
204+
obj_diff.symbols.get(symbol_display.symbol)
204205
};
205206
let Some(row) = symbol_diff.and_then(|sd| sd.instruction_rows.get(row_index as usize))
206207
else {
207208
return InstructionDiffRow::default();
208209
};
209210
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
210211
let mut segments = Vec::with_capacity(16);
211-
diff::display::display_row(obj, symbol_idx, row, &diff_config, |segment| {
212+
diff::display::display_row(obj, symbol_display.symbol, row, &diff_config, |segment| {
212213
segments.push(DiffTextSegment::from(segment));
213214
Ok(())
214215
})
215216
.unwrap();
216217
InstructionDiffRow { segments, diff_kind: InstructionDiffKind::from(row.kind) }
217218
}
218219

219-
fn symbol_context(
220-
diff: ObjectDiffBorrow,
221-
symbol_display: SectionDisplaySymbol,
222-
) -> Vec<ContextItem> {
220+
fn symbol_context(diff: ObjectDiffBorrow, symbol_ref: SymbolRef) -> Vec<ContextItem> {
223221
let obj_diff = diff.get::<ResourceObjectDiff>();
224222
let obj = obj_diff.0.as_ref();
223+
let symbol_display = from_symbol_ref(symbol_ref);
225224
diff::display::symbol_context(obj, symbol_display.symbol as usize)
226225
.into_iter()
227226
.map(|item| ContextItem::from(item))
228227
.collect()
229228
}
230229

231-
fn symbol_hover(
232-
diff: ObjectDiffBorrow,
233-
symbol_display: SectionDisplaySymbol,
234-
) -> Vec<HoverItem> {
230+
fn symbol_hover(diff: ObjectDiffBorrow, symbol_ref: SymbolRef) -> Vec<HoverItem> {
235231
let obj_diff = diff.get::<ResourceObjectDiff>();
236232
let obj = obj_diff.0.as_ref();
237233
let addend = 0; // TODO
238234
let override_color = None; // TODO: colorize replaced/deleted/inserted relocations
235+
let symbol_display = from_symbol_ref(symbol_ref);
239236
diff::display::symbol_hover(obj, symbol_display.symbol as usize, addend, override_color)
240237
.into_iter()
241238
.map(|item| HoverItem::from(item))
@@ -244,22 +241,22 @@ impl GuestDisplay for Component {
244241

245242
fn instruction_context(
246243
diff: ObjectDiffBorrow,
247-
symbol_display: SectionDisplaySymbol,
244+
symbol_ref: SymbolRef,
248245
row_index: u32,
249246
diff_config: DiffConfigBorrow,
250247
) -> Vec<ContextItem> {
251248
let obj_diff = diff.get::<ResourceObjectDiff>();
252249
let obj = obj_diff.0.as_ref();
253250
let obj_diff = &obj_diff.1;
254-
let symbol_idx = symbol_display.symbol as usize;
251+
let symbol_display = from_symbol_ref(symbol_ref);
255252
let symbol_diff = if symbol_display.is_mapping_symbol {
256253
obj_diff
257254
.mapping_symbols
258255
.iter()
259-
.find(|s| s.symbol_index == symbol_idx)
256+
.find(|s| s.symbol_index == symbol_display.symbol)
260257
.map(|s| &s.symbol_diff)
261258
} else {
262-
obj_diff.symbols.get(symbol_idx)
259+
obj_diff.symbols.get(symbol_display.symbol)
263260
};
264261
let Some(ins_ref) = symbol_diff
265262
.and_then(|sd| sd.instruction_rows.get(row_index as usize))
@@ -268,7 +265,7 @@ impl GuestDisplay for Component {
268265
return Vec::new();
269266
};
270267
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
271-
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
268+
let Some(resolved) = obj.resolve_instruction_ref(symbol_display.symbol, ins_ref) else {
272269
return vec![ContextItem::Copy(ContextItemCopy {
273270
value: "Failed to resolve instruction".to_string(),
274271
label: Some("error".to_string()),
@@ -291,22 +288,22 @@ impl GuestDisplay for Component {
291288

292289
fn instruction_hover(
293290
diff: ObjectDiffBorrow,
294-
symbol_display: SectionDisplaySymbol,
291+
symbol_ref: SymbolRef,
295292
row_index: u32,
296293
diff_config: DiffConfigBorrow,
297294
) -> Vec<HoverItem> {
298295
let obj_diff = diff.get::<ResourceObjectDiff>();
299296
let obj = obj_diff.0.as_ref();
300297
let obj_diff = &obj_diff.1;
301-
let symbol_idx = symbol_display.symbol as usize;
298+
let symbol_display = from_symbol_ref(symbol_ref);
302299
let symbol_diff = if symbol_display.is_mapping_symbol {
303300
obj_diff
304301
.mapping_symbols
305302
.iter()
306-
.find(|s| s.symbol_index == symbol_idx)
303+
.find(|s| s.symbol_index == symbol_display.symbol)
307304
.map(|s| &s.symbol_diff)
308305
} else {
309-
obj_diff.symbols.get(symbol_idx)
306+
obj_diff.symbols.get(symbol_display.symbol)
310307
};
311308
let Some(ins_ref) = symbol_diff
312309
.and_then(|sd| sd.instruction_rows.get(row_index as usize))
@@ -315,7 +312,7 @@ impl GuestDisplay for Component {
315312
return Vec::new();
316313
};
317314
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
318-
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
315+
let Some(resolved) = obj.resolve_instruction_ref(symbol_display.symbol, ins_ref) else {
319316
return vec![HoverItem::Text(HoverItemText {
320317
label: "Error".to_string(),
321318
value: "Failed to resolve instruction".to_string(),
@@ -497,20 +494,56 @@ impl GuestObject for ResourceObject {
497494
}
498495

499496
impl GuestObjectDiff for ResourceObjectDiff {
500-
fn find_symbol(&self, name: String, section_name: Option<String>) -> Option<SymbolRef> {
497+
fn find_symbol(&self, name: String, section_name: Option<String>) -> Option<SymbolInfo> {
501498
let obj = self.0.as_ref();
502-
obj.symbols
503-
.iter()
504-
.position(|s| {
505-
s.name == name
506-
&& match section_name.as_deref() {
507-
Some(section_name) => {
508-
s.section.is_some_and(|n| obj.sections[n].name == section_name)
509-
}
510-
None => true,
499+
let symbol_idx = obj.symbols.iter().position(|s| {
500+
s.name == name
501+
&& match section_name.as_deref() {
502+
Some(section_name) => {
503+
s.section.is_some_and(|n| obj.sections[n].name == section_name)
511504
}
512-
})
513-
.map(|i| i as SymbolRef)
505+
None => true,
506+
}
507+
})?;
508+
let symbol = obj.symbols.get(symbol_idx)?;
509+
Some(SymbolInfo {
510+
id: symbol_idx as SymbolRef,
511+
name: symbol.name.clone(),
512+
demangled_name: symbol.demangled_name.clone(),
513+
address: symbol.address,
514+
size: symbol.size,
515+
kind: SymbolKind::from(symbol.kind),
516+
section: symbol.section.map(|s| s as u32),
517+
section_name: symbol
518+
.section
519+
.and_then(|s| obj.sections.get(s).map(|sec| sec.name.clone())),
520+
flags: SymbolFlags::from(symbol.flags),
521+
align: symbol.align.map(|a| a.get()),
522+
virtual_address: symbol.virtual_address,
523+
})
524+
}
525+
526+
fn get_symbol(&self, symbol_ref: SymbolRef) -> Option<SymbolInfo> {
527+
let obj = self.0.as_ref();
528+
let symbol_display = from_symbol_ref(symbol_ref);
529+
let Some(symbol) = obj.symbols.get(symbol_display.symbol) else {
530+
return None;
531+
};
532+
Some(SymbolInfo {
533+
id: to_symbol_ref(symbol_display),
534+
name: symbol.name.clone(),
535+
demangled_name: symbol.demangled_name.clone(),
536+
address: symbol.address,
537+
size: symbol.size,
538+
kind: SymbolKind::from(symbol.kind),
539+
section: symbol.section.map(|s| s as u32),
540+
section_name: symbol
541+
.section
542+
.and_then(|s| obj.sections.get(s).map(|sec| sec.name.clone())),
543+
flags: SymbolFlags::from(symbol.flags),
544+
align: symbol.align.map(|a| a.get()),
545+
virtual_address: symbol.virtual_address,
546+
})
514547
}
515548
}
516549

@@ -580,18 +613,28 @@ impl Default for SymbolFlags {
580613
fn default() -> Self { Self::empty() }
581614
}
582615

583-
impl Default for SymbolDisplay {
616+
impl Default for SymbolInfo {
584617
fn default() -> Self {
585618
Self {
619+
id: u32::MAX,
586620
name: Default::default(),
587621
demangled_name: Default::default(),
588622
address: Default::default(),
589623
size: Default::default(),
590624
kind: Default::default(),
591625
section: Default::default(),
626+
section_name: Default::default(),
592627
flags: Default::default(),
593628
align: Default::default(),
594629
virtual_address: Default::default(),
630+
}
631+
}
632+
}
633+
634+
impl Default for SymbolDisplay {
635+
fn default() -> Self {
636+
Self {
637+
info: Default::default(),
595638
target_symbol: Default::default(),
596639
match_percent: Default::default(),
597640
diff_score: Default::default(),
@@ -600,4 +643,30 @@ impl Default for SymbolDisplay {
600643
}
601644
}
602645

646+
impl From<MappingConfig> for diff::MappingConfig {
647+
fn from(config: MappingConfig) -> Self {
648+
Self {
649+
mappings: config.mappings.into_iter().collect(),
650+
selecting_left: config.selecting_left,
651+
selecting_right: config.selecting_right,
652+
}
653+
}
654+
}
655+
656+
fn from_symbol_ref(symbol_ref: SymbolRef) -> diff::display::SectionDisplaySymbol {
657+
diff::display::SectionDisplaySymbol {
658+
symbol: (symbol_ref & !(1 << 31)) as usize,
659+
is_mapping_symbol: (symbol_ref & (1 << 31)) != 0,
660+
}
661+
}
662+
663+
fn to_symbol_ref(display_symbol: diff::display::SectionDisplaySymbol) -> SymbolRef {
664+
if display_symbol.is_mapping_symbol {
665+
// Use the highest bit to indicate a mapping symbol
666+
display_symbol.symbol as u32 | (1 << 31)
667+
} else {
668+
display_symbol.symbol as u32
669+
}
670+
}
671+
603672
export!(Component);

0 commit comments

Comments
 (0)