cmd/stacks: show command to reproduce, disassemble the exe

Change-Id: I4afd6368181aeb41a4a08526bb1d8bb1fe69e7c7
Reviewed-on: https://go-review.googlesource.com/c/telemetry/+/708115
Auto-Submit: Alan Donovan <adonovan@google.com>
Commit-Queue: Alan Donovan <adonovan@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/cmd/stacks/stacks.go b/cmd/stacks/stacks.go
index b2f261c..bc70189 100644
--- a/cmd/stacks/stacks.go
+++ b/cmd/stacks/stacks.go
@@ -320,7 +320,7 @@
 		info.Program, info.ProgramVersion,
 		info.GoVersion, info.GOOS, info.GOARCH)
 	if info.GoplsClient != "" {
-		s += " " + info.GoplsClient
+		s += " gopls.client=" + info.GoplsClient
 	}
 	return s
 }
@@ -830,7 +830,7 @@
 	}
 
 	// Parse the stack and get the symbol names out.
-	for _, frame := range strings.Split(stack, "\n") {
+	for frame := range strings.SplitSeq(stack, "\n") {
 		if url := frameURL(pclntab, info, frame); url != "" {
 			fmt.Fprintf(body, "- [`%s`](%s)\n", frame, url)
 		} else {
@@ -845,6 +845,19 @@
 		fmt.Fprintf(body, "%s (%d)\n", info, count)
 	}
 	fmt.Fprintf(body, "```\n\n")
+
+	// Give hints for disassembling the right executable.
+	// Beware that go install behaves differently for cross-compiles;
+	// the command below was chosen to work for simple and cross builds.
+	// TODO(adonovan): simplify when go.dev/issue/44469 is resolved.
+	fmt.Fprintf(body, "Use this command to reproduce the executable:\n")
+	fmt.Fprintf(body, "`(HOME=$(mktemp -d); GOOS=%s GOARCH=%s GOTOOLCHAIN=%s go install %s@%s && find $HOME/go/bin -type f)`\n",
+		info.GOOS,
+		info.GOARCH,
+		info.GoVersion,
+		info.Program, info.ProgramVersion)
+
+	fmt.Fprintf(body, "To disassemble: `go tool objdump exe | less`\n\n")
 }
 
 // frameURL returns the CodeSearch URL for the stack frame, if known.