Source file src/runtime/pprof/vminfo_darwin.go

     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  
     5  package pprof
     6  
     7  import (
     8  	"os"
     9  	"unsafe"
    10  )
    11  
    12  func 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.
    18  func 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  
    51  func 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  
    56  func 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
    73  func mach_vm_region(address, region_size *uint64, info unsafe.Pointer) int32
    74  
    75  //go:noescape
    76  func proc_regionfilename(pid int, address uint64, buf *byte, buflen int64) int32
    77  

View as plain text