wasm: include DWARF information in Wasm builds
This change adds DWARF debug information to Wasm binaries, which was
not present previously.
WIP: Some debug information is written correctly, but all locations are set to 0,
so debugging does not yet work in Chrome.
I opened this change so that other people could look into this.
See the discussion on GitHub for more details on this.
Fixes #33503
Change-Id: I8cc03eb398da39dd19c41b9ce2bb803ed9bfb40c
diff --git a/src/cmd/link/internal/ld/asmb.go b/src/cmd/link/internal/ld/asmb.go
index fda0439..d91488d 100644
--- a/src/cmd/link/internal/ld/asmb.go
+++ b/src/cmd/link/internal/ld/asmb.go
@@ -73,6 +73,14 @@
wg.Wait()
}
+func GetDwarfSections(ctxt *Link, ldr *loader.Loader) [][]loader.Sym {
+ var sects [][]loader.Sym
+ for _, info := range dwarfp {
+ sects = append(sects, info.syms)
+ }
+ return sects
+}
+
// Assembling the binary is broken into two steps:
// - writing out the code/data/dwarf Segments
// - writing out the architecture specific pieces.
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 2ab9a55..3fd8f82 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -1658,7 +1658,7 @@
if *FlagS && ctxt.HeadType != objabi.Hdarwin {
return false
}
- if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs {
+ if ctxt.HeadType == objabi.Hplan9 {
return false
}
@@ -1953,7 +1953,7 @@
// dwarfGenerateDebugSyms constructs debug_line, debug_frame, and
// debug_loc. It also writes out the debug_info section using symbols
-// generated in dwarfGenerateDebugInfo2.
+// generated in dwarfGenerateDebugInfo.
func dwarfGenerateDebugSyms(ctxt *Link) {
if !dwarfEnabled(ctxt) {
return
diff --git a/src/cmd/link/internal/wasm/asm.go b/src/cmd/link/internal/wasm/asm.go
index 31851fb..35c61c3 100644
--- a/src/cmd/link/internal/wasm/asm.go
+++ b/src/cmd/link/internal/wasm/asm.go
@@ -6,11 +6,14 @@
import (
"bytes"
+ "cmd/internal/dwarf"
"cmd/internal/objabi"
"cmd/link/internal/ld"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
+ "fmt"
"io"
+ "log"
"regexp"
)
@@ -216,6 +219,7 @@
writeCodeSec(ctxt, fns)
writeDataSec(ctxt)
writeProducerSec(ctxt)
+ writeDwarfSec(ctxt, ldr)
if !*ld.FlagS {
writeNameSec(ctxt, len(hostImports), fns)
}
@@ -519,6 +523,39 @@
writeSecSize(ctxt, sizeOffset)
}
+func writeDwarfSec(ctxt *ld.Link, ldr *loader.Loader) {
+ dwarfp := ld.GetDwarfSections(ctxt, ldr)
+ for _, sec := range dwarfp {
+ if len(sec) == 0 {
+ continue
+ }
+ secSym := sec[0]
+ var dataSyms []loader.Sym
+ if len(sec) > 1 {
+ dataSyms = sec[1:]
+ }
+ secName := ldr.SymName(secSym)
+ secOffset := writeSecHeader(ctxt, sectionCustom)
+ writeName(ctxt.Out, secName)
+
+ if secName == ".debug_abbrev" {
+ // why is debug_abbrev so special?
+ abbrev := dwarf.GetAbbrev()
+ if _, err := ctxt.Out.Write(abbrev); err != nil {
+ fmt.Println(err)
+ }
+ } else {
+ for _, dataSym := range dataSyms {
+ data := ldr.Data(dataSym)
+ if _, err := ctxt.Out.Write(data); err != nil {
+ log.Println(err)
+ }
+ }
+ }
+ writeSecSize(ctxt, secOffset)
+ }
+}
+
var nameRegexp = regexp.MustCompile(`[^\w\.]`)
// writeNameSec writes an optional section that assigns names to the functions declared by the "func" section.