Source file
src/runtime/pprof/vminfo_darwin_test.go
1
2
3
4
5
6
7 package pprof
8
9 import (
10 "bufio"
11 "bytes"
12 "fmt"
13 "internal/abi"
14 "internal/testenv"
15 "os"
16 "os/exec"
17 "strconv"
18 "strings"
19 "testing"
20 )
21
22 func TestVMInfo(t *testing.T) {
23 var begin, end, offset uint64
24 var filename string
25 first := true
26 machVMInfo(func(lo, hi, off uint64, file, buildID string) {
27 if first {
28 begin = lo
29 end = hi
30 offset = off
31 filename = file
32 }
33
34
35 first = false
36 })
37 lo, hi, err := useVMMapWithRetry(t)
38 if err != nil {
39 t.Fatal(err)
40 }
41 if got, want := begin, lo; got != want {
42 t.Errorf("got %x, want %x", got, want)
43 }
44 if got, want := end, hi; got != want {
45 t.Errorf("got %x, want %x", got, want)
46 }
47 if got, want := offset, uint64(0); got != want {
48 t.Errorf("got %x, want %x", got, want)
49 }
50 if !strings.HasSuffix(filename, "pprof.test") {
51 t.Errorf("got %s, want pprof.test", filename)
52 }
53 addr := uint64(abi.FuncPCABIInternal(TestVMInfo))
54 if addr < lo || addr > hi {
55 t.Errorf("%x..%x does not contain function %p (%x)", lo, hi, TestVMInfo, addr)
56 }
57 }
58
59 func useVMMapWithRetry(t *testing.T) (hi, lo uint64, err error) {
60 var retryable bool
61 for {
62 hi, lo, retryable, err = useVMMap(t)
63 if err == nil {
64 return hi, lo, nil
65 }
66 if !retryable {
67 return 0, 0, err
68 }
69 t.Logf("retrying vmmap after error: %v", err)
70 }
71 }
72
73 func useVMMap(t *testing.T) (hi, lo uint64, retryable bool, err error) {
74 pid := strconv.Itoa(os.Getpid())
75 testenv.MustHaveExecPath(t, "vmmap")
76 cmd := testenv.Command(t, "vmmap", pid)
77 out, cmdErr := cmd.Output()
78 if cmdErr != nil {
79 t.Logf("vmmap output: %s", out)
80 if ee, ok := cmdErr.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
81 t.Logf("%v: %v\n%s", cmd, cmdErr, ee.Stderr)
82 }
83 retryable = bytes.Contains(out, []byte("resource shortage"))
84 t.Logf("%v: %v", cmd, cmdErr)
85 if retryable {
86 return 0, 0, true, cmdErr
87 }
88 }
89
90
91
92 hi, lo, err = parseVmmap(out)
93 if err != nil {
94 if cmdErr != nil {
95 return 0, 0, false, fmt.Errorf("failed to parse vmmap output, vmmap reported an error: %v", err)
96 }
97 t.Logf("vmmap output: %s", out)
98 return 0, 0, false, fmt.Errorf("failed to parse vmmap output, vmmap did not report an error: %v", err)
99 }
100 return hi, lo, false, nil
101 }
102
103
104 func parseVmmap(data []byte) (hi, lo uint64, err error) {
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 banner := "==== Non-writable regions for process"
145 grabbing := false
146 sc := bufio.NewScanner(bytes.NewReader(data))
147 for sc.Scan() {
148 l := sc.Text()
149 if grabbing {
150 p := strings.Fields(l)
151 if len(p) > 7 && p[0] == "__TEXT" && p[7] == "r-x/rwx" {
152 locs := strings.Split(p[1], "-")
153 start, _ := strconv.ParseUint(locs[0], 16, 64)
154 end, _ := strconv.ParseUint(locs[1], 16, 64)
155 return start, end, nil
156 }
157 }
158 if strings.HasPrefix(l, banner) {
159 grabbing = true
160 }
161 }
162 return 0, 0, fmt.Errorf("vmmap no text segment found")
163 }
164
View as plain text