diff --git a/crates/debug/src/read_debuginfo.rs b/crates/debug/src/read_debuginfo.rs index 25b4e3fbc4..014e81fd65 100644 --- a/crates/debug/src/read_debuginfo.rs +++ b/crates/debug/src/read_debuginfo.rs @@ -1,3 +1,4 @@ +use anyhow::{bail, Result}; use gimli::{ DebugAbbrev, DebugAddr, DebugInfo, DebugLine, DebugLineStr, DebugLoc, DebugLocLists, DebugRanges, DebugRngLists, DebugStr, DebugStrOffsets, DebugTypes, EndianSlice, LittleEndian, @@ -42,7 +43,7 @@ pub struct DebugInfoData<'a> { pub wasm_file: WasmFileInfo, } -fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Dwarf<'a> { +fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Result> { const EMPTY_SECTION: &[u8] = &[]; let endian = LittleEndian; @@ -61,20 +62,20 @@ fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Dwarf<'a> { ); if sections.contains_key(".debug_addr") { - panic!("Unexpected .debug_addr"); + bail!("Unexpected .debug_addr"); } let debug_addr = DebugAddr::from(EndianSlice::new(EMPTY_SECTION, endian)); if sections.contains_key(".debug_line_str") { - panic!("Unexpected .debug_line_str"); + bail!("Unexpected .debug_line_str"); } let debug_line_str = DebugLineStr::from(EndianSlice::new(EMPTY_SECTION, endian)); let debug_str_sup = DebugStr::from(EndianSlice::new(EMPTY_SECTION, endian)); if sections.contains_key(".debug_rnglists") { - panic!("Unexpected .debug_rnglists"); + bail!("Unexpected .debug_rnglists"); } let debug_ranges = match sections.get(".debug_ranges") { @@ -85,7 +86,7 @@ fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Dwarf<'a> { let ranges = RangeLists::new(debug_ranges, debug_rnglists); if sections.contains_key(".debug_loclists") { - panic!("Unexpected .debug_loclists"); + bail!("Unexpected .debug_loclists"); } let debug_loc = match sections.get(".debug_loc") { @@ -96,18 +97,18 @@ fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Dwarf<'a> { let locations = LocationLists::new(debug_loc, debug_loclists); if sections.contains_key(".debug_str_offsets") { - panic!("Unexpected .debug_str_offsets"); + bail!("Unexpected .debug_str_offsets"); } let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(EMPTY_SECTION, endian)); if sections.contains_key(".debug_types") { - panic!("Unexpected .debug_types"); + bail!("Unexpected .debug_types"); } let debug_types = DebugTypes::from(EndianSlice::new(EMPTY_SECTION, endian)); - Dwarf { + Ok(Dwarf { debug_abbrev, debug_addr, debug_info, @@ -119,7 +120,7 @@ fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Dwarf<'a> { debug_types, locations, ranges, - } + }) } fn read_name_section(reader: wasmparser::NameSectionReader) -> wasmparser::Result { @@ -158,8 +159,8 @@ fn read_name_section(reader: wasmparser::NameSectionReader) -> wasmparser::Resul Ok(result) } -pub fn read_debuginfo(data: &[u8]) -> DebugInfoData { - let mut reader = ModuleReader::new(data).expect("reader"); +pub fn read_debuginfo(data: &[u8]) -> Result { + let mut reader = ModuleReader::new(data)?; let mut sections = HashMap::new(); let mut name_section = None; let mut code_section_offset = 0; @@ -169,13 +170,13 @@ pub fn read_debuginfo(data: &[u8]) -> DebugInfoData { let mut func_locals: Vec> = Vec::new(); while !reader.eof() { - let section = reader.read().expect("section"); + let section = reader.read()?; match section.code { SectionCode::Custom { name, .. } => { if name.starts_with(".debug_") { let mut reader = section.get_binary_reader(); let len = reader.bytes_remaining(); - sections.insert(name, reader.read_bytes(len).expect("bytes")); + sections.insert(name, reader.read_bytes(len)?); } if name == "name" { if let Ok(reader) = section.get_name_section_reader() { @@ -187,38 +188,31 @@ pub fn read_debuginfo(data: &[u8]) -> DebugInfoData { } SectionCode::Type => { signatures_params = section - .get_type_section_reader() - .expect("type section") + .get_type_section_reader()? .into_iter() - .map(|ft| ft.expect("type").params) - .collect::>(); + .map(|ft| Ok(ft?.params)) + .collect::>>()?; } SectionCode::Function => { func_params_refs = section - .get_function_section_reader() - .expect("function section") + .get_function_section_reader()? .into_iter() - .map(|index| index.expect("func index") as usize) - .collect::>(); + .map(|index| Ok(index? as usize)) + .collect::>>()?; } SectionCode::Code => { code_section_offset = section.range().start as u64; func_locals = section - .get_code_section_reader() - .expect("code section") + .get_code_section_reader()? .into_iter() .map(|body| { - let locals = body - .expect("body") - .get_locals_reader() - .expect("locals reader"); - locals + let locals = body?.get_locals_reader()?; + Ok(locals .into_iter() - .collect::, _>>() - .expect("locals data") - .into_boxed_slice() + .collect::, _>>()? + .into_boxed_slice()) }) - .collect::>(); + .collect::>>()?; } _ => (), } @@ -233,13 +227,14 @@ pub fn read_debuginfo(data: &[u8]) -> DebugInfoData { }) .collect::>(); - DebugInfoData { - dwarf: convert_sections(sections), + let dwarf = convert_sections(sections)?; + Ok(DebugInfoData { + dwarf, name_section, wasm_file: WasmFileInfo { path: None, code_section_offset, funcs: func_meta.into_boxed_slice(), }, - } + }) } diff --git a/crates/debug/src/transform/attr.rs b/crates/debug/src/transform/attr.rs index ef9e430418..5bc3a8f9c0 100644 --- a/crates/debug/src/transform/attr.rs +++ b/crates/debug/src/transform/attr.rs @@ -3,7 +3,7 @@ use super::expression::{compile_expression, CompiledExpression, FunctionFrameInf use super::range_info_builder::RangeInfoBuilder; use super::refs::{PendingDebugInfoRefs, PendingUnitRefs}; use super::{DebugInputContext, Reader, TransformError}; -use anyhow::Error; +use anyhow::{bail, Error}; use gimli::{write, AttributeValue, DebugLineOffset, DebugStr, DebuggingInformationEntry}; use wasmtime_environ::isa::TargetIsa; @@ -143,7 +143,7 @@ where addr_tr, frame_info, endian, - ) { + )? { if len == 0 { // Ignore empty range continue; @@ -183,7 +183,7 @@ where // Conversion to loclist is required. if let Some(scope_ranges) = scope_ranges { let exprs = - expr.build_with_locals(scope_ranges, addr_tr, frame_info, endian); + expr.build_with_locals(scope_ranges, addr_tr, frame_info, endian)?; if exprs.is_empty() { continue; } @@ -252,7 +252,7 @@ where pending_di_refs.insert(current_scope_id, attr.name(), offset); continue; } - _ => panic!(), //write::AttributeValue::StringRef(out_strings.add("_")), + a => bail!("Unexpected attribute: {:?}", a), }; let current_scope = out_unit.get_mut(current_scope_id); current_scope.set(attr.name(), attr_value); @@ -265,7 +265,7 @@ pub(crate) fn clone_attr_string( form: gimli::DwForm, debug_str: &DebugStr, out_strings: &mut write::StringTable, -) -> Result +) -> Result where R: Reader, { @@ -274,7 +274,7 @@ where debug_str.get_str(*str_offset)?.to_slice()?.to_vec() } AttributeValue::String(b) => b.to_slice()?.to_vec(), - _ => panic!("Unexpected attribute value"), + v => bail!("Unexpected attribute value: {:?}", v), }; Ok(match form { gimli::DW_FORM_strp => { @@ -282,6 +282,6 @@ where write::LineString::StringRef(id) } gimli::DW_FORM_string => write::LineString::String(content), - _ => panic!("DW_FORM_line_strp or other not supported"), + _ => bail!("DW_FORM_line_strp or other not supported"), }) } diff --git a/crates/debug/src/transform/expression.rs b/crates/debug/src/transform/expression.rs index 277dd6bd97..7461ea7007 100644 --- a/crates/debug/src/transform/expression.rs +++ b/crates/debug/src/transform/expression.rs @@ -1,5 +1,5 @@ use super::address_transform::AddressTransform; -use anyhow::Error; +use anyhow::{bail, Context, Error, Result}; use gimli::{self, write, Expression, Operation, Reader, ReaderOffset, Register, X86_64}; use more_asserts::{assert_le, assert_lt}; use std::collections::{HashMap, HashSet}; @@ -70,7 +70,7 @@ impl<'a> CompiledExpression<'a> { } } -fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Register { +fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Result { // TODO avoid duplication with fde.rs assert!(isa.name() == "x86" && isa.pointer_bits() == 64); // Mapping from https://github.com/bytecodealliance/cranelift/pull/902 by @iximeow @@ -116,11 +116,11 @@ fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Register { "IntRegs" => { // x86 GP registers have a weird mapping to DWARF registers, so we use a // lookup table. - X86_GP_REG_MAP[(reg - bank.first_unit) as usize] + Ok(X86_GP_REG_MAP[(reg - bank.first_unit) as usize]) } - "FloatRegs" => X86_XMM_REG_MAP[(reg - bank.first_unit) as usize], - _ => { - panic!("unsupported register bank: {}", bank.name); + "FloatRegs" => Ok(X86_XMM_REG_MAP[(reg - bank.first_unit) as usize]), + bank_name => { + bail!("unsupported register bank: {}", bank_name); } } } @@ -129,22 +129,18 @@ fn translate_loc( loc: ValueLoc, frame_info: Option<&FunctionFrameInfo>, isa: &dyn TargetIsa, -) -> Option> { +) -> Result>> { use gimli::write::Writer; - match loc { + Ok(match loc { ValueLoc::Reg(reg) => { - let machine_reg = map_reg(isa, reg).0 as u8; + let machine_reg = map_reg(isa, reg)?.0 as u8; Some(if machine_reg < 32 { vec![gimli::constants::DW_OP_reg0.0 + machine_reg] } else { let endian = gimli::RunTimeEndian::Little; let mut writer = write::EndianVec::new(endian); - writer - .write_u8(gimli::constants::DW_OP_regx.0 as u8) - .expect("regx"); - writer - .write_uleb128(machine_reg.into()) - .expect("machine_reg"); + writer.write_u8(gimli::constants::DW_OP_regx.0 as u8)?; + writer.write_uleb128(machine_reg.into())?; writer.into_vec() }) } @@ -153,21 +149,17 @@ fn translate_loc( if let Some(ss_offset) = frame_info.stack_slots[ss].offset { let endian = gimli::RunTimeEndian::Little; let mut writer = write::EndianVec::new(endian); - writer - .write_u8(gimli::constants::DW_OP_breg0.0 + X86_64::RBP.0 as u8) - .expect("bp wr"); - writer.write_sleb128(ss_offset as i64 + 16).expect("ss wr"); - writer - .write_u8(gimli::constants::DW_OP_deref.0 as u8) - .expect("bp wr"); + writer.write_u8(gimli::constants::DW_OP_breg0.0 + X86_64::RBP.0 as u8)?; + writer.write_sleb128(ss_offset as i64 + 16)?; + writer.write_u8(gimli::constants::DW_OP_deref.0 as u8)?; let buf = writer.into_vec(); - return Some(buf); + return Ok(Some(buf)); } } None } _ => None, - } + }) } fn append_memory_deref( @@ -176,13 +168,13 @@ fn append_memory_deref( vmctx_loc: ValueLoc, endian: gimli::RunTimeEndian, isa: &dyn TargetIsa, -) -> write::Result { +) -> Result { use gimli::write::Writer; let mut writer = write::EndianVec::new(endian); // FIXME for imported memory match vmctx_loc { ValueLoc::Reg(vmctx_reg) => { - let reg = map_reg(isa, vmctx_reg); + let reg = map_reg(isa, vmctx_reg)?; writer.write_u8(gimli::constants::DW_OP_breg0.0 + reg.0 as u8)?; let memory_offset = match frame_info.vmctx_memory_offset() { Some(offset) => offset, @@ -248,9 +240,9 @@ impl<'a> CompiledExpression<'a> { addr_tr: &AddressTransform, frame_info: Option<&FunctionFrameInfo>, endian: gimli::RunTimeEndian, - ) -> Vec<(write::Address, u64, write::Expression)> { + ) -> Result> { if scope.is_empty() { - return vec![]; + return Ok(vec![]); } if let [CompiledExpressionPart::Code(code)] = self.parts.as_slice() { @@ -260,7 +252,7 @@ impl<'a> CompiledExpression<'a> { result_scope.push((addr, len, write::Expression(code.to_vec()))); } } - return result_scope; + return Ok(result_scope); } let vmctx_label = get_vmctx_value_label(); @@ -295,8 +287,8 @@ impl<'a> CompiledExpression<'a> { match part { CompiledExpressionPart::Code(c) => code_buf.extend_from_slice(c.as_slice()), CompiledExpressionPart::Local(label) => { - let loc = *label_location.get(&label).expect("loc"); - if let Some(expr) = translate_loc(loc, frame_info, self.isa) { + let loc = *label_location.get(&label).context("label_location")?; + if let Some(expr) = translate_loc(loc, frame_info, self.isa)? { code_buf.extend_from_slice(&expr) } else { continue 'range; @@ -312,9 +304,7 @@ impl<'a> CompiledExpression<'a> { *vmctx_loc, endian, self.isa, - ) - .expect("append_memory_deref") - { + )? { continue 'range; } } else { @@ -327,9 +317,13 @@ impl<'a> CompiledExpression<'a> { if let (Some(vmctx_loc), Some(frame_info)) = (label_location.get(&vmctx_label), frame_info) { - if !append_memory_deref(&mut code_buf, frame_info, *vmctx_loc, endian, self.isa) - .expect("append_memory_deref") - { + if !append_memory_deref( + &mut code_buf, + frame_info, + *vmctx_loc, + endian, + self.isa, + )? { continue 'range; } } else { @@ -346,7 +340,7 @@ impl<'a> CompiledExpression<'a> { )); } - result + Ok(result) } } diff --git a/crates/debug/src/transform/line_program.rs b/crates/debug/src/transform/line_program.rs index f0e715519f..9b3792eb70 100644 --- a/crates/debug/src/transform/line_program.rs +++ b/crates/debug/src/transform/line_program.rs @@ -1,7 +1,7 @@ use super::address_transform::AddressTransform; use super::attr::clone_attr_string; use super::{Reader, TransformError}; -use anyhow::Error; +use anyhow::{Context, Error}; use gimli::{ write, DebugLine, DebugLineOffset, DebugStr, DebuggingInformationEntry, LineEncoding, Unit, }; @@ -56,13 +56,13 @@ where let comp_dir = root.attr_value(gimli::DW_AT_comp_dir)?; let comp_name = root.attr_value(gimli::DW_AT_name)?; let out_comp_dir = clone_attr_string( - comp_dir.as_ref().expect("comp_dir"), + comp_dir.as_ref().context("comp_dir")?, gimli::DW_FORM_strp, debug_str, out_strings, )?; let out_comp_name = clone_attr_string( - comp_name.as_ref().expect("comp_name"), + comp_name.as_ref().context("comp_name")?, gimli::DW_FORM_strp, debug_str, out_strings, diff --git a/crates/debug/src/transform/simulate.rs b/crates/debug/src/transform/simulate.rs index f2a6a512b8..9d3d579f06 100644 --- a/crates/debug/src/transform/simulate.rs +++ b/crates/debug/src/transform/simulate.rs @@ -2,7 +2,7 @@ use super::expression::{CompiledExpression, FunctionFrameInfo}; use super::utils::{add_internal_types, append_vmctx_info, get_function_frame_info}; use super::AddressTransform; use crate::read_debuginfo::WasmFileInfo; -use anyhow::Error; +use anyhow::{Context, Error}; use gimli::write; use gimli::{self, LineEncoding}; use std::collections::{HashMap, HashSet}; @@ -177,7 +177,7 @@ fn generate_vars( locals_names: Option<&HashMap>, out_strings: &mut write::StringTable, isa: &dyn TargetIsa, -) { +) -> Result<(), Error> { let vmctx_label = get_vmctx_value_label(); // Normalize order of ValueLabelsRanges keys to have reproducable results. @@ -195,8 +195,7 @@ fn generate_vars( scope_ranges, out_strings, isa, - ) - .expect("append_vmctx_info success"); + )?; } else { let var_index = label.index(); let (type_die_id, is_param) = @@ -213,7 +212,7 @@ fn generate_vars( let expr = CompiledExpression::from_label(*label, isa); let mut locs = Vec::new(); for (begin, length, data) in - expr.build_with_locals(scope_ranges, addr_tr, Some(frame_info), endian) + expr.build_with_locals(scope_ranges, addr_tr, Some(frame_info), endian)? { locs.push(write::Location::StartLength { begin, @@ -250,6 +249,7 @@ fn generate_vars( ); } } + Ok(()) } pub fn generate_simulated_dwarf( @@ -279,8 +279,17 @@ pub fn generate_simulated_dwarf( }; let (unit, root_id, name_id) = { - let comp_dir_id = out_strings.add(path.parent().expect("path dir").to_str().unwrap()); - let name = path.file_name().expect("path name").to_str().unwrap(); + let comp_dir_id = out_strings.add( + path.parent() + .context("path dir")? + .to_str() + .context("path dir encoding")?, + ); + let name = path + .file_name() + .context("path name")? + .to_str() + .context("path name encoding")?; let name_id = out_strings.add(name); let out_program = generate_line_info( @@ -370,7 +379,7 @@ pub fn generate_simulated_dwarf( locals_names.and_then(|m| m.get(&(index as u32))), out_strings, isa, - ); + )?; } } diff --git a/crates/debug/src/transform/unit.rs b/crates/debug/src/transform/unit.rs index 56c67f27c7..c019fd944b 100644 --- a/crates/debug/src/transform/unit.rs +++ b/crates/debug/src/transform/unit.rs @@ -6,7 +6,7 @@ use super::range_info_builder::RangeInfoBuilder; use super::refs::{PendingDebugInfoRefs, PendingUnitRefs, UnitRefsMap}; use super::utils::{add_internal_types, append_vmctx_info, get_function_frame_info}; use super::{DebugInputContext, Reader, TransformError}; -use anyhow::Error; +use anyhow::{Context, Error}; use gimli::write; use gimli::{AttributeValue, DebuggingInformationEntry, Unit}; use std::collections::HashSet; @@ -356,7 +356,7 @@ where vmctx_die_id, addr_tr, current_value_range.top(), - current_scope_ranges.top().expect("range"), + current_scope_ranges.top().context("range")?, out_strings, isa, )?; diff --git a/crates/debug/src/transform/utils.rs b/crates/debug/src/transform/utils.rs index 88f0cea491..cf4885f94c 100644 --- a/crates/debug/src/transform/utils.rs +++ b/crates/debug/src/transform/utils.rs @@ -118,7 +118,7 @@ pub(crate) fn append_vmctx_info( let expr = CompiledExpression::vmctx(isa); let mut locs = Vec::new(); for (begin, length, data) in - expr.build_with_locals(scope_ranges, addr_tr, frame_info, endian) + expr.build_with_locals(scope_ranges, addr_tr, frame_info, endian)? { locs.push(write::Location::StartLength { begin, diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 957f1c4099..3c44dff4fb 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -71,7 +71,9 @@ impl<'data> RawCompiledModule<'data> { .map_err(|error| SetupError::Compile(CompileError::Wasm(error)))?; let debug_data = if debug_info { - Some(read_debuginfo(&data)) + // TODO Do we want to ignore invalid DWARF data? + let debug_data = read_debuginfo(&data)?; + Some(debug_data) } else { None }; diff --git a/src/obj.rs b/src/obj.rs index 0adf4aa3fb..74419c5810 100644 --- a/src/obj.rs +++ b/src/obj.rs @@ -136,7 +136,7 @@ pub fn compile_to_obj( .context("failed to emit module")?; if debug_info { - let debug_data = read_debuginfo(wasm); + let debug_data = read_debuginfo(wasm).context("failed to emit DWARF")?; emit_debugsections( &mut obj, &module_vmctx_info,