Skip to content

Commit 2bcbc34

Browse files
committed
wasm: Improve API error handling
1 parent 9b557e4 commit 2bcbc34

File tree

3 files changed

+111
-39
lines changed

3 files changed

+111
-39
lines changed

objdiff-wasm/src/api.rs

Lines changed: 100 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use alloc::{
33
rc::{Rc, Weak},
44
str::FromStr,
55
string::{String, ToString},
6+
vec,
67
vec::Vec,
78
};
89
use core::cell::RefCell;
@@ -153,16 +154,17 @@ impl GuestDisplay for Component {
153154
let obj = obj_diff.0.as_ref();
154155
let obj_diff = &obj_diff.1;
155156
let symbol_idx = symbol_display.symbol as usize;
156-
let symbol = &obj.symbols[symbol_idx];
157+
let Some(symbol) = obj.symbols.get(symbol_idx) else {
158+
return SymbolDisplay { name: "<unknown>".to_string(), ..Default::default() };
159+
};
157160
let symbol_diff = if symbol_display.is_mapping_symbol {
158161
obj_diff
159162
.mapping_symbols
160163
.iter()
161164
.find(|s| s.symbol_index == symbol_idx)
162165
.map(|s| &s.symbol_diff)
163-
.unwrap()
164166
} else {
165-
&obj_diff.symbols[symbol_idx]
167+
obj_diff.symbols.get(symbol_idx)
166168
};
167169
SymbolDisplay {
168170
name: symbol.name.clone(),
@@ -174,10 +176,10 @@ impl GuestDisplay for Component {
174176
flags: SymbolFlags::from(symbol.flags),
175177
align: symbol.align.map(|a| a.get()),
176178
virtual_address: symbol.virtual_address,
177-
target_symbol: symbol_diff.target_symbol.map(|s| s as u32),
178-
match_percent: symbol_diff.match_percent,
179-
diff_score: symbol_diff.diff_score,
180-
row_count: symbol_diff.instruction_rows.len() as u32,
179+
target_symbol: symbol_diff.and_then(|sd| sd.target_symbol.map(|s| s as u32)),
180+
match_percent: symbol_diff.and_then(|sd| sd.match_percent),
181+
diff_score: symbol_diff.and_then(|sd| sd.diff_score),
182+
row_count: symbol_diff.map_or(0, |sd| sd.instruction_rows.len() as u32),
181183
}
182184
}
183185

@@ -187,7 +189,6 @@ impl GuestDisplay for Component {
187189
row_index: u32,
188190
diff_config: DiffConfigBorrow,
189191
) -> InstructionDiffRow {
190-
let mut segments = Vec::with_capacity(16);
191192
let obj_diff = diff.get::<ResourceObjectDiff>();
192193
let obj = obj_diff.0.as_ref();
193194
let obj_diff = &obj_diff.1;
@@ -198,12 +199,15 @@ impl GuestDisplay for Component {
198199
.iter()
199200
.find(|s| s.symbol_index == symbol_idx)
200201
.map(|s| &s.symbol_diff)
201-
.unwrap()
202202
} else {
203-
&obj_diff.symbols[symbol_idx]
203+
obj_diff.symbols.get(symbol_idx)
204+
};
205+
let Some(row) = symbol_diff.and_then(|sd| sd.instruction_rows.get(row_index as usize))
206+
else {
207+
return InstructionDiffRow::default();
204208
};
205-
let row = &symbol_diff.instruction_rows[row_index as usize];
206209
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
210+
let mut segments = Vec::with_capacity(16);
207211
diff::display::display_row(obj, symbol_idx, row, &diff_config, |segment| {
208212
segments.push(DiffTextSegment::from(segment));
209213
Ok(())
@@ -230,9 +234,9 @@ impl GuestDisplay for Component {
230234
) -> Vec<HoverItem> {
231235
let obj_diff = diff.get::<ResourceObjectDiff>();
232236
let obj = obj_diff.0.as_ref();
233-
// TODO: colorize replaced/deleted/inserted relocations
234-
let override_color = None;
235-
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0, override_color)
237+
let addend = 0; // TODO
238+
let override_color = None; // TODO: colorize replaced/deleted/inserted relocations
239+
diff::display::symbol_hover(obj, symbol_display.symbol as usize, addend, override_color)
236240
.into_iter()
237241
.map(|item| HoverItem::from(item))
238242
.collect()
@@ -243,7 +247,7 @@ impl GuestDisplay for Component {
243247
symbol_display: SectionDisplaySymbol,
244248
row_index: u32,
245249
diff_config: DiffConfigBorrow,
246-
) -> Result<Vec<ContextItem>, String> {
250+
) -> Vec<ContextItem> {
247251
let obj_diff = diff.get::<ResourceObjectDiff>();
248252
let obj = obj_diff.0.as_ref();
249253
let obj_diff = &obj_diff.1;
@@ -254,32 +258,43 @@ impl GuestDisplay for Component {
254258
.iter()
255259
.find(|s| s.symbol_index == symbol_idx)
256260
.map(|s| &s.symbol_diff)
257-
.unwrap()
258261
} else {
259-
&obj_diff.symbols[symbol_idx]
262+
obj_diff.symbols.get(symbol_idx)
260263
};
261-
let row = &symbol_diff.instruction_rows[row_index as usize];
262-
let Some(ins_ref) = row.ins_ref else {
263-
return Ok(Vec::new());
264+
let Some(ins_ref) = symbol_diff
265+
.and_then(|sd| sd.instruction_rows.get(row_index as usize))
266+
.and_then(|row| row.ins_ref)
267+
else {
268+
return Vec::new();
264269
};
265270
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
266271
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
267-
return Err("Failed to resolve instruction".into());
272+
return vec![ContextItem::Copy(ContextItemCopy {
273+
value: "Failed to resolve instruction".to_string(),
274+
label: Some("error".to_string()),
275+
})];
276+
};
277+
let ins = match obj.arch.process_instruction(resolved, &diff_config) {
278+
Ok(ins) => ins,
279+
Err(e) => {
280+
return vec![ContextItem::Copy(ContextItemCopy {
281+
value: e.to_string(),
282+
label: Some("error".to_string()),
283+
})];
284+
}
268285
};
269-
let ins =
270-
obj.arch.process_instruction(resolved, &diff_config).map_err(|e| e.to_string())?;
271-
Ok(diff::display::instruction_context(obj, resolved, &ins)
286+
diff::display::instruction_context(obj, resolved, &ins)
272287
.into_iter()
273288
.map(|item| ContextItem::from(item))
274-
.collect())
289+
.collect()
275290
}
276291

277292
fn instruction_hover(
278293
diff: ObjectDiffBorrow,
279294
symbol_display: SectionDisplaySymbol,
280295
row_index: u32,
281296
diff_config: DiffConfigBorrow,
282-
) -> Result<Vec<HoverItem>, String> {
297+
) -> Vec<HoverItem> {
283298
let obj_diff = diff.get::<ResourceObjectDiff>();
284299
let obj = obj_diff.0.as_ref();
285300
let obj_diff = &obj_diff.1;
@@ -290,24 +305,37 @@ impl GuestDisplay for Component {
290305
.iter()
291306
.find(|s| s.symbol_index == symbol_idx)
292307
.map(|s| &s.symbol_diff)
293-
.unwrap()
294308
} else {
295-
&obj_diff.symbols[symbol_idx]
309+
obj_diff.symbols.get(symbol_idx)
296310
};
297-
let row = &symbol_diff.instruction_rows[row_index as usize];
298-
let Some(ins_ref) = row.ins_ref else {
299-
return Ok(Vec::new());
311+
let Some(ins_ref) = symbol_diff
312+
.and_then(|sd| sd.instruction_rows.get(row_index as usize))
313+
.and_then(|row| row.ins_ref)
314+
else {
315+
return Vec::new();
300316
};
301317
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
302318
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
303-
return Err("Failed to resolve instruction".into());
319+
return vec![HoverItem::Text(HoverItemText {
320+
label: "Error".to_string(),
321+
value: "Failed to resolve instruction".to_string(),
322+
color: HoverItemColor::Delete,
323+
})];
304324
};
305-
let ins =
306-
obj.arch.process_instruction(resolved, &diff_config).map_err(|e| e.to_string())?;
307-
Ok(diff::display::instruction_hover(obj, resolved, &ins)
325+
let ins = match obj.arch.process_instruction(resolved, &diff_config) {
326+
Ok(ins) => ins,
327+
Err(e) => {
328+
return vec![HoverItem::Text(HoverItemText {
329+
label: "Error".to_string(),
330+
value: e.to_string(),
331+
color: HoverItemColor::Delete,
332+
})];
333+
}
334+
};
335+
diff::display::instruction_hover(obj, resolved, &ins)
308336
.into_iter()
309337
.map(|item| HoverItem::from(item))
310-
.collect())
338+
.collect()
311339
}
312340
}
313341

@@ -536,4 +564,40 @@ impl From<diff::display::SymbolNavigationKind> for SymbolNavigationKind {
536564
}
537565
}
538566

567+
impl Default for InstructionDiffKind {
568+
fn default() -> Self { Self::None }
569+
}
570+
571+
impl Default for InstructionDiffRow {
572+
fn default() -> Self { Self { segments: Default::default(), diff_kind: Default::default() } }
573+
}
574+
575+
impl Default for SymbolKind {
576+
fn default() -> Self { Self::Unknown }
577+
}
578+
579+
impl Default for SymbolFlags {
580+
fn default() -> Self { Self::empty() }
581+
}
582+
583+
impl Default for SymbolDisplay {
584+
fn default() -> Self {
585+
Self {
586+
name: Default::default(),
587+
demangled_name: Default::default(),
588+
address: Default::default(),
589+
size: Default::default(),
590+
kind: Default::default(),
591+
section: Default::default(),
592+
flags: Default::default(),
593+
align: Default::default(),
594+
virtual_address: Default::default(),
595+
target_symbol: Default::default(),
596+
match_percent: Default::default(),
597+
diff_score: Default::default(),
598+
row_count: Default::default(),
599+
}
600+
}
601+
}
602+
539603
export!(Component);

objdiff-wasm/src/cabi_realloc.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,17 @@ static FORCE_CODEGEN_OF_CABI_REALLOC: unsafe extern "C" fn(
3535
pub unsafe extern "C" fn cabi_realloc(
3636
old_ptr: *mut u8,
3737
old_len: usize,
38-
align: usize,
38+
mut align: usize,
3939
new_len: usize,
4040
) -> *mut u8 {
41+
// HACK: The object crate requires the data alignment for 64-bit objects to be 8,
42+
// but in wasm32, our allocator will have a minimum alignment of 4. We can't specify
43+
// the alignment of `list<u8>` in the component model, so we work around this here.
44+
// https://github.com/WebAssembly/component-model/issues/258
45+
#[cfg(target_pointer_width = "32")]
46+
if align == 1 {
47+
align = 8;
48+
}
4149
let layout;
4250
let ptr = if old_len == 0 {
4351
if new_len == 0 {

objdiff-wasm/wit/objdiff.wit

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,14 +257,14 @@ interface display {
257257
symbol: section-display-symbol,
258258
row-index: u32,
259259
config: borrow<diff-config>,
260-
) -> result<list<context-item>, string>;
260+
) -> list<context-item>;
261261

262262
instruction-hover: func(
263263
diff: borrow<object-diff>,
264264
symbol: section-display-symbol,
265265
row-index: u32,
266266
config: borrow<diff-config>,
267-
) -> result<list<hover-item>, string>;
267+
) -> list<hover-item>;
268268
}
269269

270270
world api {

0 commit comments

Comments
 (0)