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>
This commit is contained in:
erifan01
2019-11-21 17:35:28 +08:00
committed by Ian Lance Taylor
parent ce4227a45e
commit bc7efcf3b8
5 changed files with 53 additions and 15 deletions

View File

@@ -144,12 +144,16 @@ var targets = []target{
}
// 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 @@ func main() {
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 @@ func (t *target) mksyscallFlags() (flags []string) {
// 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 @@ func generatePtracePair(arch1, arch2 string) error {
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 @@ func generatePtracePair(arch1, arch2 string) error {
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 @@ func writeOnePtrace(w io.Writer, arch, def string) {
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 = `

View File

@@ -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 PtraceGetRegsArm64(pid int, regsout *PtraceRegsArm64) error {
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)))
}

View File

@@ -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

View File

@@ -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

View File

@@ -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