unix: add functions PtraceGetRegSetArm64 and PtraceSetRegSetArm64
Since arm64 GNU/Linux version 2.6.34, PTRACE_GETREGS was replaced by PTRACE_GETREGSET,
in order to get or set the general purpose and floating-point register values,
PTRACE_GETREGSET/PTRACE_SETREGSET request type and a proper "NT_XXX" constant values
should be used. For the sake of not breaking the existing API, we added two functions
PtraceGetRegSetArm64 and PtraceSetRegSetArm64, they take an additional argument "addr",
and use PTRACE_GETREGSET and PTRACE_SETREGSET request types respectively.
Change-Id: I14c55733e15cea4b7d775187b1018fcb2880d6a9
Reviewed-on: https://go-review.googlesource.com/c/sys/+/204418
Run-TryBot: eric fang <eric.fang@arm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/linux/mkall.go b/unix/linux/mkall.go
index 88d9c82..d874a35 100644
--- a/unix/linux/mkall.go
+++ b/unix/linux/mkall.go
@@ -144,12 +144,16 @@
}
// ptracePairs is a list of pairs of targets that can, in some cases,
-// run each other's binaries.
-var ptracePairs = []struct{ a1, a2 string }{
- {"386", "amd64"},
- {"arm", "arm64"},
- {"mips", "mips64"},
- {"mipsle", "mips64le"},
+// run each other's binaries. 'archName' is the combined name of 'a1'
+// and 'a2', which is used in the file name. Generally we use an 'x'
+// suffix in the file name to indicate that the file works for both
+// big-endian and little-endian, here we use 'nn' to indicate that this
+// file is suitable for 32-bit and 64-bit.
+var ptracePairs = []struct{ a1, a2, archName string }{
+ {"386", "amd64", "x86"},
+ {"arm", "arm64", "armnn"},
+ {"mips", "mips64", "mipsnn"},
+ {"mipsle", "mips64le", "mipsnnle"},
}
func main() {
@@ -186,7 +190,7 @@
fmt.Printf("----- GENERATING ptrace pairs -----\n")
ok := true
for _, p := range ptracePairs {
- if err := generatePtracePair(p.a1, p.a2); err != nil {
+ if err := generatePtracePair(p.a1, p.a2, p.archName); err != nil {
fmt.Printf("%v\n***** FAILURE: %s/%s *****\n\n", err, p.a1, p.a2)
ok = false
}
@@ -545,8 +549,9 @@
// type for each one. It writes a new file defining the types
// PtraceRegsArch1 and PtraceRegsArch2 and the corresponding functions
// Ptrace{Get,Set}Regs{arch1,arch2}. This permits debugging the other
-// binary on a native system.
-func generatePtracePair(arch1, arch2 string) error {
+// binary on a native system. 'archName' is the combined name of 'arch1'
+// and 'arch2', which is used in the file name.
+func generatePtracePair(arch1, arch2, archName string) error {
def1, err := ptraceDef(arch1)
if err != nil {
return err
@@ -555,12 +560,12 @@
if err != nil {
return err
}
- f, err := os.Create(fmt.Sprintf("zptrace%s_linux.go", arch1))
+ f, err := os.Create(fmt.Sprintf("zptrace_%s_linux.go", archName))
if err != nil {
return err
}
buf := bufio.NewWriter(f)
- fmt.Fprintf(buf, "// Code generated by linux/mkall.go generatePtracePair(%s, %s). DO NOT EDIT.\n", arch1, arch2)
+ fmt.Fprintf(buf, "// Code generated by linux/mkall.go generatePtracePair(%q, %q). DO NOT EDIT.\n", arch1, arch2)
fmt.Fprintf(buf, "\n")
fmt.Fprintf(buf, "// +build linux\n")
fmt.Fprintf(buf, "// +build %s %s\n", arch1, arch2)
@@ -572,6 +577,10 @@
writeOnePtrace(buf, arch1, def1)
fmt.Fprintf(buf, "\n")
writeOnePtrace(buf, arch2, def2)
+ if arch2 == "arm64" {
+ fmt.Fprintf(buf, "\n")
+ writeOnePtraceRegSet(buf, arch2)
+ }
if err := buf.Flush(); err != nil {
return err
}
@@ -617,6 +626,23 @@
fmt.Fprintf(w, "}\n")
}
+// writeOnePtraceRegSet writes out the ptrace definitions of PTRACE_GETREGSET and
+// PTRACE_SETREGSET request type.
+func writeOnePtraceRegSet(w io.Writer, arch string) {
+ uarch := string(unicode.ToUpper(rune(arch[0]))) + arch[1:]
+ fmt.Fprintf(w, "// PtraceGetRegSet%s fetches the registers used by %s binaries.\n", uarch, arch)
+ fmt.Fprintf(w, "func PtraceGetRegSet%s(pid, addr int, regsout *PtraceRegs%s) error {\n", uarch, uarch)
+ fmt.Fprintf(w, "\tiovec := Iovec{(*byte)(unsafe.Pointer(regsout)), uint64(unsafe.Sizeof(*regsout))}\n")
+ fmt.Fprintf(w, "\treturn ptrace(PTRACE_GETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec)))\n")
+ fmt.Fprintf(w, "}\n")
+ fmt.Fprintf(w, "\n")
+ fmt.Fprintf(w, "// PtraceSetRegSet%s sets the registers used by %s binaries.\n", uarch, arch)
+ fmt.Fprintf(w, "func PtraceSetRegSet%s(pid, addr int, regs *PtraceRegs%s) error {\n", uarch, uarch)
+ fmt.Fprintf(w, "\tiovec := Iovec{(*byte)(unsafe.Pointer(regs)), uint64(unsafe.Sizeof(*regs))}\n")
+ fmt.Fprintf(w, "\treturn ptrace(PTRACE_SETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec)))\n")
+ fmt.Fprintf(w, "}\n")
+}
+
// cCode is compiled for the target architecture, and the resulting data section is carved for
// the statically initialized bit masks.
const cCode = `
diff --git a/unix/zptracearm_linux.go b/unix/zptrace_armnn_linux.go
similarity index 61%
rename from unix/zptracearm_linux.go
rename to unix/zptrace_armnn_linux.go
index faf23bb..8bcde84 100644
--- a/unix/zptracearm_linux.go
+++ b/unix/zptrace_armnn_linux.go
@@ -1,4 +1,4 @@
-// Code generated by linux/mkall.go generatePtracePair(arm, arm64). DO NOT EDIT.
+// Code generated by linux/mkall.go generatePtracePair("arm", "arm64"). DO NOT EDIT.
// +build linux
// +build arm arm64
@@ -39,3 +39,15 @@
func PtraceSetRegsArm64(pid int, regs *PtraceRegsArm64) error {
return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
}
+
+// PtraceGetRegSetArm64 fetches the registers used by arm64 binaries.
+func PtraceGetRegSetArm64(pid, addr int, regsout *PtraceRegsArm64) error {
+ iovec := Iovec{(*byte)(unsafe.Pointer(regsout)), uint64(unsafe.Sizeof(*regsout))}
+ return ptrace(PTRACE_GETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec)))
+}
+
+// PtraceSetRegSetArm64 sets the registers used by arm64 binaries.
+func PtraceSetRegSetArm64(pid, addr int, regs *PtraceRegsArm64) error {
+ iovec := Iovec{(*byte)(unsafe.Pointer(regs)), uint64(unsafe.Sizeof(*regs))}
+ return ptrace(PTRACE_SETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec)))
+}
diff --git a/unix/zptracemips_linux.go b/unix/zptrace_mipsnn_linux.go
similarity index 93%
rename from unix/zptracemips_linux.go
rename to unix/zptrace_mipsnn_linux.go
index c431131..24b841e 100644
--- a/unix/zptracemips_linux.go
+++ b/unix/zptrace_mipsnn_linux.go
@@ -1,4 +1,4 @@
-// Code generated by linux/mkall.go generatePtracePair(mips, mips64). DO NOT EDIT.
+// Code generated by linux/mkall.go generatePtracePair("mips", "mips64"). DO NOT EDIT.
// +build linux
// +build mips mips64
diff --git a/unix/zptracemipsle_linux.go b/unix/zptrace_mipsnnle_linux.go
similarity index 93%
rename from unix/zptracemipsle_linux.go
rename to unix/zptrace_mipsnnle_linux.go
index dc3d6d3..47b0489 100644
--- a/unix/zptracemipsle_linux.go
+++ b/unix/zptrace_mipsnnle_linux.go
@@ -1,4 +1,4 @@
-// Code generated by linux/mkall.go generatePtracePair(mipsle, mips64le). DO NOT EDIT.
+// Code generated by linux/mkall.go generatePtracePair("mipsle", "mips64le"). DO NOT EDIT.
// +build linux
// +build mipsle mips64le
diff --git a/unix/zptrace386_linux.go b/unix/zptrace_x86_linux.go
similarity index 95%
rename from unix/zptrace386_linux.go
rename to unix/zptrace_x86_linux.go
index 2d21c49..ea5d9cb 100644
--- a/unix/zptrace386_linux.go
+++ b/unix/zptrace_x86_linux.go
@@ -1,4 +1,4 @@
-// Code generated by linux/mkall.go generatePtracePair(386, amd64). DO NOT EDIT.
+// Code generated by linux/mkall.go generatePtracePair("386", "amd64"). DO NOT EDIT.
// +build linux
// +build 386 amd64