1// Copyright 2023 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package pprof 6 7import ( 8 "os" 9 "unsafe" 10) 11 12func isExecutable(protection int32) bool { 13 return (protection&_VM_PROT_EXECUTE) != 0 && (protection&_VM_PROT_READ) != 0 14} 15 16// machVMInfo uses the mach_vm_region region system call to add mapping entries 17// for the text region of the running process. 18func machVMInfo(addMapping func(lo, hi, offset uint64, file, buildID string)) bool { 19 added := false 20 var addr uint64 = 0x1 21 for { 22 var memRegionSize uint64 23 var info machVMRegionBasicInfoData 24 // Get the first address and page size. 25 kr := mach_vm_region( 26 &addr, 27 &memRegionSize, 28 unsafe.Pointer(&info)) 29 if kr != 0 { 30 if kr == _MACH_SEND_INVALID_DEST { 31 // No more memory regions. 32 return true 33 } 34 return added // return true if at least one mapping was added 35 } 36 if isExecutable(info.Protection) { 37 // NOTE: the meaning/value of Offset is unclear. However, 38 // this likely doesn't matter as the text segment's file 39 // offset is usually 0. 40 addMapping(addr, 41 addr+memRegionSize, 42 read64(&info.Offset), 43 regionFilename(addr), 44 "") 45 added = true 46 } 47 addr += memRegionSize 48 } 49} 50 51func read64(p *[8]byte) uint64 { 52 // all supported darwin platforms are little endian 53 return uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 | uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56 54} 55 56func regionFilename(address uint64) string { 57 buf := make([]byte, _MAXPATHLEN) 58 r := proc_regionfilename( 59 os.Getpid(), 60 address, 61 unsafe.SliceData(buf), 62 int64(cap(buf))) 63 if r == 0 { 64 return "" 65 } 66 return string(buf[:r]) 67} 68 69// mach_vm_region and proc_regionfilename are implemented by 70// the runtime package (runtime/sys_darwin.go). 71// 72//go:noescape 73func mach_vm_region(address, region_size *uint64, info unsafe.Pointer) int32 74 75//go:noescape 76func proc_regionfilename(pid int, address uint64, buf *byte, buflen int64) int32 77