cubefs

Форк
0
211 строк · 4.6 Кб
1
// Copyright 2019 The Prometheus Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !js
15
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
16
// +build !js
17

18
package procfs
19

20
import (
21
	"bufio"
22
	"fmt"
23
	"os"
24
	"strconv"
25
	"strings"
26

27
	"golang.org/x/sys/unix"
28
)
29

30
// ProcMapPermissions contains permission settings read from `/proc/[pid]/maps`.
31
type ProcMapPermissions struct {
32
	// mapping has the [R]ead flag set
33
	Read bool
34
	// mapping has the [W]rite flag set
35
	Write bool
36
	// mapping has the [X]ecutable flag set
37
	Execute bool
38
	// mapping has the [S]hared flag set
39
	Shared bool
40
	// mapping is marked as [P]rivate (copy on write)
41
	Private bool
42
}
43

44
// ProcMap contains the process memory-mappings of the process
45
// read from `/proc/[pid]/maps`.
46
type ProcMap struct {
47
	// The start address of current mapping.
48
	StartAddr uintptr
49
	// The end address of the current mapping
50
	EndAddr uintptr
51
	// The permissions for this mapping
52
	Perms *ProcMapPermissions
53
	// The current offset into the file/fd (e.g., shared libs)
54
	Offset int64
55
	// Device owner of this mapping (major:minor) in Mkdev format.
56
	Dev uint64
57
	// The inode of the device above
58
	Inode uint64
59
	// The file or psuedofile (or empty==anonymous)
60
	Pathname string
61
}
62

63
// parseDevice parses the device token of a line and converts it to a dev_t
64
// (mkdev) like structure.
65
func parseDevice(s string) (uint64, error) {
66
	toks := strings.Split(s, ":")
67
	if len(toks) < 2 {
68
		return 0, fmt.Errorf("unexpected number of fields")
69
	}
70

71
	major, err := strconv.ParseUint(toks[0], 16, 0)
72
	if err != nil {
73
		return 0, err
74
	}
75

76
	minor, err := strconv.ParseUint(toks[1], 16, 0)
77
	if err != nil {
78
		return 0, err
79
	}
80

81
	return unix.Mkdev(uint32(major), uint32(minor)), nil
82
}
83

84
// parseAddress converts a hex-string to a uintptr.
85
func parseAddress(s string) (uintptr, error) {
86
	a, err := strconv.ParseUint(s, 16, 0)
87
	if err != nil {
88
		return 0, err
89
	}
90

91
	return uintptr(a), nil
92
}
93

94
// parseAddresses parses the start-end address.
95
func parseAddresses(s string) (uintptr, uintptr, error) {
96
	toks := strings.Split(s, "-")
97
	if len(toks) < 2 {
98
		return 0, 0, fmt.Errorf("invalid address")
99
	}
100

101
	saddr, err := parseAddress(toks[0])
102
	if err != nil {
103
		return 0, 0, err
104
	}
105

106
	eaddr, err := parseAddress(toks[1])
107
	if err != nil {
108
		return 0, 0, err
109
	}
110

111
	return saddr, eaddr, nil
112
}
113

114
// parsePermissions parses a token and returns any that are set.
115
func parsePermissions(s string) (*ProcMapPermissions, error) {
116
	if len(s) < 4 {
117
		return nil, fmt.Errorf("invalid permissions token")
118
	}
119

120
	perms := ProcMapPermissions{}
121
	for _, ch := range s {
122
		switch ch {
123
		case 'r':
124
			perms.Read = true
125
		case 'w':
126
			perms.Write = true
127
		case 'x':
128
			perms.Execute = true
129
		case 'p':
130
			perms.Private = true
131
		case 's':
132
			perms.Shared = true
133
		}
134
	}
135

136
	return &perms, nil
137
}
138

139
// parseProcMap will attempt to parse a single line within a proc/[pid]/maps
140
// buffer.
141
func parseProcMap(text string) (*ProcMap, error) {
142
	fields := strings.Fields(text)
143
	if len(fields) < 5 {
144
		return nil, fmt.Errorf("truncated procmap entry")
145
	}
146

147
	saddr, eaddr, err := parseAddresses(fields[0])
148
	if err != nil {
149
		return nil, err
150
	}
151

152
	perms, err := parsePermissions(fields[1])
153
	if err != nil {
154
		return nil, err
155
	}
156

157
	offset, err := strconv.ParseInt(fields[2], 16, 0)
158
	if err != nil {
159
		return nil, err
160
	}
161

162
	device, err := parseDevice(fields[3])
163
	if err != nil {
164
		return nil, err
165
	}
166

167
	inode, err := strconv.ParseUint(fields[4], 10, 0)
168
	if err != nil {
169
		return nil, err
170
	}
171

172
	pathname := ""
173

174
	if len(fields) >= 5 {
175
		pathname = strings.Join(fields[5:], " ")
176
	}
177

178
	return &ProcMap{
179
		StartAddr: saddr,
180
		EndAddr:   eaddr,
181
		Perms:     perms,
182
		Offset:    offset,
183
		Dev:       device,
184
		Inode:     inode,
185
		Pathname:  pathname,
186
	}, nil
187
}
188

189
// ProcMaps reads from /proc/[pid]/maps to get the memory-mappings of the
190
// process.
191
func (p Proc) ProcMaps() ([]*ProcMap, error) {
192
	file, err := os.Open(p.path("maps"))
193
	if err != nil {
194
		return nil, err
195
	}
196
	defer file.Close()
197

198
	maps := []*ProcMap{}
199
	scan := bufio.NewScanner(file)
200

201
	for scan.Scan() {
202
		m, err := parseProcMap(scan.Text())
203
		if err != nil {
204
			return nil, err
205
		}
206

207
		maps = append(maps, m)
208
	}
209

210
	return maps, nil
211
}
212

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.