aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>2024-01-24 19:02:32 +0100
committerKeith Randall <khr@golang.org>2024-05-11 20:38:24 +0000
commit7f9edb42259114020c67eb51643e43cf5a2cf9a7 (patch)
tree3cca83f699264cbb26aab9bc7496ec2ea469d4b7
parent74a49188d300076d6fc6747ea7678d327c5645a1 (diff)
downloadgo-7f9edb42259114020c67eb51643e43cf5a2cf9a7.tar.gz
go-7f9edb42259114020c67eb51643e43cf5a2cf9a7.zip
runtime: add runtime.debugPinnerV1
Adds runtime.debugPinnerV1 which returns a runtime.Pinner object that pins itself. This is intended to be used by debuggers in conjunction with runtime.debugCall to keep heap memory reachable even if it isn't referenced from anywhere else. Change-Id: I508ee6a7b103e68df83c96f2e04a0599200300dc Reviewed-on: https://go-review.googlesource.com/c/go/+/558276 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Austin Clements <austin@google.com>
-rw-r--r--src/runtime/asm_amd64.s3
-rw-r--r--src/runtime/asm_arm64.s3
-rw-r--r--src/runtime/asm_ppc64x.s3
-rw-r--r--src/runtime/debug.go19
4 files changed, 25 insertions, 3 deletions
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index cb21629a84..cdf9874a7f 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -371,8 +371,9 @@ bad_cpu: // show that the program requires a certain microarchitecture level.
CALL runtime·abort(SB)
RET
- // Prevent dead-code elimination of debugCallV2, which is
+ // Prevent dead-code elimination of debugCallV2 and debugPinnerV1, which are
// intended to be called by debuggers.
+ MOVQ $runtime·debugPinnerV1<ABIInternal>(SB), AX
MOVQ $runtime·debugCallV2<ABIInternal>(SB), AX
RET
diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s
index 6d77b08a1b..64a1880589 100644
--- a/src/runtime/asm_arm64.s
+++ b/src/runtime/asm_arm64.s
@@ -96,8 +96,9 @@ nocgo:
// start this M
BL runtime·mstart(SB)
- // Prevent dead-code elimination of debugCallV2, which is
+ // Prevent dead-code elimination of debugCallV2 and debugPinnerV1, which are
// intended to be called by debuggers.
+ MOVD $runtime·debugPinnerV1<ABIInternal>(SB), R0
MOVD $runtime·debugCallV2<ABIInternal>(SB), R0
MOVD $0, R0
diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s
index 97c2a370bd..98002bccf6 100644
--- a/src/runtime/asm_ppc64x.s
+++ b/src/runtime/asm_ppc64x.s
@@ -98,9 +98,10 @@ nocgo:
// start this M
BL runtime·mstart(SB)
- // Prevent dead-code elimination of debugCallV2, which is
+ // Prevent dead-code elimination of debugCallV2 and debugPinnerV1, which are
// intended to be called by debuggers.
#ifdef GOARCH_ppc64le
+ MOVD $runtime·debugPinnerV1<ABIInternal>(SB), R31
MOVD $runtime·debugCallV2<ABIInternal>(SB), R31
#endif
MOVD R0, 0(R0)
diff --git a/src/runtime/debug.go b/src/runtime/debug.go
index 184e4127c3..c477e2b9f6 100644
--- a/src/runtime/debug.go
+++ b/src/runtime/debug.go
@@ -124,3 +124,22 @@ func mayMoreStackMove() {
gp.stackguard0 = stackForceMove
}
}
+
+// debugPinnerKeepUnpin is used to make runtime.(*Pinner).Unpin reachable.
+var debugPinnerKeepUnpin bool = false
+
+// debugPinnerV1 returns a new Pinner that pins itself. This function can be
+// used by debuggers to easily obtain a Pinner that will not be garbage
+// collected (or moved in memory) even if no references to it exist in the
+// target program. This pinner in turn can be used to extend this property
+// to other objects, which debuggers can use to simplify the evaluation of
+// expressions involving multiple call injections.
+func debugPinnerV1() *Pinner {
+ p := new(Pinner)
+ p.Pin(unsafe.Pointer(p))
+ if debugPinnerKeepUnpin {
+ // Make Unpin reachable.
+ p.Unpin()
+ }
+ return p
+}