Enables debug info (a.k.a. DWARF) by default (#924)
This makes DWARF enabled by default, with an opt-out flag. This didn't need to be experimental as the feature was requested for a long time and there's no API impact to using it. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -12,12 +12,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tetratelabs/wazero"
|
"github.com/tetratelabs/wazero"
|
||||||
"github.com/tetratelabs/wazero/experimental"
|
|
||||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||||
"github.com/tetratelabs/wazero/sys"
|
"github.com/tetratelabs/wazero/sys"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ctx = experimental.WithDWARFBasedStackTrace(context.Background())
|
var ctx = context.Background()
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
doMain(os.Stdout, os.Stderr, os.Exit)
|
doMain(os.Stdout, os.Stderr, os.Exit)
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tetratelabs/wazero/experimental"
|
|
||||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -158,7 +157,3 @@ func runMain(t *testing.T, args []string) (int, string, string) {
|
|||||||
|
|
||||||
return exitCode, stdOut.String(), stdErr.String()
|
return exitCode, stdOut.String(), stdErr.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContext(t *testing.T) {
|
|
||||||
require.True(t, experimental.DWARFBasedStackTraceEnabled(ctx))
|
|
||||||
}
|
|
||||||
|
|||||||
44
config.go
44
config.go
@@ -66,6 +66,41 @@ type RuntimeConfig interface {
|
|||||||
//
|
//
|
||||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
|
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
|
||||||
WithMemoryCapacityFromMax(memoryCapacityFromMax bool) RuntimeConfig
|
WithMemoryCapacityFromMax(memoryCapacityFromMax bool) RuntimeConfig
|
||||||
|
|
||||||
|
// WithDebugInfoEnabled toggles DWARF based stack traces in the face of
|
||||||
|
// runtime errors. Defaults to true.
|
||||||
|
//
|
||||||
|
// Those who wish to disable this, can like so:
|
||||||
|
//
|
||||||
|
// r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithDebugInfoEnabled(false)
|
||||||
|
//
|
||||||
|
// When disabled, a stack trace message looks like:
|
||||||
|
//
|
||||||
|
// wasm stack trace:
|
||||||
|
// .runtime._panic(i32)
|
||||||
|
// .myFunc()
|
||||||
|
// .main.main()
|
||||||
|
// .runtime.run()
|
||||||
|
// ._start()
|
||||||
|
//
|
||||||
|
// When enabled, the stack trace includes source code information:
|
||||||
|
//
|
||||||
|
// wasm stack trace:
|
||||||
|
// .runtime._panic(i32)
|
||||||
|
// 0x16e2: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_tinygowasm.go:73:6
|
||||||
|
// .myFunc()
|
||||||
|
// 0x190b: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:19:7
|
||||||
|
// .main.main()
|
||||||
|
// 0x18ed: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:4:3
|
||||||
|
// .runtime.run()
|
||||||
|
// 0x18cc: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/scheduler_none.go:26:10
|
||||||
|
// ._start()
|
||||||
|
// 0x18b6: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_wasm_wasi.go:22:5
|
||||||
|
//
|
||||||
|
// Note: This only takes into effect when the original Wasm binary has the
|
||||||
|
// DWARF "custom sections" that are often stripped, depending on
|
||||||
|
// optimization flags passed to the compiler.
|
||||||
|
WithDebugInfoEnabled(bool) RuntimeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRuntimeConfig returns a RuntimeConfig using the compiler if it is supported in this environment,
|
// NewRuntimeConfig returns a RuntimeConfig using the compiler if it is supported in this environment,
|
||||||
@@ -79,6 +114,7 @@ type runtimeConfig struct {
|
|||||||
memoryLimitPages uint32
|
memoryLimitPages uint32
|
||||||
memoryCapacityFromMax bool
|
memoryCapacityFromMax bool
|
||||||
isInterpreter bool
|
isInterpreter bool
|
||||||
|
dwarfDisabled bool // negative as defaults to enabled
|
||||||
newEngine func(context.Context, api.CoreFeatures) wasm.Engine
|
newEngine func(context.Context, api.CoreFeatures) wasm.Engine
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +123,7 @@ var engineLessConfig = &runtimeConfig{
|
|||||||
enabledFeatures: api.CoreFeaturesV2,
|
enabledFeatures: api.CoreFeaturesV2,
|
||||||
memoryLimitPages: wasm.MemoryLimitPages,
|
memoryLimitPages: wasm.MemoryLimitPages,
|
||||||
memoryCapacityFromMax: false,
|
memoryCapacityFromMax: false,
|
||||||
|
dwarfDisabled: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRuntimeConfigCompiler compiles WebAssembly modules into
|
// NewRuntimeConfigCompiler compiles WebAssembly modules into
|
||||||
@@ -148,6 +185,13 @@ func (c *runtimeConfig) WithMemoryCapacityFromMax(memoryCapacityFromMax bool) Ru
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithDebugInfoEnabled implements RuntimeConfig.WithDebugInfoEnabled
|
||||||
|
func (c *runtimeConfig) WithDebugInfoEnabled(dwarfEnabled bool) RuntimeConfig {
|
||||||
|
ret := c.clone()
|
||||||
|
ret.dwarfDisabled = !dwarfEnabled
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// CompiledModule is a WebAssembly module ready to be instantiated (Runtime.InstantiateModule) as an api.Module.
|
// CompiledModule is a WebAssembly module ready to be instantiated (Runtime.InstantiateModule) as an api.Module.
|
||||||
//
|
//
|
||||||
// In WebAssembly terminology, this is a decoded, validated, and possibly also compiled module. wazero avoids using
|
// In WebAssembly terminology, this is a decoded, validated, and possibly also compiled module. wazero avoids using
|
||||||
|
|||||||
@@ -50,6 +50,15 @@ func TestRuntimeConfig(t *testing.T) {
|
|||||||
memoryCapacityFromMax: true,
|
memoryCapacityFromMax: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "WithDebugInfoEnabled",
|
||||||
|
with: func(c RuntimeConfig) RuntimeConfig {
|
||||||
|
return c.WithDebugInfoEnabled(false)
|
||||||
|
},
|
||||||
|
expected: &runtimeConfig{
|
||||||
|
dwarfDisabled: true, // dwarf is a more technical name and ok here.
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package experimental_test
|
package wazero_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -8,25 +8,24 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tetratelabs/wazero"
|
"github.com/tetratelabs/wazero"
|
||||||
"github.com/tetratelabs/wazero/experimental"
|
|
||||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||||
"github.com/tetratelabs/wazero/internal/platform"
|
"github.com/tetratelabs/wazero/internal/platform"
|
||||||
"github.com/tetratelabs/wazero/internal/testing/dwarftestdata"
|
"github.com/tetratelabs/wazero/internal/testing/dwarftestdata"
|
||||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWithDWARFBasedStackTrace(t *testing.T) {
|
func TestWithDebugInfo(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
require.False(t, experimental.DWARFBasedStackTraceEnabled(ctx))
|
|
||||||
ctx = experimental.WithDWARFBasedStackTrace(ctx)
|
|
||||||
require.True(t, experimental.DWARFBasedStackTraceEnabled(ctx))
|
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
r wazero.Runtime
|
r wazero.Runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []testCase{{name: "interpreter", r: wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter())}}
|
tests := []testCase{{
|
||||||
|
name: "interpreter",
|
||||||
|
r: wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter()),
|
||||||
|
}}
|
||||||
|
|
||||||
if platform.CompilerSupported() {
|
if platform.CompilerSupported() {
|
||||||
tests = append(tests, testCase{
|
tests = append(tests, testCase{
|
||||||
@@ -167,8 +166,7 @@ wasm stack trace:
|
|||||||
compiled, err := r.CompileModule(ctx, lang.bin)
|
compiled, err := r.CompileModule(ctx, lang.bin)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Use context.Background to ensure that DWARF is a compile-time option.
|
_, err = r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig())
|
||||||
_, err = r.InstantiateModule(context.Background(), compiled, wazero.NewModuleConfig())
|
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package experimental
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
type enableDWARFBasedStackTraceKey struct{}
|
|
||||||
|
|
||||||
// WithDWARFBasedStackTrace enables the DWARF based stack traces in the face of runtime errors.
|
|
||||||
// This only takes into effect when the original Wasm binary has the DWARF "custom sections"
|
|
||||||
// that are often stripped depending on the optimization options of the compilers.
|
|
||||||
//
|
|
||||||
// For example, when this is not enabled, the stack trace message looks like:
|
|
||||||
//
|
|
||||||
// wasm stack trace:
|
|
||||||
// .runtime._panic(i32)
|
|
||||||
// .myFunc()
|
|
||||||
// .main.main()
|
|
||||||
// .runtime.run()
|
|
||||||
// ._start()
|
|
||||||
//
|
|
||||||
// and when it is enabled:
|
|
||||||
//
|
|
||||||
// wasm stack trace:
|
|
||||||
// .runtime._panic(i32)
|
|
||||||
// 0x16e2: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_tinygowasm.go:73:6
|
|
||||||
// .myFunc()
|
|
||||||
// 0x190b: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:19:7
|
|
||||||
// .main.main()
|
|
||||||
// 0x18ed: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:4:3
|
|
||||||
// .runtime.run()
|
|
||||||
// 0x18cc: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/scheduler_none.go:26:10
|
|
||||||
// ._start()
|
|
||||||
// 0x18b6: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_wasm_wasi.go:22:5
|
|
||||||
//
|
|
||||||
// which contains the source code information.
|
|
||||||
//
|
|
||||||
// See https://github.com/tetratelabs/wazero/pull/881 for more context.
|
|
||||||
func WithDWARFBasedStackTrace(ctx context.Context) context.Context {
|
|
||||||
return context.WithValue(ctx, enableDWARFBasedStackTraceKey{}, struct{}{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// DWARFBasedStackTraceEnabled returns true if the given context has the option enabling the DWARF
|
|
||||||
// based stack trace, and false otherwise.
|
|
||||||
func DWARFBasedStackTraceEnabled(ctx context.Context) bool {
|
|
||||||
return ctx.Value(enableDWARFBasedStackTraceKey{}) != nil
|
|
||||||
}
|
|
||||||
@@ -138,6 +138,7 @@ func NewRuntimeWithConfig(ctx context.Context, rConfig RuntimeConfig) Runtime {
|
|||||||
memoryLimitPages: config.memoryLimitPages,
|
memoryLimitPages: config.memoryLimitPages,
|
||||||
memoryCapacityFromMax: config.memoryCapacityFromMax,
|
memoryCapacityFromMax: config.memoryCapacityFromMax,
|
||||||
isInterpreter: config.isInterpreter,
|
isInterpreter: config.isInterpreter,
|
||||||
|
dwarfDisabled: config.dwarfDisabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +150,7 @@ type runtime struct {
|
|||||||
memoryLimitPages uint32
|
memoryLimitPages uint32
|
||||||
memoryCapacityFromMax bool
|
memoryCapacityFromMax bool
|
||||||
isInterpreter bool
|
isInterpreter bool
|
||||||
|
dwarfDisabled bool
|
||||||
compiledModules []*compiledModule
|
compiledModules []*compiledModule
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,9 +174,8 @@ func (r *runtime) CompileModule(ctx context.Context, binary []byte) (CompiledMod
|
|||||||
return nil, errors.New("invalid binary")
|
return nil, errors.New("invalid binary")
|
||||||
}
|
}
|
||||||
|
|
||||||
dwarfEnabled := experimentalapi.DWARFBasedStackTraceEnabled(ctx)
|
|
||||||
internal, err := binaryformat.DecodeModule(binary, r.enabledFeatures,
|
internal, err := binaryformat.DecodeModule(binary, r.enabledFeatures,
|
||||||
r.memoryLimitPages, r.memoryCapacityFromMax, dwarfEnabled, false)
|
r.memoryLimitPages, r.memoryCapacityFromMax, !r.dwarfDisabled, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if err = internal.Validate(r.enabledFeatures); err != nil {
|
} else if err = internal.Validate(r.enabledFeatures); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user