have correct funcName pass to the funcptrtest function
Is function descriptor f a valid function?
|
// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName |
"unsafe"
)
//go:noescape
func initZosLibVec()
//go:noescape
func GetZosLibVec() uintptr
func init() {
initZosLibVec()
r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACE\x00"))[0])))
if r0 != 0 {
n, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0)
ZosTraceLevel = int(n)
r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACEFD\x00"))[0])))
if r0 != 0 {
fd, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0)
f := os.NewFile(fd, "zostracefile")
if f != nil {
ZosTracefile = f
}
}
}
}
//go:noescape
func CallLeFuncWithErr(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno)
//go:noescape
func CallLeFuncWithPtrReturn(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno)
// -------------------------------
// pointer validity test
// good pointer returns 0
// bad pointer returns 1
//
//go:nosplit
func ptrtest(uintptr) uint64
// Load memory at ptr location with error handling if the location is invalid
//
//go:noescape
func safeload(ptr uintptr) (value uintptr, error uintptr)
const (
entrypointLocationOffset = 8 // From function descriptor
xplinkEyecatcher = 0x00c300c500c500f1 // ".C.E.E.1"
eyecatcherOffset = 16 // From function entrypoint (negative)
ppa1LocationOffset = 8 // From function entrypoint (negative)
nameLenOffset = 0x14 // From PPA1 start
nameOffset = 0x16 // From PPA1 start
)
func getPpaOffset(funcptr uintptr) int64 {
entrypoint, err := safeload(funcptr + entrypointLocationOffset)
if err != 0 {
return -1
}
// XPLink functions have ".C.E.E.1" as the first 8 bytes (EBCDIC)
val, err := safeload(entrypoint - eyecatcherOffset)
if err != 0 {
return -1
}
if val != xplinkEyecatcher {
return -1
}
ppaoff, err := safeload(entrypoint - ppa1LocationOffset)
if err != 0 {
return -1
}
ppaoff >>= 32
return int64(ppaoff)
}
//-------------------------------
// function descriptor pointer validity test
// good pointer returns 0
// bad pointer returns 1
// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName
// have correct funcName pass to the funcptrtest function
func funcptrtest(funcptr uintptr, funcName string) uint64 {
entrypoint, err := safeload(funcptr + entrypointLocationOffset)
if err != 0 {
return 1
}
ppaoff := getPpaOffset(funcptr)
if ppaoff == -1 {
return 1
}
// PPA1 offset value is from the start of the entire function block, not the entrypoint
ppa1 := (entrypoint - eyecatcherOffset) + uintptr(ppaoff)
nameLen, err := safeload(ppa1 + nameLenOffset)
if err != 0 {
return 1
}
nameLen >>= 48
if nameLen > 128 {
return 1
}
// no function name input to argument end here
if funcName == "" {
return 0
}
var funcname [128]byte
for i := 0; i < int(nameLen); i += 8 {
v, err := safeload(ppa1 + nameOffset + uintptr(i))
if err != 0 {
return 1
}
funcname[i] = byte(v >> 56)
funcname[i+1] = byte(v >> 48)
funcname[i+2] = byte(v >> 40)
funcname[i+3] = byte(v >> 32)
funcname[i+4] = byte(v >> 24)
funcname[i+5] = byte(v >> 16)
funcname[i+6] = byte(v >> 8)
funcname[i+7] = byte(v)
}
runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l
[]uintptr{uintptr(unsafe.Pointer(&funcname[0])), nameLen})
name := string(funcname[:nameLen])
if name != funcName {
return 1
}
return 0
}
// For detection of capabilities on a system.
// Is function descriptor f a valid function?
func isValidLeFunc(f uintptr) error {
ret := funcptrtest(f, "")
if ret != 0 {
return fmt.Errorf("Bad pointer, not an LE function ")
}
return nil
}
// Retrieve function name from descriptor
func getLeFuncName(f uintptr) (string, error) {
// assume it has been checked, only check ppa1 validity here
entry := ((*[2]uintptr)(unsafe.Pointer(f)))[1]
preamp := ((*[4]uint32)(unsafe.Pointer(entry - eyecatcherOffset)))
offsetPpa1 := preamp[2]
if offsetPpa1 > 0x0ffff {
return "", fmt.Errorf("PPA1 offset seems too big 0x%x\n", offsetPpa1)
}
ppa1 := uintptr(unsafe.Pointer(preamp)) + uintptr(offsetPpa1)
res := ptrtest(ppa1)
if res != 0 {
return "", fmt.Errorf("PPA1 address not valid")
}
size := *(*uint16)(unsafe.Pointer(ppa1 + nameLenOffset))
if size > 128 {
return "", fmt.Errorf("Function name seems too long, length=%d\n", size)
}
var name [128]byte
funcname := (*[128]byte)(unsafe.Pointer(ppa1 + nameOffset))
copy(name[0:size], funcname[0:size])
runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l
[]uintptr{uintptr(unsafe.Pointer(&name[0])), uintptr(size)})
return string(name[:size]), nil
}
// Check z/OS version
func zosLeVersion() (version, release uint32) {
p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32
p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88)))
p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8)))
p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984)))
vrm := *(*uint32)(unsafe.Pointer(p1 + 80))
version = (vrm & 0x00ff0000) >> 16
release = (vrm & 0x0000ff00) >> 8
return
}
// returns a zos C FILE * for stdio fd 0, 1, 2
func ZosStdioFilep(fd int32) uintptr {
return uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(uint64(*(*uint32)(unsafe.Pointer(uintptr(1208)))) + 80))) + uint64((fd+2)<<3))))))))
}
func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
stat.Dev = uint64(statLE.Dev)
have correct funcName pass to the funcptrtest function
Is function descriptor f a valid function?
HAOS/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
Line 113 in 328bbe3