| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package pprof |
| |
| import ( |
| "errors" |
| "internal/syscall/windows" |
| "os" |
| "syscall" |
| ) |
| |
| // readMapping adds memory mapping information to the profile. |
| func (b *profileBuilder) readMapping() { |
| snap, err := createModuleSnapshot() |
| if err != nil { |
| // pprof expects a map entry, so fake one, when we haven't added anything yet. |
| b.addMappingEntry(0, 0, 0, "", "", true) |
| return |
| } |
| defer func() { _ = syscall.CloseHandle(snap) }() |
| |
| var module windows.ModuleEntry32 |
| module.Size = uint32(windows.SizeofModuleEntry32) |
| err = windows.Module32First(snap, &module) |
| if err != nil { |
| // pprof expects a map entry, so fake one, when we haven't added anything yet. |
| b.addMappingEntry(0, 0, 0, "", "", true) |
| return |
| } |
| for err == nil { |
| exe := syscall.UTF16ToString(module.ExePath[:]) |
| b.addMappingEntry( |
| uint64(module.ModBaseAddr), |
| uint64(module.ModBaseAddr)+uint64(module.ModBaseSize), |
| 0, |
| exe, |
| peBuildID(exe), |
| false, |
| ) |
| err = windows.Module32Next(snap, &module) |
| } |
| } |
| |
| func readMainModuleMapping() (start, end uint64, exe, buildID string, err error) { |
| exe, err = os.Executable() |
| if err != nil { |
| return 0, 0, "", "", err |
| } |
| snap, err := createModuleSnapshot() |
| if err != nil { |
| return 0, 0, "", "", err |
| } |
| defer func() { _ = syscall.CloseHandle(snap) }() |
| |
| var module windows.ModuleEntry32 |
| module.Size = uint32(windows.SizeofModuleEntry32) |
| err = windows.Module32First(snap, &module) |
| if err != nil { |
| return 0, 0, "", "", err |
| } |
| |
| return uint64(module.ModBaseAddr), uint64(module.ModBaseAddr) + uint64(module.ModBaseSize), exe, peBuildID(exe), nil |
| } |
| |
| func createModuleSnapshot() (syscall.Handle, error) { |
| for { |
| snap, err := syscall.CreateToolhelp32Snapshot(windows.TH32CS_SNAPMODULE|windows.TH32CS_SNAPMODULE32, uint32(syscall.Getpid())) |
| var errno syscall.Errno |
| if err != nil && errors.As(err, &errno) && errno == windows.ERROR_BAD_LENGTH { |
| // When CreateToolhelp32Snapshot(SNAPMODULE|SNAPMODULE32, ...) fails |
| // with ERROR_BAD_LENGTH then it should be retried until it succeeds. |
| continue |
| } |
| return snap, err |
| } |
| } |