forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
147 lines (129 loc) · 4.78 KB
/
Copy pathutils.py
File metadata and controls
147 lines (129 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
145
146
147
# Copyright 2016 Catalysts GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import ctypes as ct
import sys
import traceback
import warnings
import re
from .libbcc import lib
def _read_cpu_range(path):
cpus = []
with open(path, 'r') as f:
cpus_range_str = f.read()
for cpu_range in cpus_range_str.split(','):
rangeop = cpu_range.find('-')
if rangeop == -1:
cpus.append(int(cpu_range))
else:
start = int(cpu_range[:rangeop])
end = int(cpu_range[rangeop+1:])
cpus.extend(range(start, end+1))
return cpus
def get_online_cpus():
return _read_cpu_range('/sys/devices/system/cpu/online')
def get_possible_cpus():
return _read_cpu_range('/sys/devices/system/cpu/possible')
def detect_language(candidates, pid):
res = lib.bcc_procutils_language(pid)
language = ct.cast(res, ct.c_char_p).value.decode()
return language if language in candidates else None
FILESYSTEMENCODING = sys.getfilesystemencoding()
def printb(s, file=sys.stdout, nl=1):
"""
printb(s)
print a bytes object to stdout and flush
"""
buf = file.buffer if hasattr(file, "buffer") else file
buf.write(s)
if nl:
buf.write(b"\n")
file.flush()
class ArgString(object):
"""
ArgString(arg)
encapsulate a system argument that can be easily coerced to a bytes()
object, which is better for comparing to kernel or probe data (which should
never be en/decode()'ed).
"""
def __init__(self, arg):
if sys.version_info[0] >= 3:
self.s = arg
else:
self.s = arg.decode(FILESYSTEMENCODING)
def __bytes__(self):
return self.s.encode(FILESYSTEMENCODING)
def __str__(self):
return self.s
def warn_with_traceback(message, category, filename, lineno, file=None, line=None):
log = file if hasattr(file, "write") else sys.stderr
traceback.print_stack(f=sys._getframe(2), file=log)
log.write(warnings.formatwarning(message, category, filename, lineno, line))
# uncomment to get full tracebacks for invalid uses of python3+str in arguments
#warnings.showwarning = warn_with_traceback
_strict_bytes = False
def _assert_is_bytes(arg):
if arg is None:
return arg
if _strict_bytes:
assert type(arg) is bytes, "not a bytes object: %r" % arg
elif type(arg) is not bytes:
warnings.warn("not a bytes object: %r" % arg, DeprecationWarning, 2)
return ArgString(arg).__bytes__()
return arg
class StrcmpRewrite(object):
@staticmethod
def _generate_streq_function(string, probe_read_func, streq_functions,
probeid):
fname = "streq_%d" % probeid
streq_functions += """
static inline bool %s(char const *ignored, uintptr_t str) {
char needle[] = %s;
char haystack[sizeof(needle)];
%s(&haystack, sizeof(haystack), (void *)str);
for (int i = 0; i < sizeof(needle) - 1; ++i) {
if (needle[i] != haystack[i]) {
return false;
}
}
return true;
}
""" % (fname, string, probe_read_func)
return fname, streq_functions
@staticmethod
def rewrite_expr(expr, bin_cmp, is_user, probe_user_list, streq_functions,
probeid):
if bin_cmp:
STRCMP_RE = 'STRCMP\\(\"([^"]+)\\",(.+?)\\)'
else:
STRCMP_RE = 'STRCMP\\(("[^"]+\\"),(.+?)\\)'
matches = re.finditer(STRCMP_RE, expr)
for match in matches:
string = match.group(1)
probe_read_func = "bpf_probe_read"
# if user probe or @user tag is specified, use
# bpf_probe_read_user for char* read
if is_user or \
match.group(2).strip() in probe_user_list:
probe_read_func = "bpf_probe_read_user"
fname, streq_functions = StrcmpRewrite._generate_streq_function(
string, probe_read_func,
streq_functions, probeid)
probeid += 1
expr = expr.replace("STRCMP", fname, 1)
rdict = {
"expr": expr,
"streq_functions": streq_functions,
"probeid": probeid
}
return rdict