1 #[cfg(feature = "coredump")] 2 use super::coredump::WasmCoreDump; 3 #[cfg(feature = "gc")] 4 use crate::ThrownException; 5 use crate::prelude::*; 6 use crate::store::StoreOpaque; 7 use crate::{AsContext, Module}; 8 use core::fmt; 9 use core::num::NonZeroUsize; 10 use wasmtime_environ::{FilePos, demangle_function_name, demangle_function_name_or_index}; 11 12 /// Representation of a WebAssembly trap and what caused it to occur. 13 /// 14 /// WebAssembly traps happen explicitly for instructions such as `unreachable` 15 /// but can also happen as side effects of other instructions such as `i32.load` 16 /// loading an out-of-bounds address. Traps halt the execution of WebAssembly 17 /// and cause an error to be returned to the host. This enumeration is a list of 18 /// all possible traps that can happen in wasm, in addition to some 19 /// Wasmtime-specific trap codes listed here as well. 20 /// 21 /// # Errors in Wasmtime 22 /// 23 /// Error-handling in Wasmtime is primarily done through the 24 /// [`wasmtime::Error`] type where most results are a 25 /// [`wasmtime::Result<T>`] which is an alias for [`Result<T, 26 /// wasmtime::Error>`](std::result::Result). Errors in Wasmtime are represented 27 /// with [`wasmtime::Error`] which acts as a container for any type of error in 28 /// addition to optional context for this error. The "base" error or 29 /// [`wasmtime::Error::root_cause`] is a [`Trap`] whenever WebAssembly hits a 30 /// trap, or otherwise it's whatever the host created the error with when 31 /// returning an error for a host call. 32 /// 33 /// Any error which happens while WebAssembly is executing will also, by 34 /// default, capture a backtrace of the wasm frames while executing. This 35 /// backtrace is represented with a [`WasmBacktrace`] instance and is attached 36 /// to the [`wasmtime::Error`] return value as a 37 /// [`context`](crate::Error::context). Inspecting a [`WasmBacktrace`] can be 38 /// done with the [`downcast_ref`](crate::Error::downcast_ref) function. For 39 /// information on this see the [`WasmBacktrace`] documentation. 40 /// 41 /// [`wasmtime::Error`]: crate::Error 42 /// [`wasmtime::Result<T>`]: crate::Result 43 /// [`wasmtime::Error::root_cause`]: crate::Error::root_cause 44 /// 45 /// # Examples 46 /// 47 /// ``` 48 /// # use wasmtime::*; 49 /// # fn main() -> Result<()> { 50 /// let engine = Engine::default(); 51 /// let module = Module::new( 52 /// &engine, 53 /// r#" 54 /// (module 55 /// (func (export "trap") 56 /// unreachable) 57 /// (func $overflow (export "overflow") 58 /// call $overflow) 59 /// ) 60 /// "#, 61 /// )?; 62 /// let mut store = Store::new(&engine, ()); 63 /// let instance = Instance::new(&mut store, &module, &[])?; 64 /// 65 /// let trap = instance.get_typed_func::<(), ()>(&mut store, "trap")?; 66 /// let error = trap.call(&mut store, ()).unwrap_err(); 67 /// assert_eq!(*error.downcast_ref::<Trap>().unwrap(), Trap::UnreachableCodeReached); 68 /// assert!(error.root_cause().is::<Trap>()); 69 /// 70 /// let overflow = instance.get_typed_func::<(), ()>(&mut store, "overflow")?; 71 /// let error = overflow.call(&mut store, ()).unwrap_err(); 72 /// assert_eq!(*error.downcast_ref::<Trap>().unwrap(), Trap::StackOverflow); 73 /// # Ok(()) 74 /// # } 75 /// ``` 76 pub use wasmtime_environ::Trap; 77 78 #[cold] // traps are exceptional, this helps move handling off the main path 79 pub(crate) fn from_runtime_box( 80 store: &mut StoreOpaque, 81 runtime_trap: Box<crate::runtime::vm::Trap>, 82 ) -> Error { 83 let crate::runtime::vm::Trap { 84 reason, 85 backtrace, 86 coredumpstack, 87 } = *runtime_trap; 88 let (mut error, pc) = match reason { 89 #[cfg(feature = "gc")] 90 crate::runtime::vm::TrapReason::Exception => (ThrownException.into(), None), 91 // For user-defined errors they're already an `crate::Error` so no 92 // conversion is really necessary here, but a `backtrace` may have 93 // been captured so it's attempted to get inserted here. 94 // 95 // If the error is actually a `Trap` then the backtrace is inserted 96 // directly into the `Trap` since there's storage there for it. 97 // Otherwise though this represents a host-defined error which isn't 98 // using a `Trap` but instead some other condition that was fatal to 99 // wasm itself. In that situation the backtrace is inserted as 100 // contextual information on error using `error.context(...)` to 101 // provide useful information to debug with for the embedder/caller, 102 // otherwise the information about what the wasm was doing when the 103 // error was generated would be lost. 104 crate::runtime::vm::TrapReason::User(error) => (error, None), 105 crate::runtime::vm::TrapReason::Jit { 106 pc, 107 faulting_addr, 108 trap, 109 } => { 110 let mut err: Error = trap.into(); 111 112 // If a fault address was present, for example with segfaults, 113 // then simultaneously assert that it's within a known linear memory 114 // and additionally translate it to a wasm-local address to be added 115 // as context to the error. 116 if let Some(fault) = faulting_addr.and_then(|addr| store.wasm_fault(pc, addr)) { 117 err = err.context(fault); 118 } 119 (err, Some(pc)) 120 } 121 crate::runtime::vm::TrapReason::Wasm(trap_code) => (trap_code.into(), None), 122 }; 123 124 if let Some(bt) = backtrace { 125 let bt = WasmBacktrace::from_captured( 126 store, 127 bt, 128 pc, 129 store.engine().config().wasm_backtrace_max_frames, 130 ); 131 if !bt.wasm_trace.is_empty() { 132 error = error.context(bt); 133 } 134 } 135 136 let _ = &coredumpstack; 137 #[cfg(feature = "coredump")] 138 if let Some(coredump) = coredumpstack { 139 let bt = WasmBacktrace::from_captured( 140 store, 141 coredump.bt, 142 pc, 143 store.engine().config().wasm_backtrace_max_frames, 144 ); 145 let cd = WasmCoreDump::new(store, bt); 146 error = error.context(cd); 147 } 148 149 error 150 } 151 152 /// Representation of a backtrace of function frames in a WebAssembly module for 153 /// where an error happened. 154 /// 155 /// This structure is attached to the [`wasmtime::Error`] returned from many 156 /// Wasmtime functions that execute WebAssembly such as [`Instance::new`] or 157 /// [`Func::call`]. This can be acquired with the 158 /// [`Error::downcast`](crate::Error::downcast) family of methods to 159 /// programmatically inspect the backtrace. Otherwise since it's part of the 160 /// error returned this will get printed along with the rest of the error when 161 /// the error is logged. 162 /// 163 /// Capturing of wasm backtraces can be configured through the 164 /// [`Config::wasm_backtrace_max_frames`](crate::Config::wasm_backtrace_max_frames) method. 165 /// 166 /// For more information about errors in wasmtime see the documentation of the 167 /// [`Trap`] type. 168 /// 169 /// [`Func::call`]: crate::Func::call 170 /// [`Instance::new`]: crate::Instance::new 171 /// [`wasmtime::Error`]: crate::Error 172 /// 173 /// # Examples 174 /// 175 /// ``` 176 /// # use wasmtime::*; 177 /// # fn main() -> Result<()> { 178 /// let engine = Engine::default(); 179 /// let module = Module::new( 180 /// &engine, 181 /// r#" 182 /// (module 183 /// (func $start (export "run") 184 /// call $trap) 185 /// (func $trap 186 /// unreachable) 187 /// ) 188 /// "#, 189 /// )?; 190 /// let mut store = Store::new(&engine, ()); 191 /// let instance = Instance::new(&mut store, &module, &[])?; 192 /// let func = instance.get_typed_func::<(), ()>(&mut store, "run")?; 193 /// let error = func.call(&mut store, ()).unwrap_err(); 194 /// let bt = error.downcast_ref::<WasmBacktrace>().unwrap(); 195 /// let frames = bt.frames(); 196 /// assert_eq!(frames.len(), 2); 197 /// assert_eq!(frames[0].func_name(), Some("trap")); 198 /// assert_eq!(frames[1].func_name(), Some("start")); 199 /// # Ok(()) 200 /// # } 201 /// ``` 202 #[derive(Debug)] 203 pub struct WasmBacktrace { 204 wasm_trace: Vec<FrameInfo>, 205 hint_wasm_backtrace_details_env: bool, 206 // This is currently only present for the `Debug` implementation for extra 207 // context. 208 _runtime_trace: crate::runtime::vm::Backtrace, 209 } 210 211 impl WasmBacktrace { 212 /// Captures a trace of the WebAssembly frames on the stack for the 213 /// provided store. 214 /// 215 /// This will return a [`WasmBacktrace`] which holds captured 216 /// [`FrameInfo`]s for each frame of WebAssembly on the call stack of the 217 /// current thread. If no WebAssembly is on the stack then the returned 218 /// backtrace will have no frames in it. 219 /// 220 /// Note that this function will respect the 221 /// [`Config::wasm_backtrace_max_frames`] configuration option and will 222 /// return an empty backtrace if that is set to `None`. To always capture a 223 /// backtrace use the [`WasmBacktrace::force_capture`] method. 224 /// 225 /// Also note that this function will only capture frames from the 226 /// specified `store` on the stack, ignoring frames from other stores if 227 /// present. 228 /// 229 /// [`Config::wasm_backtrace_max_frames`]: crate::Config::wasm_backtrace_max_frames 230 /// 231 /// # Example 232 /// 233 /// ``` 234 /// # use wasmtime::*; 235 /// # fn main() -> Result<()> { 236 /// let engine = Engine::default(); 237 /// let module = Module::new( 238 /// &engine, 239 /// r#" 240 /// (module 241 /// (import "" "" (func $host)) 242 /// (func $foo (export "f") call $bar) 243 /// (func $bar call $host) 244 /// ) 245 /// "#, 246 /// )?; 247 /// 248 /// let mut store = Store::new(&engine, ()); 249 /// let func = Func::wrap(&mut store, |cx: Caller<'_, ()>| { 250 /// let trace = WasmBacktrace::capture(&cx); 251 /// println!("{trace:?}"); 252 /// }); 253 /// let instance = Instance::new(&mut store, &module, &[func.into()])?; 254 /// let func = instance.get_typed_func::<(), ()>(&mut store, "f")?; 255 /// func.call(&mut store, ())?; 256 /// # Ok(()) 257 /// # } 258 /// ``` 259 pub fn capture(store: impl AsContext) -> WasmBacktrace { 260 let store = store.as_context(); 261 if let Some(max_frames) = store.engine().config().wasm_backtrace_max_frames { 262 Self::from_captured( 263 store.0, 264 crate::runtime::vm::Backtrace::new(store.0), 265 None, 266 Some(max_frames), 267 ) 268 } else { 269 WasmBacktrace { 270 wasm_trace: Vec::new(), 271 hint_wasm_backtrace_details_env: false, 272 _runtime_trace: crate::runtime::vm::Backtrace::empty(), 273 } 274 } 275 } 276 277 /// Unconditionally captures a trace of the WebAssembly frames on the stack 278 /// for the provided store. 279 /// 280 /// Same as [`WasmBacktrace::capture`] except that it disregards the 281 /// [`Config::wasm_backtrace_max_frames`](crate::Config::wasm_backtrace_max_frames) 282 /// setting and always captures a backtrace. 283 pub fn force_capture(store: impl AsContext) -> WasmBacktrace { 284 let store = store.as_context(); 285 let max_frames = store 286 .engine() 287 .config() 288 .wasm_backtrace_max_frames 289 .unwrap_or(crate::config::DEFAULT_WASM_BACKTRACE_MAX_FRAMES); 290 Self::from_captured( 291 store.0, 292 crate::runtime::vm::Backtrace::new(store.0), 293 None, 294 Some(max_frames), 295 ) 296 } 297 298 fn from_captured( 299 store: &StoreOpaque, 300 runtime_trace: crate::runtime::vm::Backtrace, 301 trap_pc: Option<usize>, 302 max_frames: Option<NonZeroUsize>, 303 ) -> Self { 304 let Some(max_frames) = max_frames else { 305 return WasmBacktrace { 306 wasm_trace: Vec::new(), 307 hint_wasm_backtrace_details_env: false, 308 _runtime_trace: crate::runtime::vm::Backtrace::empty(), 309 }; 310 }; 311 let mut wasm_trace = Vec::<FrameInfo>::with_capacity(max_frames.get()); 312 let mut hint_wasm_backtrace_details_env = false; 313 let wasm_backtrace_details_env_used = 314 store.engine().config().wasm_backtrace_details_env_used; 315 316 for frame in runtime_trace.frames() { 317 if wasm_trace.len() >= max_frames.get() { 318 break; 319 } 320 321 debug_assert!(frame.pc() != 0); 322 323 // Note that we need to be careful about the pc we pass in 324 // here to lookup frame information. This program counter is 325 // used to translate back to an original source location in 326 // the origin wasm module. If this pc is the exact pc that 327 // the trap happened at, then we look up that pc precisely. 328 // Otherwise backtrace information typically points at the 329 // pc *after* the call instruction (because otherwise it's 330 // likely a call instruction on the stack). In that case we 331 // want to lookup information for the previous instruction 332 // (the call instruction) so we subtract one as the lookup. 333 let pc_to_lookup = if Some(frame.pc()) == trap_pc { 334 frame.pc() 335 } else { 336 frame.pc() - 1 337 }; 338 339 // NB: The PC we are looking up _must_ be a Wasm PC since 340 // `crate::runtime::vm::Backtrace` only contains Wasm frames. 341 // 342 // However, consider the case where we have multiple, nested calls 343 // across stores (with host code in between, by necessity, since 344 // only things in the same store can be linked directly together): 345 // 346 // | ... | 347 // | Host | | 348 // +-----------------+ | stack 349 // | Wasm in store A | | grows 350 // +-----------------+ | down 351 // | Host | | 352 // +-----------------+ | 353 // | Wasm in store B | V 354 // +-----------------+ 355 // 356 // In this scenario, the `crate::runtime::vm::Backtrace` will 357 // contain two frames: Wasm in store B followed by Wasm in store 358 // A. But `store.modules()` will only have the module information 359 // for modules instantiated within this store. Therefore, we use `if 360 // let Some(..)` instead of the `unwrap` you might otherwise expect 361 // and we ignore frames from modules that were not registered in 362 // this store's module registry. 363 if let Some((info, module)) = store.modules().lookup_frame_info(pc_to_lookup) { 364 wasm_trace.push(info); 365 366 // If this frame has unparsed debug information and the 367 // store's configuration indicates that we were 368 // respecting the environment variable of whether to 369 // do this then we will print out a helpful note in 370 // `Display` to indicate that more detailed information 371 // in a trap may be available. 372 let has_unparsed_debuginfo = 373 module.module().compiled_module().has_unparsed_debuginfo(); 374 if has_unparsed_debuginfo 375 && wasm_backtrace_details_env_used 376 && cfg!(feature = "addr2line") 377 { 378 hint_wasm_backtrace_details_env = true; 379 } 380 } 381 } 382 383 Self { 384 wasm_trace, 385 _runtime_trace: runtime_trace, 386 hint_wasm_backtrace_details_env, 387 } 388 } 389 390 /// Returns a list of function frames in WebAssembly this backtrace 391 /// represents. 392 pub fn frames(&self) -> &[FrameInfo] { 393 self.wasm_trace.as_slice() 394 } 395 } 396 397 impl fmt::Display for WasmBacktrace { 398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 399 writeln!(f, "error while executing at wasm backtrace:")?; 400 401 let mut needs_newline = false; 402 for (i, frame) in self.wasm_trace.iter().enumerate() { 403 // Avoid putting a trailing newline on the output 404 if needs_newline { 405 writeln!(f, "")?; 406 } else { 407 needs_newline = true; 408 } 409 let name = frame.module().name().unwrap_or("<unknown>"); 410 write!(f, " {i:>3}: ")?; 411 412 if let Some(offset) = frame.module_offset() { 413 write!(f, "{offset:#8x} - ")?; 414 } 415 416 let write_raw_func_name = |f: &mut fmt::Formatter<'_>| { 417 demangle_function_name_or_index(f, frame.func_name(), frame.func_index() as usize) 418 }; 419 if frame.symbols().is_empty() { 420 write!(f, "{name}!")?; 421 write_raw_func_name(f)?; 422 } else { 423 for (i, symbol) in frame.symbols().iter().enumerate() { 424 if i > 0 { 425 if needs_newline { 426 writeln!(f, "")?; 427 } else { 428 needs_newline = true; 429 } 430 write!(f, " - ")?; 431 } else { 432 // ... 433 } 434 match symbol.name() { 435 Some(name) => demangle_function_name(f, name)?, 436 None if i == 0 => write_raw_func_name(f)?, 437 None => write!(f, "<inlined function>")?, 438 } 439 if let Some(file) = symbol.file() { 440 writeln!(f, "")?; 441 write!(f, " at {file}")?; 442 if let Some(line) = symbol.line() { 443 write!(f, ":{line}")?; 444 if let Some(col) = symbol.column() { 445 write!(f, ":{col}")?; 446 } 447 } 448 } 449 } 450 } 451 } 452 if self.hint_wasm_backtrace_details_env { 453 write!( 454 f, 455 "\nnote: using the `WASMTIME_BACKTRACE_DETAILS=1` \ 456 environment variable may show more debugging information" 457 )?; 458 } 459 Ok(()) 460 } 461 } 462 463 /// Description of a frame in a backtrace for a [`WasmBacktrace`]. 464 /// 465 /// Whenever an error happens while WebAssembly is executing a 466 /// [`WasmBacktrace`] will be attached to the error returned which can be used 467 /// to acquire this `FrameInfo`. For more information see [`WasmBacktrace`]. 468 #[derive(Debug)] 469 pub struct FrameInfo { 470 module: Module, 471 func_index: u32, 472 func_name: Option<String>, 473 func_start: FilePos, 474 instr: Option<FilePos>, 475 symbols: Vec<FrameSymbol>, 476 } 477 478 impl FrameInfo { 479 /// Fetches frame information about a program counter in a backtrace. 480 /// 481 /// Returns an object if this `pc` is known to this module, or returns `None` 482 /// if no information can be found. 483 pub(crate) fn new(module: Module, text_offset: usize) -> Option<FrameInfo> { 484 let compiled_module = module.compiled_module(); 485 let index = compiled_module.func_by_text_offset(text_offset)?; 486 let func_start = compiled_module.func_start_srcloc(index); 487 let instr = 488 wasmtime_environ::lookup_file_pos(module.engine_code().address_map_data(), text_offset); 489 let index = compiled_module.module().func_index(index); 490 let func_index = index.as_u32(); 491 let func_name = compiled_module.func_name(index).map(|s| s.to_string()); 492 493 // In debug mode for now assert that we found a mapping for `pc` within 494 // the function, because otherwise something is buggy along the way and 495 // not accounting for all the instructions. This isn't super critical 496 // though so we can omit this check in release mode. 497 // 498 // Note that if the module doesn't even have an address map due to 499 // compilation settings then it's expected that `instr` is `None`. 500 debug_assert!( 501 instr.is_some() || !compiled_module.has_address_map(), 502 "failed to find instruction for {text_offset:#x}" 503 ); 504 505 // Use our wasm-relative pc to symbolize this frame. If there's a 506 // symbolication context (dwarf debug info) available then we can try to 507 // look this up there. 508 // 509 // Note that dwarf pcs are code-section-relative, hence the subtraction 510 // from the location of `instr`. Also note that all errors are ignored 511 // here for now since technically wasm modules can always have any 512 // custom section contents. 513 let mut symbols = Vec::new(); 514 515 let _ = &mut symbols; 516 #[cfg(feature = "addr2line")] 517 if let Some(s) = &compiled_module.symbolize_context().ok().and_then(|c| c) { 518 if let Some(offset) = instr.and_then(|i| i.file_offset()) { 519 let to_lookup = u64::from(offset) - s.code_section_offset(); 520 if let Ok(mut frames) = s.addr2line().find_frames(to_lookup).skip_all_loads() { 521 while let Ok(Some(frame)) = frames.next() { 522 symbols.push(FrameSymbol { 523 name: frame 524 .function 525 .as_ref() 526 .and_then(|l| l.raw_name().ok()) 527 .map(|s| s.to_string()), 528 file: frame 529 .location 530 .as_ref() 531 .and_then(|l| l.file) 532 .map(|s| s.to_string()), 533 line: frame.location.as_ref().and_then(|l| l.line), 534 column: frame.location.as_ref().and_then(|l| l.column), 535 }); 536 } 537 } 538 } 539 } 540 541 Some(FrameInfo { 542 module, 543 func_index, 544 func_name, 545 instr, 546 func_start, 547 symbols, 548 }) 549 } 550 551 /// Returns the WebAssembly function index for this frame. 552 /// 553 /// This function index is the index in the function index space of the 554 /// WebAssembly module that this frame comes from. 555 pub fn func_index(&self) -> u32 { 556 self.func_index 557 } 558 559 /// Returns the module for this frame. 560 /// 561 /// This is the module who's code was being run in this frame. 562 pub fn module(&self) -> &Module { 563 &self.module 564 } 565 566 /// Returns a descriptive name of the function for this frame, if one is 567 /// available. 568 /// 569 /// The name of this function may come from the `name` section of the 570 /// WebAssembly binary, or wasmtime may try to infer a better name for it if 571 /// not available, for example the name of the export if it's exported. 572 /// 573 /// This return value is primarily used for debugging and human-readable 574 /// purposes for things like traps. Note that the exact return value may be 575 /// tweaked over time here and isn't guaranteed to be something in 576 /// particular about a wasm module due to its primary purpose of assisting 577 /// in debugging. 578 /// 579 /// This function returns `None` when no name could be inferred. 580 pub fn func_name(&self) -> Option<&str> { 581 self.func_name.as_deref() 582 } 583 584 /// Returns the offset within the original wasm module this frame's program 585 /// counter was at. 586 /// 587 /// The offset here is the offset from the beginning of the original wasm 588 /// module to the instruction that this frame points to. 589 /// 590 /// Note that `None` may be returned if the original module was not 591 /// compiled with mapping information to yield this information. This is 592 /// controlled by the 593 /// [`Config::generate_address_map`](crate::Config::generate_address_map) 594 /// configuration option. 595 pub fn module_offset(&self) -> Option<usize> { 596 Some(self.instr?.file_offset()? as usize) 597 } 598 599 /// Returns the offset from the original wasm module's function to this 600 /// frame's program counter. 601 /// 602 /// The offset here is the offset from the beginning of the defining 603 /// function of this frame (within the wasm module) to the instruction this 604 /// frame points to. 605 /// 606 /// Note that `None` may be returned if the original module was not 607 /// compiled with mapping information to yield this information. This is 608 /// controlled by the 609 /// [`Config::generate_address_map`](crate::Config::generate_address_map) 610 /// configuration option. 611 pub fn func_offset(&self) -> Option<usize> { 612 let instr_offset = self.instr?.file_offset()?; 613 Some((instr_offset - self.func_start.file_offset()?) as usize) 614 } 615 616 /// Returns the debug symbols found, if any, for this function frame. 617 /// 618 /// When a wasm program is compiled with DWARF debug information then this 619 /// function may be populated to return symbols which contain extra debug 620 /// information about a frame including the filename and line number. If no 621 /// debug information was found or if it was malformed then this will return 622 /// an empty array. 623 pub fn symbols(&self) -> &[FrameSymbol] { 624 &self.symbols 625 } 626 } 627 628 /// Debug information for a symbol that is attached to a [`FrameInfo`]. 629 /// 630 /// When DWARF debug information is present in a wasm file then this structure 631 /// can be found on a [`FrameInfo`] and can be used to learn about filenames, 632 /// line numbers, etc, which are the origin of a function in a stack trace. 633 #[derive(Debug)] 634 pub struct FrameSymbol { 635 name: Option<String>, 636 file: Option<String>, 637 line: Option<u32>, 638 column: Option<u32>, 639 } 640 641 impl FrameSymbol { 642 /// Returns the function name associated with this symbol. 643 /// 644 /// Note that this may not be present with malformed debug information, or 645 /// the debug information may not include it. Also note that the symbol is 646 /// frequently mangled, so you might need to run some form of demangling 647 /// over it. 648 pub fn name(&self) -> Option<&str> { 649 self.name.as_deref() 650 } 651 652 /// Returns the source code filename this symbol was defined in. 653 /// 654 /// Note that this may not be present with malformed debug information, or 655 /// the debug information may not include it. 656 pub fn file(&self) -> Option<&str> { 657 self.file.as_deref() 658 } 659 660 /// Returns the 1-indexed source code line number this symbol was defined 661 /// on. 662 /// 663 /// Note that this may not be present with malformed debug information, or 664 /// the debug information may not include it. 665 pub fn line(&self) -> Option<u32> { 666 self.line 667 } 668 669 /// Returns the 1-indexed source code column number this symbol was defined 670 /// on. 671 /// 672 /// Note that this may not be present with malformed debug information, or 673 /// the debug information may not include it. 674 pub fn column(&self) -> Option<u32> { 675 self.column 676 } 677 } 678