Skip to main content

wasmtime/runtime/
trap.rs

1#[cfg(feature = "coredump")]
2use super::coredump::WasmCoreDump;
3#[cfg(feature = "gc")]
4use crate::ThrownException;
5use crate::prelude::*;
6use crate::store::StoreOpaque;
7use crate::{AsContext, Module};
8use core::fmt;
9use core::num::NonZeroUsize;
10use 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/// ```
76pub use wasmtime_environ::Trap;
77
78#[cold] // traps are exceptional, this helps move handling off the main path
79pub(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)]
203pub 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
211impl 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
397impl 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)]
469pub 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
478impl 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)]
634pub struct FrameSymbol {
635    name: Option<String>,
636    file: Option<String>,
637    line: Option<u32>,
638    column: Option<u32>,
639}
640
641impl 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}