Vendor gopsutil with go mod fix (#8108)

Point to gopsutil fork with shirou/gopsutil#889 changes. I used hashicorp/gopsutil rather than pointing to https://github.com/Lomanic/gopsutil/tree/issue832 directly just in case..
This commit is contained in:
Mahmood Ali
2020-06-03 16:09:27 -04:00
committed by GitHub
parent 87d75f6adf
commit fa845c7a7e
28 changed files with 803 additions and 261 deletions

3
.gitignore vendored
View File

@@ -105,6 +105,3 @@ azure-hashistack.pem
# generated keys for e2e tests
e2e/terraform/keys/
# darwin CGO files copied for build
vendor/github.com/shirou/gopsutil/host/include/

View File

@@ -45,8 +45,6 @@ endif
ifeq (Darwin,$(THIS_OS))
ALL_TARGETS += darwin_amd64
# Copy CGO files for darwin into place
# TODO(shoenig) remove pending github.com/shirou/gopsutil/pull/885
$(shell cp -R lib/darwin/include vendor/github.com/shirou/gopsutil/host)
endif
# On FreeBSD, we only build for FreeBSD

1
go.mod
View File

@@ -9,6 +9,7 @@ replace (
github.com/godbus/dbus => github.com/godbus/dbus v5.0.1+incompatible
github.com/hashicorp/nomad/api => ./api
github.com/kr/pty => github.com/kr/pty v1.1.5
github.com/shirou/gopsutil => github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible
)
require (

5
go.sum
View File

@@ -389,6 +389,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible h1:3dtKc7GWJY4Mm85E1kczAN4JuBFM3kamwt5Zx426Yl8=
github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible/go.mod h1:Mz8xr0ujmCW1qsmWMIUDOc+RgaN9QMvrgnBzQF12nYM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl v1.0.1-0.20191016231534-914dc3f8dd7c h1:PdZEHcpa3117kJ1Wa5EYupzCzn9QlBby8Fx2YpZPYvo=
github.com/hashicorp/hcl v1.0.1-0.20191016231534-914dc3f8dd7c/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -651,9 +653,6 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128 h1:vWI
github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v2.20.2+incompatible h1:ucK79BhBpgqQxPASyS2cu9HX8cfDVljBN1WWFvbNvgY=
github.com/shirou/gopsutil v2.20.2+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=

View File

@@ -14,8 +14,7 @@ import (
)
// TimesStat contains the amounts of time the CPU has spent performing different
// kinds of work. Time units are in USER_HZ or Jiffies (typically hundredths of
// a second). It is based on linux /proc/stat file.
// kinds of work. Time units are in seconds. It is based on linux /proc/stat file.
type TimesStat struct {
CPU string `json:"cpu"`
User float64 `json:"user"`

View File

@@ -4,6 +4,7 @@ package cpu
import (
"context"
"os/exec"
"strconv"
"strings"
@@ -23,6 +24,21 @@ const (
// default value. from time.h
var ClocksPerSec = float64(128)
func init() {
getconf, err := exec.LookPath("getconf")
if err != nil {
return
}
out, err := invoke.Command(getconf, "CLK_TCK")
// ignore errors
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
ClocksPerSec = float64(i)
}
}
}
func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}

View File

@@ -13,7 +13,7 @@ import (
"github.com/shirou/gopsutil/internal/common"
)
var CPUTick = float64(100)
var ClocksPerSec = float64(100)
func init() {
getconf, err := exec.LookPath("getconf")
@@ -25,7 +25,7 @@ func init() {
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
CPUTick = i
ClocksPerSec = i
}
}
}
@@ -250,34 +250,34 @@ func parseStatLine(line string) (*TimesStat, error) {
ct := &TimesStat{
CPU: cpu,
User: user / CPUTick,
Nice: nice / CPUTick,
System: system / CPUTick,
Idle: idle / CPUTick,
Iowait: iowait / CPUTick,
Irq: irq / CPUTick,
Softirq: softirq / CPUTick,
User: user / ClocksPerSec,
Nice: nice / ClocksPerSec,
System: system / ClocksPerSec,
Idle: idle / ClocksPerSec,
Iowait: iowait / ClocksPerSec,
Irq: irq / ClocksPerSec,
Softirq: softirq / ClocksPerSec,
}
if len(fields) > 8 { // Linux >= 2.6.11
steal, err := strconv.ParseFloat(fields[8], 64)
if err != nil {
return nil, err
}
ct.Steal = steal / CPUTick
ct.Steal = steal / ClocksPerSec
}
if len(fields) > 9 { // Linux >= 2.6.24
guest, err := strconv.ParseFloat(fields[9], 64)
if err != nil {
return nil, err
}
ct.Guest = guest / CPUTick
ct.Guest = guest / ClocksPerSec
}
if len(fields) > 10 { // Linux >= 3.2.0
guestNice, err := strconv.ParseFloat(fields[10], 64)
if err != nil {
return nil, err
}
ct.GuestNice = guestNice / CPUTick
ct.GuestNice = guestNice / ClocksPerSec
}
return ct, nil

View File

@@ -50,7 +50,7 @@ type Win32_PerfFormattedData_PerfOS_System struct {
}
const (
win32_TicksPerSecond = 10000000.0
ClocksPerSec = 10000000.0
// systemProcessorPerformanceInformationClass information class to query with NTQuerySystemInformation
// https://processhacker.sourceforge.io/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0
@@ -159,10 +159,10 @@ func perCPUTimes() ([]TimesStat, error) {
for core, v := range stats {
c := TimesStat{
CPU: fmt.Sprintf("cpu%d", core),
User: float64(v.UserTime) / win32_TicksPerSecond,
System: float64(v.KernelTime-v.IdleTime) / win32_TicksPerSecond,
Idle: float64(v.IdleTime) / win32_TicksPerSecond,
Irq: float64(v.InterruptTime) / win32_TicksPerSecond,
User: float64(v.UserTime) / ClocksPerSec,
System: float64(v.KernelTime-v.IdleTime) / ClocksPerSec,
Idle: float64(v.IdleTime) / ClocksPerSec,
Irq: float64(v.InterruptTime) / ClocksPerSec,
}
ret = append(ret, c)
}

View File

@@ -7,7 +7,7 @@ package disk
#cgo LDFLAGS: -framework CoreFoundation -framework IOKit
#include <stdint.h>
#include <CoreFoundation/CoreFoundation.h>
#include "disk_darwin.h"
#include "iostat_darwin.h"
*/
import "C"

View File

@@ -5,6 +5,8 @@ package disk
import (
"bytes"
"context"
"fmt"
"syscall"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@@ -23,18 +25,24 @@ var (
FileReadOnlyVolume = int64(524288) // 0x00080000
)
type Win32_PerfFormattedData struct {
Name string
AvgDiskBytesPerRead uint64
AvgDiskBytesPerWrite uint64
AvgDiskReadQueueLength uint64
AvgDiskWriteQueueLength uint64
AvgDisksecPerRead uint64
AvgDisksecPerWrite uint64
// diskPerformance is an equivalent representation of DISK_PERFORMANCE in the Windows API.
// https://docs.microsoft.com/fr-fr/windows/win32/api/winioctl/ns-winioctl-disk_performance
type diskPerformance struct {
BytesRead int64
BytesWritten int64
ReadTime int64
WriteTime int64
IdleTime int64
ReadCount uint32
WriteCount uint32
QueueDepth uint32
SplitCount uint32
QueryTime int64
StorageDeviceNumber uint32
StorageManagerName [8]uint16
alignmentPadding uint32 // necessary for 32bit support, see https://github.com/elastic/beats/pull/16553
}
const WaitMSec = 500
func Usage(path string) (*UsageStat, error) {
return UsageWithContext(context.Background(), path)
}
@@ -136,31 +144,52 @@ func IOCounters(names ...string) (map[string]IOCountersStat, error) {
}
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
ret := make(map[string]IOCountersStat, 0)
var dst []Win32_PerfFormattedData
// https://github.com/giampaolo/psutil/blob/544e9daa4f66a9f80d7bf6c7886d693ee42f0a13/psutil/arch/windows/disk.c#L83
drivemap := make(map[string]IOCountersStat, 0)
var diskPerformance diskPerformance
err := common.WMIQueryWithContext(ctx, "SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk", &dst)
lpBuffer := make([]uint16, 254)
lpBufferLen, err := windows.GetLogicalDriveStrings(uint32(len(lpBuffer)), &lpBuffer[0])
if err != nil {
return ret, err
return drivemap, err
}
for _, d := range dst {
if len(d.Name) > 3 { // not get _Total or Harddrive
continue
}
for _, v := range lpBuffer[:lpBufferLen] {
if 'A' <= v && v <= 'Z' {
path := string(v) + ":"
typepath, _ := windows.UTF16PtrFromString(path)
typeret := windows.GetDriveType(typepath)
if typeret == 0 {
return drivemap, windows.GetLastError()
}
if typeret != windows.DRIVE_FIXED {
continue
}
szDevice := fmt.Sprintf(`\\.\%s`, path)
const IOCTL_DISK_PERFORMANCE = 0x70020
h, err := windows.CreateFile(syscall.StringToUTF16Ptr(szDevice), 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_EXISTING, 0, 0)
if err != nil {
if err == windows.ERROR_FILE_NOT_FOUND {
continue
}
return drivemap, err
}
defer windows.CloseHandle(h)
if len(names) > 0 && !common.StringsHas(names, d.Name) {
continue
}
ret[d.Name] = IOCountersStat{
Name: d.Name,
ReadCount: uint64(d.AvgDiskReadQueueLength),
WriteCount: d.AvgDiskWriteQueueLength,
ReadBytes: uint64(d.AvgDiskBytesPerRead),
WriteBytes: uint64(d.AvgDiskBytesPerWrite),
ReadTime: d.AvgDisksecPerRead,
WriteTime: d.AvgDisksecPerWrite,
var diskPerformanceSize uint32
err = windows.DeviceIoControl(h, IOCTL_DISK_PERFORMANCE, nil, 0, (*byte)(unsafe.Pointer(&diskPerformance)), uint32(unsafe.Sizeof(diskPerformance)), &diskPerformanceSize, nil)
if err != nil {
return drivemap, err
}
drivemap[path] = IOCountersStat{
ReadBytes: uint64(diskPerformance.BytesRead),
WriteBytes: uint64(diskPerformance.BytesWritten),
ReadCount: uint64(diskPerformance.ReadCount),
WriteCount: uint64(diskPerformance.WriteCount),
ReadTime: uint64(diskPerformance.ReadTime / 10000 / 1000), // convert to ms: https://github.com/giampaolo/psutil/issues/1012
WriteTime: uint64(diskPerformance.WriteTime / 10000 / 1000),
Name: path,
}
}
}
return ret, nil
return drivemap, nil
}

View File

@@ -1,7 +1,7 @@
// https://github.com/lufia/iostat/blob/9f7362b77ad333b26c01c99de52a11bdb650ded2/iostat_darwin.c
#include <stdint.h>
#include <CoreFoundation/CoreFoundation.h>
#include "disk_darwin.h"
#include "iostat_darwin.h"
#define IOKIT 1 /* to get io_name_t in device_types.h */

View File

@@ -4,9 +4,7 @@
package host
// #cgo LDFLAGS: -framework IOKit
// #include <stdio.h>
// #include <string.h>
// #include "include/smc.c"
// #include "smc_darwin.h"
import "C"
import "context"

View File

@@ -460,6 +460,38 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
}
var warns Warnings
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
files, err = filepath.Glob(common.HostSys("/class/thermal/thermal_zone*/"))
if err != nil {
return temperatures, err
}
for _, file := range files {
// Get the name of the temperature you are reading
name, err := ioutil.ReadFile(filepath.Join(file, "type"))
if err != nil {
warns.Add(err)
continue
}
// Get the temperature reading
current, err := ioutil.ReadFile(filepath.Join(file, "temp"))
if err != nil {
warns.Add(err)
continue
}
temperature, err := strconv.ParseInt(strings.TrimSpace(string(current)), 10, 64)
if err != nil {
warns.Add(err)
continue
}
temperatures = append(temperatures, TemperatureStat{
SensorKey: strings.TrimSpace(string(name)),
Temperature: float64(temperature) / 1000.0,
})
}
return temperatures, warns.Reference()
}
// example directory
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
// name temp1_input temp2_input temp3_input temp4_input temp5_input temp6_input temp7_input

170
vendor/github.com/shirou/gopsutil/host/smc_darwin.c generated vendored Normal file
View File

@@ -0,0 +1,170 @@
#include <stdio.h>
#include <string.h>
#include "smc_darwin.h"
#define IOSERVICE_SMC "AppleSMC"
#define IOSERVICE_MODEL "IOPlatformExpertDevice"
#define DATA_TYPE_SP78 "sp78"
typedef enum {
kSMCUserClientOpen = 0,
kSMCUserClientClose = 1,
kSMCHandleYPCEvent = 2,
kSMCReadKey = 5,
kSMCWriteKey = 6,
kSMCGetKeyCount = 7,
kSMCGetKeyFromIndex = 8,
kSMCGetKeyInfo = 9,
} selector_t;
typedef struct {
unsigned char major;
unsigned char minor;
unsigned char build;
unsigned char reserved;
unsigned short release;
} SMCVersion;
typedef struct {
uint16_t version;
uint16_t length;
uint32_t cpuPLimit;
uint32_t gpuPLimit;
uint32_t memPLimit;
} SMCPLimitData;
typedef struct {
IOByteCount data_size;
uint32_t data_type;
uint8_t data_attributes;
} SMCKeyInfoData;
typedef struct {
uint32_t key;
SMCVersion vers;
SMCPLimitData p_limit_data;
SMCKeyInfoData key_info;
uint8_t result;
uint8_t status;
uint8_t data8;
uint32_t data32;
uint8_t bytes[32];
} SMCParamStruct;
typedef enum {
kSMCSuccess = 0,
kSMCError = 1,
kSMCKeyNotFound = 0x84,
} kSMC_t;
typedef struct {
uint8_t data[32];
uint32_t data_type;
uint32_t data_size;
kSMC_t kSMC;
} smc_return_t;
static const int SMC_KEY_SIZE = 4; // number of characters in an SMC key.
static io_connect_t conn; // our connection to the SMC.
kern_return_t open_smc(void) {
kern_return_t result;
io_service_t service;
service = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching(IOSERVICE_SMC));
if (service == 0) {
// Note: IOServiceMatching documents 0 on failure
printf("ERROR: %s NOT FOUND\n", IOSERVICE_SMC);
return kIOReturnError;
}
result = IOServiceOpen(service, mach_task_self(), 0, &conn);
IOObjectRelease(service);
return result;
}
kern_return_t close_smc(void) { return IOServiceClose(conn); }
static uint32_t to_uint32(char *key) {
uint32_t ans = 0;
uint32_t shift = 24;
if (strlen(key) != SMC_KEY_SIZE) {
return 0;
}
for (int i = 0; i < SMC_KEY_SIZE; i++) {
ans += key[i] << shift;
shift -= 8;
}
return ans;
}
static kern_return_t call_smc(SMCParamStruct *input, SMCParamStruct *output) {
kern_return_t result;
size_t input_cnt = sizeof(SMCParamStruct);
size_t output_cnt = sizeof(SMCParamStruct);
result = IOConnectCallStructMethod(conn, kSMCHandleYPCEvent, input, input_cnt,
output, &output_cnt);
if (result != kIOReturnSuccess) {
result = err_get_code(result);
}
return result;
}
static kern_return_t read_smc(char *key, smc_return_t *result_smc) {
kern_return_t result;
SMCParamStruct input;
SMCParamStruct output;
memset(&input, 0, sizeof(SMCParamStruct));
memset(&output, 0, sizeof(SMCParamStruct));
memset(result_smc, 0, sizeof(smc_return_t));
input.key = to_uint32(key);
input.data8 = kSMCGetKeyInfo;
result = call_smc(&input, &output);
result_smc->kSMC = output.result;
if (result != kIOReturnSuccess || output.result != kSMCSuccess) {
return result;
}
result_smc->data_size = output.key_info.data_size;
result_smc->data_type = output.key_info.data_type;
input.key_info.data_size = output.key_info.data_size;
input.data8 = kSMCReadKey;
result = call_smc(&input, &output);
result_smc->kSMC = output.result;
if (result != kIOReturnSuccess || output.result != kSMCSuccess) {
return result;
}
memcpy(result_smc->data, output.bytes, sizeof(output.bytes));
return result;
}
double get_temperature(char *key) {
kern_return_t result;
smc_return_t result_smc;
result = read_smc(key, &result_smc);
if (!(result == kIOReturnSuccess) && result_smc.data_size == 2 &&
result_smc.data_type == to_uint32(DATA_TYPE_SP78)) {
return 0.0;
}
return (double)result_smc.data[0];
}

32
vendor/github.com/shirou/gopsutil/host/smc_darwin.h generated vendored Normal file
View File

@@ -0,0 +1,32 @@
#ifndef __SMC_H__
#define __SMC_H__ 1
#include <IOKit/IOKitLib.h>
#define AMBIENT_AIR_0 "TA0P"
#define AMBIENT_AIR_1 "TA1P"
#define CPU_0_DIODE "TC0D"
#define CPU_0_HEATSINK "TC0H"
#define CPU_0_PROXIMITY "TC0P"
#define ENCLOSURE_BASE_0 "TB0T"
#define ENCLOSURE_BASE_1 "TB1T"
#define ENCLOSURE_BASE_2 "TB2T"
#define ENCLOSURE_BASE_3 "TB3T"
#define GPU_0_DIODE "TG0D"
#define GPU_0_HEATSINK "TG0H"
#define GPU_0_PROXIMITY "TG0P"
#define HARD_DRIVE_BAY "TH0P"
#define MEMORY_SLOT_0 "TM0S"
#define MEMORY_SLOTS_PROXIMITY "TM0P"
#define NORTHBRIDGE "TN0H"
#define NORTHBRIDGE_DIODE "TN0D"
#define NORTHBRIDGE_PROXIMITY "TN0P"
#define THUNDERBOLT_0 "TI0P"
#define THUNDERBOLT_1 "TI1P"
#define WIRELESS_MODULE "TW0P"
kern_return_t open_smc(void);
kern_return_t close_smc(void);
double get_temperature(char *);
#endif // __SMC_H__

View File

@@ -10,7 +10,6 @@ import (
"path/filepath"
"strconv"
"strings"
"sync/atomic"
"time"
)
@@ -54,14 +53,7 @@ func NumProcs() (uint64, error) {
return cnt, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
system, role, err := Virtualization()
if err != nil {
@@ -94,8 +86,7 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
if err != nil {
return 0, err
}
t = uint64(b)
atomic.StoreUint64(&cachedBootTime, t)
t := uint64(b)
return t, nil
}
}
@@ -108,8 +99,7 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
if err != nil {
return 0, err
}
t = uint64(time.Now().Unix()) - uint64(b)
atomic.StoreUint64(&cachedBootTime, t)
t := uint64(time.Now().Unix()) - uint64(b)
return t, nil
}

View File

@@ -49,21 +49,33 @@ const (
PDH_NO_DATA = 0x800007d5
)
const (
ProcessBasicInformation = 0
ProcessWow64Information = 26
)
var (
Modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
ModNt = windows.NewLazySystemDLL("ntdll.dll")
ModPdh = windows.NewLazySystemDLL("pdh.dll")
ModPsapi = windows.NewLazySystemDLL("psapi.dll")
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
ProcRtlGetNativeSystemInformation = ModNt.NewProc("RtlGetNativeSystemInformation")
ProcRtlNtStatusToDosError = ModNt.NewProc("RtlNtStatusToDosError")
ProcNtQueryInformationProcess = ModNt.NewProc("NtQueryInformationProcess")
ProcNtReadVirtualMemory = ModNt.NewProc("NtReadVirtualMemory")
ProcNtWow64QueryInformationProcess64 = ModNt.NewProc("NtWow64QueryInformationProcess64")
ProcNtWow64ReadVirtualMemory64 = ModNt.NewProc("NtWow64ReadVirtualMemory64")
procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
)
type FILETIME struct {

View File

@@ -84,7 +84,7 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
if tot == 0 {
usedPercent = 0
} else {
usedPercent = float64(used) / float64(tot)
usedPercent = float64(used) / float64(tot) * 100
}
ret := &SwapMemoryStat{
Total: tot,

View File

@@ -3,11 +3,7 @@ package net
import (
"context"
"encoding/json"
"fmt"
"net"
"strconv"
"strings"
"syscall"
"github.com/shirou/gopsutil/internal/common"
)
@@ -161,14 +157,6 @@ func (l *ConntrackStatList) Summary() []ConntrackStat {
return []ConntrackStat{*summary}
}
var constMap = map[string]int{
"unix": syscall.AF_UNIX,
"TCP": syscall.SOCK_STREAM,
"UDP": syscall.SOCK_DGRAM,
"IPv4": syscall.AF_INET,
"IPv6": syscall.AF_INET6,
}
func (n IOCountersStat) String() string {
s, _ := json.Marshal(n)
return string(s)
@@ -273,84 +261,3 @@ func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
return []IOCountersStat{r}, nil
}
func parseNetLine(line string) (ConnectionStat, error) {
f := strings.Fields(line)
if len(f) < 8 {
return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
}
if len(f) == 8 {
f = append(f, f[7])
f[7] = "unix"
}
pid, err := strconv.Atoi(f[1])
if err != nil {
return ConnectionStat{}, err
}
fd, err := strconv.Atoi(strings.Trim(f[3], "u"))
if err != nil {
return ConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3])
}
netFamily, ok := constMap[f[4]]
if !ok {
return ConnectionStat{}, fmt.Errorf("unknown family, %s", f[4])
}
netType, ok := constMap[f[7]]
if !ok {
return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
}
var laddr, raddr Addr
if f[7] == "unix" {
laddr.IP = f[8]
} else {
laddr, raddr, err = parseNetAddr(f[8])
if err != nil {
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
}
}
n := ConnectionStat{
Fd: uint32(fd),
Family: uint32(netFamily),
Type: uint32(netType),
Laddr: laddr,
Raddr: raddr,
Pid: int32(pid),
}
if len(f) == 10 {
n.Status = strings.Trim(f[9], "()")
}
return n, nil
}
func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
parse := func(l string) (Addr, error) {
host, port, err := net.SplitHostPort(l)
if err != nil {
return Addr{}, fmt.Errorf("wrong addr, %s", l)
}
lport, err := strconv.Atoi(port)
if err != nil {
return Addr{}, err
}
return Addr{IP: host, Port: uint32(lport)}, nil
}
addrs := strings.Split(line, "->")
if len(addrs) == 0 {
return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line)
}
laddr, err = parse(addrs[0])
if len(addrs) == 2 { // remote addr exists
raddr, err = parse(addrs[1])
if err != nil {
return laddr, raddr, err
}
}
return laddr, raddr, err
}

View File

@@ -50,7 +50,7 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
filename := common.HostProc("net/dev")
return IOCountersByFile(pernic, filename)
return IOCountersByFileWithContext(ctx, pernic, filename)
}
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {

View File

@@ -4,7 +4,11 @@ package net
import (
"context"
"fmt"
"net"
"strconv"
"strings"
"syscall"
"github.com/shirou/gopsutil/internal/common"
)
@@ -86,6 +90,95 @@ func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]C
return ret, nil
}
var constMap = map[string]int{
"unix": syscall.AF_UNIX,
"TCP": syscall.SOCK_STREAM,
"UDP": syscall.SOCK_DGRAM,
"IPv4": syscall.AF_INET,
"IPv6": syscall.AF_INET6,
}
func parseNetLine(line string) (ConnectionStat, error) {
f := strings.Fields(line)
if len(f) < 8 {
return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
}
if len(f) == 8 {
f = append(f, f[7])
f[7] = "unix"
}
pid, err := strconv.Atoi(f[1])
if err != nil {
return ConnectionStat{}, err
}
fd, err := strconv.Atoi(strings.Trim(f[3], "u"))
if err != nil {
return ConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3])
}
netFamily, ok := constMap[f[4]]
if !ok {
return ConnectionStat{}, fmt.Errorf("unknown family, %s", f[4])
}
netType, ok := constMap[f[7]]
if !ok {
return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
}
var laddr, raddr Addr
if f[7] == "unix" {
laddr.IP = f[8]
} else {
laddr, raddr, err = parseNetAddr(f[8])
if err != nil {
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
}
}
n := ConnectionStat{
Fd: uint32(fd),
Family: uint32(netFamily),
Type: uint32(netType),
Laddr: laddr,
Raddr: raddr,
Pid: int32(pid),
}
if len(f) == 10 {
n.Status = strings.Trim(f[9], "()")
}
return n, nil
}
func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
parse := func(l string) (Addr, error) {
host, port, err := net.SplitHostPort(l)
if err != nil {
return Addr{}, fmt.Errorf("wrong addr, %s", l)
}
lport, err := strconv.Atoi(port)
if err != nil {
return Addr{}, err
}
return Addr{IP: host, Port: uint32(lport)}, nil
}
addrs := strings.Split(line, "->")
if len(addrs) == 0 {
return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line)
}
laddr, err = parse(addrs[0])
if len(addrs) == 2 { // remote addr exists
raddr, err = parse(addrs[1])
if err != nil {
return laddr, raddr, err
}
}
return laddr, raddr, err
}
// Return up to `max` network connections opened by a process.
func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error) {
return ConnectionsPidMaxWithContext(context.Background(), kind, pid, max)

View File

@@ -22,7 +22,7 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
}
txtFound := 0
lines := strings.Split(string(out), "\n")
for i := 1; i < len(lines); i += 2 {
for i := 1; i < len(lines); i++ {
if lines[i] == "ftxt" {
txtFound++
if txtFound == 2 {

View File

@@ -1157,10 +1157,19 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
return 0, 0, nil, 0, 0, 0, nil, err
}
// There is no such thing as iotime in stat file. As an approximation, we
// will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux
// docs). Note: I am assuming at least Linux 2.6.18
iotime, err := strconv.ParseFloat(fields[i+40], 64)
if err != nil {
iotime = 0 // Ancient linux version, most likely
}
cpuTimes := &cpu.TimesStat{
CPU: "cpu",
User: float64(utime / ClockTicks),
System: float64(stime / ClockTicks),
Iowait: float64(iotime / ClockTicks),
}
bootTime, _ := common.BootTimeWithContext(ctx)

View File

@@ -4,14 +4,13 @@ package process
import (
"context"
"errors"
"fmt"
"os"
"strings"
"syscall"
"time"
"unsafe"
"github.com/StackExchange/wmi"
cpu "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
net "github.com/shirou/gopsutil/net"
@@ -30,6 +29,9 @@ var (
procQueryFullProcessImageNameW = common.Modkernel32.NewProc("QueryFullProcessImageNameW")
procGetPriorityClass = common.Modkernel32.NewProc("GetPriorityClass")
procGetProcessIoCounters = common.Modkernel32.NewProc("GetProcessIoCounters")
procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
processorArchitecture uint
)
type SystemProcessInformation struct {
@@ -47,6 +49,28 @@ type SystemProcessInformation struct {
Reserved6 [6]uint64
}
type systemProcessorInformation struct {
ProcessorArchitecture uint16
ProcessorLevel uint16
ProcessorRevision uint16
Reserved uint16
ProcessorFeatureBits uint16
}
type systemInfo struct {
wProcessorArchitecture uint16
wReserved uint16
dwPageSize uint32
lpMinimumApplicationAddress uintptr
lpMaximumApplicationAddress uintptr
dwActiveProcessorMask uintptr
dwNumberOfProcessors uint32
dwProcessorType uint32
dwAllocationGranularity uint32
wProcessorLevel uint16
wProcessorRevision uint16
}
// Memory_info_ex is different between OSes
type MemoryInfoExStat struct {
}
@@ -65,43 +89,22 @@ type ioCounters struct {
OtherTransferCount uint64
}
type Win32_Process struct {
Name string
ExecutablePath *string
CommandLine *string
Priority uint32
CreationDate *time.Time
ProcessID uint32
ThreadCount uint32
Status *string
ReadOperationCount uint64
ReadTransferCount uint64
WriteOperationCount uint64
WriteTransferCount uint64
CSCreationClassName string
CSName string
Caption *string
CreationClassName string
Description *string
ExecutionState *uint16
HandleCount uint32
KernelModeTime uint64
MaximumWorkingSetSize *uint32
MinimumWorkingSetSize *uint32
OSCreationClassName string
OSName string
OtherOperationCount uint64
OtherTransferCount uint64
PageFaults uint32
PageFileUsage uint32
ParentProcessID uint32
PeakPageFileUsage uint32
PeakVirtualSize uint64
PeakWorkingSetSize uint32
PrivatePageCount uint64
TerminationDate *time.Time
UserModeTime uint64
WorkingSetSize uint64
type processBasicInformation32 struct {
Reserved1 uint32
PebBaseAddress uint32
Reserved2 uint32
Reserved3 uint32
UniqueProcessId uint32
Reserved4 uint32
}
type processBasicInformation64 struct {
Reserved1 uint64
PebBaseAddress uint64
Reserved2 uint64
Reserved3 uint64
UniqueProcessId uint64
Reserved4 uint64
}
type winLUID struct {
@@ -125,7 +128,10 @@ type winLong int32
type winDWord uint32
func init() {
wmi.DefaultClient.AllowMissingFields = true
var systemInfo systemInfo
procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo)))
processorArchitecture = uint(systemInfo.wProcessorArchitecture)
// enable SeDebugPrivilege https://github.com/midstar/proci/blob/6ec79f57b90ba3d9efa2a7b16ef9c9369d4be875/proci_windows.go#L80-L119
handle, err := syscall.GetCurrentProcess()
@@ -237,26 +243,6 @@ func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
return ppid, nil
}
func GetWin32Proc(pid int32) ([]Win32_Process, error) {
return GetWin32ProcWithContext(context.Background(), pid)
}
func GetWin32ProcWithContext(ctx context.Context, pid int32) ([]Win32_Process, error) {
var dst []Win32_Process
query := fmt.Sprintf("WHERE ProcessId = %d", pid)
q := wmi.CreateQuery(&dst, query)
err := common.WMIQueryWithContext(ctx, q, &dst)
if err != nil {
return []Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err)
}
if len(dst) == 0 {
return []Win32_Process{}, fmt.Errorf("could not get win32Proc: empty")
}
return dst, nil
}
func (p *Process) Name() (string, error) {
return p.NameWithContext(context.Background())
}
@@ -308,12 +294,12 @@ func (p *Process) Cmdline() (string, error) {
return p.CmdlineWithContext(context.Background())
}
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
dst, err := GetWin32ProcWithContext(ctx, p.Pid)
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
cmdline, err := getProcessCommandLine(p.Pid)
if err != nil {
return "", fmt.Errorf("could not get CommandLine: %s", err)
}
return *dst[0].CommandLine, nil
return cmdline, nil
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
@@ -774,24 +760,6 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
return out, nil
}
func getProcInfo(pid int32) (*SystemProcessInformation, error) {
initialBufferSize := uint64(0x4000)
bufferSize := initialBufferSize
buffer := make([]byte, bufferSize)
var sysProcInfo SystemProcessInformation
ret, _, _ := common.ProcNtQuerySystemInformation.Call(
uintptr(unsafe.Pointer(&sysProcInfo)),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(unsafe.Pointer(&bufferSize)),
uintptr(unsafe.Pointer(&bufferSize)))
if ret != 0 {
return nil, windows.GetLastError()
}
return &sysProcInfo, nil
}
func getRusage(pid int32) (*windows.Rusage, error) {
var CPU windows.Rusage
@@ -860,3 +828,148 @@ func getProcessCPUTimes(pid int32) (SYSTEM_TIMES, error) {
return times, err
}
func is32BitProcess(procHandle syscall.Handle) bool {
var wow64 uint
ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle),
uintptr(common.ProcessWow64Information),
uintptr(unsafe.Pointer(&wow64)),
uintptr(unsafe.Sizeof(wow64)),
uintptr(0),
)
if int(ret) >= 0 {
if wow64 != 0 {
return true
}
} else {
//if the OS does not support the call, we fallback into the bitness of the app
if unsafe.Sizeof(wow64) == 4 {
return true
}
}
return false
}
func getProcessCommandLine(pid int32) (string, error) {
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION | windows.PROCESS_VM_READ, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
return "", nil
}
if err != nil {
return "", err
}
defer syscall.CloseHandle(syscall.Handle(h))
const (
PROCESSOR_ARCHITECTURE_INTEL = 0
PROCESSOR_ARCHITECTURE_ARM = 5
PROCESSOR_ARCHITECTURE_ARM64 = 12
PROCESSOR_ARCHITECTURE_IA64 = 6
PROCESSOR_ARCHITECTURE_AMD64 = 9
)
procIs32Bits := true
switch processorArchitecture {
case PROCESSOR_ARCHITECTURE_INTEL:
fallthrough
case PROCESSOR_ARCHITECTURE_ARM:
procIs32Bits = true
case PROCESSOR_ARCHITECTURE_ARM64:
fallthrough
case PROCESSOR_ARCHITECTURE_IA64:
fallthrough
case PROCESSOR_ARCHITECTURE_AMD64:
procIs32Bits = is32BitProcess(syscall.Handle(h))
default:
//for other unknown platforms, we rely on process platform
if unsafe.Sizeof(processorArchitecture) == 8 {
procIs32Bits = false
}
}
pebAddress := queryPebAddress(syscall.Handle(h), procIs32Bits)
if pebAddress == 0 {
return "", errors.New("cannot locate process PEB")
}
if procIs32Bits {
buf := readProcessMemory(syscall.Handle(h), procIs32Bits, pebAddress + uint64(16), 4)
if len(buf) != 4 {
return "", errors.New("cannot locate process user parameters")
}
userProcParams := uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24)
//read CommandLine field from PRTL_USER_PROCESS_PARAMETERS
remoteCmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, userProcParams + uint64(64), 8)
if len(remoteCmdLine) != 8 {
return "", errors.New("cannot read cmdline field")
}
//remoteCmdLine is actually a UNICODE_STRING32
//the first two bytes has the length
cmdLineLength := uint(remoteCmdLine[0]) | (uint(remoteCmdLine[1]) << 8)
if cmdLineLength > 0 {
//and, at offset 4, is the pointer to the buffer
bufferAddress := uint32(remoteCmdLine[4]) | (uint32(remoteCmdLine[5]) << 8) |
(uint32(remoteCmdLine[6]) << 16) | (uint32(remoteCmdLine[7]) << 24)
cmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, uint64(bufferAddress), cmdLineLength)
if len(cmdLine) != int(cmdLineLength) {
return "", errors.New("cannot read cmdline")
}
return convertUTF16ToString(cmdLine), nil
}
} else {
buf := readProcessMemory(syscall.Handle(h), procIs32Bits, pebAddress + uint64(32), 8)
if len(buf) != 8 {
return "", errors.New("cannot locate process user parameters")
}
userProcParams := uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24) |
(uint64(buf[4]) << 32) | (uint64(buf[5]) << 40) | (uint64(buf[6]) << 48) | (uint64(buf[7]) << 56)
//read CommandLine field from PRTL_USER_PROCESS_PARAMETERS
remoteCmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, userProcParams + uint64(112), 16)
if len(remoteCmdLine) != 16 {
return "", errors.New("cannot read cmdline field")
}
//remoteCmdLine is actually a UNICODE_STRING64
//the first two bytes has the length
cmdLineLength := uint(remoteCmdLine[0]) | (uint(remoteCmdLine[1]) << 8)
if cmdLineLength > 0 {
//and, at offset 8, is the pointer to the buffer
bufferAddress := uint64(remoteCmdLine[8]) | (uint64(remoteCmdLine[9]) << 8) |
(uint64(remoteCmdLine[10]) << 16) | (uint64(remoteCmdLine[11]) << 24) |
(uint64(remoteCmdLine[12]) << 32) | (uint64(remoteCmdLine[13]) << 40) |
(uint64(remoteCmdLine[14]) << 48) | (uint64(remoteCmdLine[15]) << 56)
cmdLine := readProcessMemory(syscall.Handle(h), procIs32Bits, bufferAddress, cmdLineLength)
if len(cmdLine) != int(cmdLineLength) {
return "", errors.New("cannot read cmdline")
}
return convertUTF16ToString(cmdLine), nil
}
}
//if we reach here, we have no command line
return "", nil
}
func convertUTF16ToString(src []byte) string {
srcLen := len(src) / 2
codePoints := make([]uint16, srcLen)
srcIdx := 0
for i := 0; i < srcLen; i++ {
codePoints[i] = uint16(src[srcIdx]) | uint16(src[srcIdx + 1] << 8)
srcIdx += 2
}
return syscall.UTF16ToString(codePoints)
}

View File

@@ -2,6 +2,13 @@
package process
import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
)
type PROCESS_MEMORY_COUNTERS struct {
CB uint32
PageFaultCount uint32
@@ -14,3 +21,82 @@ type PROCESS_MEMORY_COUNTERS struct {
PagefileUsage uint32
PeakPagefileUsage uint32
}
func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) uint64 {
if is32BitProcess {
//we are on a 32-bit process reading an external 32-bit process
var info processBasicInformation32
ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle),
uintptr(common.ProcessBasicInformation),
uintptr(unsafe.Pointer(&info)),
uintptr(unsafe.Sizeof(info)),
uintptr(0),
)
if int(ret) >= 0 {
return uint64(info.PebBaseAddress)
}
} else {
//we are on a 32-bit process reading an external 64-bit process
if common.ProcNtWow64QueryInformationProcess64.Find() == nil { //avoid panic
var info processBasicInformation64
ret, _, _ := common.ProcNtWow64QueryInformationProcess64.Call(
uintptr(procHandle),
uintptr(common.ProcessBasicInformation),
uintptr(unsafe.Pointer(&info)),
uintptr(unsafe.Sizeof(info)),
uintptr(0),
)
if int(ret) >= 0 {
return info.PebBaseAddress
}
}
}
//return 0 on error
return 0
}
func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, size uint) []byte {
if is32BitProcess {
var read uint
buffer := make([]byte, size)
ret, _, _ := common.ProcNtReadVirtualMemory.Call(
uintptr(h),
uintptr(address),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(size),
uintptr(unsafe.Pointer(&read)),
)
if int(ret) >= 0 && read > 0 {
return buffer[:read]
}
} else {
//reading a 64-bit process from a 32-bit one
if common.ProcNtWow64ReadVirtualMemory64.Find() == nil { //avoid panic
var read uint64
buffer := make([]byte, size)
ret, _, _ := common.ProcNtWow64ReadVirtualMemory64.Call(
uintptr(h),
uintptr(address & 0xFFFFFFFF), //the call expects a 64-bit value
uintptr(address >> 32),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(size), //the call expects a 64-bit value
uintptr(0), //but size is 32-bit so pass zero as the high dword
uintptr(unsafe.Pointer(&read)),
)
if int(ret) >= 0 && read > 0 {
return buffer[:uint(read)]
}
}
}
//if we reach here, an error happened
return nil
}

View File

@@ -2,6 +2,13 @@
package process
import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
)
type PROCESS_MEMORY_COUNTERS struct {
CB uint32
PageFaultCount uint32
@@ -14,3 +21,56 @@ type PROCESS_MEMORY_COUNTERS struct {
PagefileUsage uint64
PeakPagefileUsage uint64
}
func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) uint64 {
if is32BitProcess {
//we are on a 64-bit process reading an external 32-bit process
var wow64 uint
ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle),
uintptr(common.ProcessWow64Information),
uintptr(unsafe.Pointer(&wow64)),
uintptr(unsafe.Sizeof(wow64)),
uintptr(0),
)
if int(ret) >= 0 {
return uint64(wow64)
}
} else {
//we are on a 64-bit process reading an external 64-bit process
var info processBasicInformation64
ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle),
uintptr(common.ProcessBasicInformation),
uintptr(unsafe.Pointer(&info)),
uintptr(unsafe.Sizeof(info)),
uintptr(0),
)
if int(ret) >= 0 {
return info.PebBaseAddress
}
}
//return 0 on error
return 0
}
func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte {
var read uint
buffer := make([]byte, size)
ret, _, _ := common.ProcNtReadVirtualMemory.Call(
uintptr(procHandle),
uintptr(address),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(size),
uintptr(unsafe.Pointer(&read)),
)
if int(ret) >= 0 && read > 0 {
return buffer[:read]
}
return nil
}

3
vendor/modules.txt vendored
View File

@@ -700,7 +700,7 @@ github.com/sean-/seed
# github.com/seccomp/libseccomp-golang v0.9.2-0.20200314001724-bdab42bd5128
## explicit
github.com/seccomp/libseccomp-golang
# github.com/shirou/gopsutil v2.20.2+incompatible
# github.com/shirou/gopsutil v2.20.2+incompatible => github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible
## explicit
github.com/shirou/gopsutil/cpu
github.com/shirou/gopsutil/disk
@@ -1059,3 +1059,4 @@ honnef.co/go/tools/version
# github.com/godbus/dbus => github.com/godbus/dbus v5.0.1+incompatible
# github.com/hashicorp/nomad/api => ./api
# github.com/kr/pty => github.com/kr/pty v1.1.5
# github.com/shirou/gopsutil => github.com/hashicorp/gopsutil v2.18.13-0.20200531184148-5aca383d4f9d+incompatible