Add init debugging support

This adds Delve into the initramfs and a conditional hook which attaches Delve to our init
after the network is up. This allows for breakpoint-debugging the init itself, at least after the
very early node bringup.

Test Plan:
`bazel run -c dbg //:launch`, then use IDEA's Go Remote target to connect to localhost:2345
and set a breakpoint.

Bug: T786

X-Origin-Diff: phab/D581
GitOrigin-RevId: f6b32e7b7f4d36c8492df3e11ee97588817dbd8e
diff --git a/core/cmd/init/debug_enabled.go b/core/cmd/init/debug_enabled.go
new file mode 100644
index 0000000..1c2af00
--- /dev/null
+++ b/core/cmd/init/debug_enabled.go
@@ -0,0 +1,42 @@
+// Copyright 2020 The Monogon Project Authors.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"context"
+	"fmt"
+	"os/exec"
+
+	"git.monogon.dev/source/nexantic.git/core/internal/common"
+	"git.monogon.dev/source/nexantic.git/core/internal/network"
+)
+
+// initializeDebugger attaches Delve to ourselves and exposes it on common.DebuggerPort
+// This is coupled to compilation_mode=dbg because otherwise Delve doesn't have the necessary DWARF debug info
+func initializeDebugger(networkSvc *network.Service) {
+	go func() {
+		// This is intentionally delayed until network becomes available since Delve for some reason connects to itself
+		// and in early-boot no network interface is available to do that through. Also external access isn't possible
+		// early on anyways.
+		networkSvc.GetIP(context.Background(), true)
+		dlvCmd := exec.Command("/dlv", "--headless=true", fmt.Sprintf("--listen=:%v", common.DebuggerPort),
+			"--accept-multiclient", "--only-same-user=false", "attach", "--continue", "1", "/init")
+		if err := dlvCmd.Start(); err != nil {
+			panic(err)
+		}
+	}()
+}