Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
b755c709
Commit
b755c709
authored
Jul 18, 2016
by
Brenden Blanco
Committed by
GitHub
Jul 18, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #614 from markdrayton/fix-auto-kprobe
Fix probe detaching and auto-kprobes
parents
a1333bcd
cb679d7b
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
170 additions
and
117 deletions
+170
-117
src/python/bcc/__init__.py
src/python/bcc/__init__.py
+121
-111
src/python/bcc/table.py
src/python/bcc/table.py
+3
-3
tests/python/test_histogram.py
tests/python/test_histogram.py
+3
-0
tests/python/test_probe_count.py
tests/python/test_probe_count.py
+41
-1
tools/argdist.py
tools/argdist.py
+2
-2
No files found.
src/python/bcc/__init__.py
View file @
b755c709
...
@@ -20,7 +20,6 @@ import json
...
@@ -20,7 +20,6 @@ import json
import
multiprocessing
import
multiprocessing
import
os
import
os
import
re
import
re
from
subprocess
import
Popen
,
PIPE
,
STDOUT
import
struct
import
struct
import
sys
import
sys
basestring
=
(
unicode
if
sys
.
version_info
[
0
]
<
3
else
str
)
basestring
=
(
unicode
if
sys
.
version_info
[
0
]
<
3
else
str
)
...
@@ -31,45 +30,20 @@ from .table import Table
...
@@ -31,45 +30,20 @@ from .table import Table
from
.tracepoint
import
Perf
,
Tracepoint
from
.tracepoint
import
Perf
,
Tracepoint
from
.usyms
import
ProcessSymbols
from
.usyms
import
ProcessSymbols
open_kprobes
=
{}
open_uprobes
=
{}
open_tracepoints
=
{}
tracefile
=
None
TRACEFS
=
"/sys/kernel/debug/tracing"
_kprobe_limit
=
1000
_kprobe_limit
=
1000
_num_open_probes
=
0
# for tests
def
_get_num_open_probes
():
global
_num_open_probes
return
_num_open_probes
TRACEFS
=
"/sys/kernel/debug/tracing"
DEBUG_LLVM_IR
=
0x1
DEBUG_LLVM_IR
=
0x1
DEBUG_BPF
=
0x2
DEBUG_BPF
=
0x2
DEBUG_PREPROCESSOR
=
0x4
DEBUG_PREPROCESSOR
=
0x4
@
atexit
.
register
def
cleanup_kprobes
():
for
k
,
v
in
open_kprobes
.
items
():
lib
.
perf_reader_free
(
v
)
if
isinstance
(
k
,
str
):
desc
=
"-:kprobes/%s"
%
k
lib
.
bpf_detach_kprobe
(
desc
.
encode
(
"ascii"
))
for
k
,
v
in
open_uprobes
.
items
():
lib
.
perf_reader_free
(
v
)
if
isinstance
(
k
,
str
):
desc
=
"-:uprobes/%s"
%
k
lib
.
bpf_detach_uprobe
(
desc
.
encode
(
"ascii"
))
for
k
,
v
in
open_tracepoints
.
items
():
lib
.
perf_reader_free
(
v
)
if
isinstance
(
k
,
str
):
(
tp_category
,
tp_name
)
=
k
.
split
(
':'
)
lib
.
bpf_detach_tracepoint
(
tp_category
,
tp_name
)
open_kprobes
.
clear
()
open_uprobes
.
clear
()
open_tracepoints
.
clear
()
if
tracefile
:
tracefile
.
close
()
def
_check_probe_quota
(
num_new_probes
):
if
len
(
open_kprobes
)
+
len
(
open_uprobes
)
+
num_new_probes
>
_kprobe_limit
:
raise
Exception
(
"Number of open probes would exceed quota"
)
class
SymbolCache
(
object
):
class
SymbolCache
(
object
):
def
__init__
(
self
,
pid
):
def
__init__
(
self
,
pid
):
self
.
cache
=
lib
.
bcc_symcache_new
(
pid
)
self
.
cache
=
lib
.
bcc_symcache_new
(
pid
)
...
@@ -159,6 +133,12 @@ class BPF(object):
...
@@ -159,6 +133,12 @@ class BPF(object):
DEBUG_PREPROCESSOR: print Preprocessed C file to stderr
DEBUG_PREPROCESSOR: print Preprocessed C file to stderr
"""
"""
self
.
open_kprobes
=
{}
self
.
open_uprobes
=
{}
self
.
open_tracepoints
=
{}
self
.
tracefile
=
None
atexit
.
register
(
self
.
cleanup
)
self
.
_reader_cb_impl
=
_CB_TYPE
(
BPF
.
_reader_cb
)
self
.
_reader_cb_impl
=
_CB_TYPE
(
BPF
.
_reader_cb
)
self
.
_user_cb
=
cb
self
.
_user_cb
=
cb
self
.
debug
=
debug
self
.
debug
=
debug
...
@@ -348,24 +328,40 @@ class BPF(object):
...
@@ -348,24 +328,40 @@ class BPF(object):
%
(
dev
,
errstr
))
%
(
dev
,
errstr
))
fn
.
sock
=
sock
fn
.
sock
=
sock
@
staticmethod
def
_get_kprobe_functions
(
self
,
event_re
):
def
_get_kprobe_functions
(
event_re
):
blacklist
=
set
([
line
.
rstrip
().
split
()[
1
]
for
line
in
p
=
Popen
([
"awk"
,
"$1 ~ /%s/ { print $1 }"
%
event_re
,
open
(
"%s/../kprobes/blacklist"
%
TRACEFS
)])
"%s/available_filter_functions"
%
TRACEFS
],
stdout
=
PIPE
)
fns
=
[]
lines
=
p
.
communicate
()[
0
].
decode
().
split
()
with
open
(
"%s/available_filter_functions"
%
TRACEFS
)
as
f
:
with
open
(
"%s/../kprobes/blacklist"
%
TRACEFS
)
as
f
:
for
line
in
f
:
blacklist
=
[
line
.
split
()[
1
]
for
line
in
f
.
readlines
()
]
fn
=
line
.
rstrip
().
split
()[
0
]
fns
=
[
line
.
rstrip
()
for
line
in
lines
if
if
re
.
match
(
event_re
,
fn
)
and
fn
not
in
blacklist
:
(
line
!=
"
\
n
"
and
line
not
in
blacklist
)]
fns
.
append
(
fn
)
_check_probe_quota
(
len
(
fns
))
self
.
_check_probe_quota
(
len
(
fns
))
return
fns
return
fns
def
_check_probe_quota
(
self
,
num_new_probes
):
global
_num_open_probes
if
_num_open_probes
+
num_new_probes
>
_kprobe_limit
:
raise
Exception
(
"Number of open probes would exceed global quota"
)
def
_add_kprobe
(
self
,
name
,
probe
):
global
_num_open_probes
self
.
open_kprobes
[
name
]
=
probe
_num_open_probes
+=
1
def
_del_kprobe
(
self
,
name
):
global
_num_open_probes
del
self
.
open_kprobes
[
name
]
_num_open_probes
-=
1
def
attach_kprobe
(
self
,
event
=
""
,
fn_name
=
""
,
event_re
=
""
,
def
attach_kprobe
(
self
,
event
=
""
,
fn_name
=
""
,
event_re
=
""
,
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
assert
isinstance
(
event
,
str
),
"event must be a string"
# allow the caller to glob multiple functions together
# allow the caller to glob multiple functions together
if
event_re
:
if
event_re
:
for
line
in
BPF
.
_get_kprobe_functions
(
event_re
):
for
line
in
self
.
_get_kprobe_functions
(
event_re
):
try
:
try
:
self
.
attach_kprobe
(
event
=
line
,
fn_name
=
fn_name
,
pid
=
pid
,
self
.
attach_kprobe
(
event
=
line
,
fn_name
=
fn_name
,
pid
=
pid
,
cpu
=
cpu
,
group_fd
=
group_fd
)
cpu
=
cpu
,
group_fd
=
group_fd
)
...
@@ -373,7 +369,7 @@ class BPF(object):
...
@@ -373,7 +369,7 @@ class BPF(object):
pass
pass
return
return
_check_probe_quota
(
1
)
self
.
_check_probe_quota
(
1
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
ev_name
=
"p_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
ev_name
=
"p_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
desc
=
"p:kprobes/%s %s"
%
(
ev_name
,
event
)
desc
=
"p:kprobes/%s %s"
%
(
ev_name
,
event
)
...
@@ -383,42 +379,28 @@ class BPF(object):
...
@@ -383,42 +379,28 @@ class BPF(object):
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
if
not
res
:
if
not
res
:
raise
Exception
(
"Failed to attach BPF to kprobe"
)
raise
Exception
(
"Failed to attach BPF to kprobe"
)
open_kprobes
[
ev_name
]
=
res
self
.
_add_kprobe
(
ev_name
,
res
)
return
self
return
self
@
staticmethod
def
detach_kprobe
(
self
,
event
):
def
open_kprobes
():
assert
isinstance
(
event
,
str
),
"event must be a string"
global
open_kprobes
return
open_kprobes
@
staticmethod
def
open_uprobes
():
global
open_uprobes
return
open_uprobes
@
staticmethod
def
open_tracepoints
():
global
open_tracepoints
return
open_tracepoints
@
staticmethod
def
detach_kprobe
(
event
):
ev_name
=
"p_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
ev_name
=
"p_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
if
ev_name
not
in
open_kprobes
:
if
ev_name
not
in
self
.
open_kprobes
:
raise
Exception
(
"Kprobe %s is not attached"
%
event
)
raise
Exception
(
"Kprobe %s is not attached"
%
event
)
lib
.
perf_reader_free
(
open_kprobes
[
ev_name
])
lib
.
perf_reader_free
(
self
.
open_kprobes
[
ev_name
])
desc
=
"-:kprobes/%s"
%
ev_name
desc
=
"-:kprobes/%s"
%
ev_name
res
=
lib
.
bpf_detach_kprobe
(
desc
.
encode
(
"ascii"
))
res
=
lib
.
bpf_detach_kprobe
(
desc
.
encode
(
"ascii"
))
if
res
<
0
:
if
res
<
0
:
raise
Exception
(
"Failed to detach BPF from kprobe"
)
raise
Exception
(
"Failed to detach BPF from kprobe"
)
del
open_kprobes
[
ev_name
]
self
.
_del_kprobe
(
ev_name
)
def
attach_kretprobe
(
self
,
event
=
""
,
fn_name
=
""
,
event_re
=
""
,
def
attach_kretprobe
(
self
,
event
=
""
,
fn_name
=
""
,
event_re
=
""
,
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
assert
isinstance
(
event
,
str
),
"event must be a string"
# allow the caller to glob multiple functions together
# allow the caller to glob multiple functions together
if
event_re
:
if
event_re
:
for
line
in
BPF
.
_get_kprobe_functions
(
event_re
):
for
line
in
self
.
_get_kprobe_functions
(
event_re
):
try
:
try
:
self
.
attach_kretprobe
(
event
=
line
,
fn_name
=
fn_name
,
pid
=
pid
,
self
.
attach_kretprobe
(
event
=
line
,
fn_name
=
fn_name
,
pid
=
pid
,
cpu
=
cpu
,
group_fd
=
group_fd
)
cpu
=
cpu
,
group_fd
=
group_fd
)
...
@@ -426,7 +408,7 @@ class BPF(object):
...
@@ -426,7 +408,7 @@ class BPF(object):
pass
pass
return
return
_check_probe_quota
(
1
)
self
.
_check_probe_quota
(
1
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
ev_name
=
"r_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
ev_name
=
"r_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
desc
=
"r:kprobes/%s %s"
%
(
ev_name
,
event
)
desc
=
"r:kprobes/%s %s"
%
(
ev_name
,
event
)
...
@@ -436,20 +418,20 @@ class BPF(object):
...
@@ -436,20 +418,20 @@ class BPF(object):
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
if
not
res
:
if
not
res
:
raise
Exception
(
"Failed to attach BPF to kprobe"
)
raise
Exception
(
"Failed to attach BPF to kprobe"
)
open_kprobes
[
ev_name
]
=
res
self
.
_add_kprobe
(
ev_name
,
res
)
return
self
return
self
@
staticmethod
def
detach_kretprobe
(
self
,
event
):
def
detach_kretprobe
(
event
):
assert
isinstance
(
event
,
str
),
"event must be a string"
ev_name
=
"r_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
ev_name
=
"r_"
+
event
.
replace
(
"+"
,
"_"
).
replace
(
"."
,
"_"
)
if
ev_name
not
in
open_kprobes
:
if
ev_name
not
in
self
.
open_kprobes
:
raise
Exception
(
"Kretprobe %s is not attached"
%
event
)
raise
Exception
(
"Kretprobe %s is not attached"
%
event
)
lib
.
perf_reader_free
(
open_kprobes
[
ev_name
])
lib
.
perf_reader_free
(
self
.
open_kprobes
[
ev_name
])
desc
=
"-:kprobes/%s"
%
ev_name
desc
=
"-:kprobes/%s"
%
ev_name
res
=
lib
.
bpf_detach_kprobe
(
desc
.
encode
(
"ascii"
))
res
=
lib
.
bpf_detach_kprobe
(
desc
.
encode
(
"ascii"
))
if
res
<
0
:
if
res
<
0
:
raise
Exception
(
"Failed to detach BPF from kprobe"
)
raise
Exception
(
"Failed to detach BPF from kprobe"
)
del
open_kprobes
[
ev_name
]
self
.
_del_kprobe
(
ev_name
)
@
classmethod
@
classmethod
def
_check_path_symbol
(
cls
,
module
,
symname
,
addr
):
def
_check_path_symbol
(
cls
,
module
,
symname
,
addr
):
...
@@ -489,7 +471,7 @@ class BPF(object):
...
@@ -489,7 +471,7 @@ class BPF(object):
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
if
not
res
:
if
not
res
:
raise
Exception
(
"Failed to attach BPF to tracepoint"
)
raise
Exception
(
"Failed to attach BPF to tracepoint"
)
open_tracepoints
[
tp
]
=
res
self
.
open_tracepoints
[
tp
]
=
res
return
self
return
self
def
detach_tracepoint
(
self
,
tp
=
""
):
def
detach_tracepoint
(
self
,
tp
=
""
):
...
@@ -501,15 +483,25 @@ class BPF(object):
...
@@ -501,15 +483,25 @@ class BPF(object):
Example: bpf.detach_tracepoint("sched:sched_switch")
Example: bpf.detach_tracepoint("sched:sched_switch")
"""
"""
if
tp
not
in
open_tracepoints
:
if
tp
not
in
self
.
open_tracepoints
:
raise
Exception
(
"Tracepoint %s is not attached"
%
tp
)
raise
Exception
(
"Tracepoint %s is not attached"
%
tp
)
lib
.
perf_reader_free
(
open_tracepoints
[
tp
])
lib
.
perf_reader_free
(
self
.
open_tracepoints
[
tp
])
(
tp_category
,
tp_name
)
=
tp
.
split
(
':'
)
(
tp_category
,
tp_name
)
=
tp
.
split
(
':'
)
res
=
lib
.
bpf_detach_tracepoint
(
tp_category
.
encode
(
"ascii"
),
res
=
lib
.
bpf_detach_tracepoint
(
tp_category
.
encode
(
"ascii"
),
tp_name
.
encode
(
"ascii"
))
tp_name
.
encode
(
"ascii"
))
if
res
<
0
:
if
res
<
0
:
raise
Exception
(
"Failed to detach BPF from tracepoint"
)
raise
Exception
(
"Failed to detach BPF from tracepoint"
)
del
open_tracepoints
[
tp
]
del
self
.
open_tracepoints
[
tp
]
def
_add_uprobe
(
self
,
name
,
probe
):
global
_num_open_probes
self
.
open_uprobes
[
name
]
=
probe
_num_open_probes
+=
1
def
_del_uprobe
(
self
,
name
):
global
_num_open_probes
del
self
.
open_uprobes
[
name
]
_num_open_probes
-=
1
def
attach_uprobe
(
self
,
name
=
""
,
sym
=
""
,
addr
=
None
,
def
attach_uprobe
(
self
,
name
=
""
,
sym
=
""
,
addr
=
None
,
fn_name
=
""
,
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
fn_name
=
""
,
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
...
@@ -531,7 +523,7 @@ class BPF(object):
...
@@ -531,7 +523,7 @@ class BPF(object):
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
_check_probe_quota
(
1
)
self
.
_check_probe_quota
(
1
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
ev_name
=
"p_%s_0x%x"
%
(
self
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
ev_name
=
"p_%s_0x%x"
%
(
self
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
desc
=
"p:uprobes/%s %s:0x%x"
%
(
ev_name
,
path
,
addr
)
desc
=
"p:uprobes/%s %s:0x%x"
%
(
ev_name
,
path
,
addr
)
...
@@ -541,11 +533,10 @@ class BPF(object):
...
@@ -541,11 +533,10 @@ class BPF(object):
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
if
not
res
:
if
not
res
:
raise
Exception
(
"Failed to attach BPF to uprobe"
)
raise
Exception
(
"Failed to attach BPF to uprobe"
)
open_uprobes
[
ev_name
]
=
res
self
.
_add_uprobe
(
ev_name
,
res
)
return
self
return
self
@
classmethod
def
detach_uprobe
(
self
,
name
=
""
,
sym
=
""
,
addr
=
None
):
def
detach_uprobe
(
cls
,
name
=
""
,
sym
=
""
,
addr
=
None
):
"""detach_uprobe(name="", sym="", addr=None)
"""detach_uprobe(name="", sym="", addr=None)
Stop running a bpf function that is attached to symbol 'sym' in library
Stop running a bpf function that is attached to symbol 'sym' in library
...
@@ -553,15 +544,15 @@ class BPF(object):
...
@@ -553,15 +544,15 @@ class BPF(object):
"""
"""
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
ev_name
=
"p_%s_0x%x"
%
(
cls
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
ev_name
=
"p_%s_0x%x"
%
(
self
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
if
ev_name
not
in
open_uprobes
:
if
ev_name
not
in
self
.
open_uprobes
:
raise
Exception
(
"Uprobe %s is not attached"
%
event
)
raise
Exception
(
"Uprobe %s is not attached"
%
event
)
lib
.
perf_reader_free
(
open_uprobes
[
ev_name
])
lib
.
perf_reader_free
(
self
.
open_uprobes
[
ev_name
])
desc
=
"-:uprobes/%s"
%
ev_name
desc
=
"-:uprobes/%s"
%
ev_name
res
=
lib
.
bpf_detach_uprobe
(
desc
.
encode
(
"ascii"
))
res
=
lib
.
bpf_detach_uprobe
(
desc
.
encode
(
"ascii"
))
if
res
<
0
:
if
res
<
0
:
raise
Exception
(
"Failed to detach BPF from uprobe"
)
raise
Exception
(
"Failed to detach BPF from uprobe"
)
del
open_uprobes
[
ev_name
]
self
.
_del_uprobe
(
ev_name
)
def
attach_uretprobe
(
self
,
name
=
""
,
sym
=
""
,
addr
=
None
,
def
attach_uretprobe
(
self
,
name
=
""
,
sym
=
""
,
addr
=
None
,
fn_name
=
""
,
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
fn_name
=
""
,
pid
=-
1
,
cpu
=
0
,
group_fd
=-
1
):
...
@@ -575,7 +566,7 @@ class BPF(object):
...
@@ -575,7 +566,7 @@ class BPF(object):
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
_check_probe_quota
(
1
)
self
.
_check_probe_quota
(
1
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
fn
=
self
.
load_func
(
fn_name
,
BPF
.
KPROBE
)
ev_name
=
"r_%s_0x%x"
%
(
self
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
ev_name
=
"r_%s_0x%x"
%
(
self
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
desc
=
"r:uprobes/%s %s:0x%x"
%
(
ev_name
,
path
,
addr
)
desc
=
"r:uprobes/%s %s:0x%x"
%
(
ev_name
,
path
,
addr
)
...
@@ -585,11 +576,10 @@ class BPF(object):
...
@@ -585,11 +576,10 @@ class BPF(object):
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
res
=
ct
.
cast
(
res
,
ct
.
c_void_p
)
if
not
res
:
if
not
res
:
raise
Exception
(
"Failed to attach BPF to uprobe"
)
raise
Exception
(
"Failed to attach BPF to uprobe"
)
open_uprobes
[
ev_name
]
=
res
self
.
_add_uprobe
(
ev_name
,
res
)
return
self
return
self
@
classmethod
def
detach_uretprobe
(
self
,
name
=
""
,
sym
=
""
,
addr
=
None
):
def
detach_uretprobe
(
cls
,
name
=
""
,
sym
=
""
,
addr
=
None
):
"""detach_uretprobe(name="", sym="", addr=None)
"""detach_uretprobe(name="", sym="", addr=None)
Stop running a bpf function that is attached to symbol 'sym' in library
Stop running a bpf function that is attached to symbol 'sym' in library
...
@@ -597,23 +587,23 @@ class BPF(object):
...
@@ -597,23 +587,23 @@ class BPF(object):
"""
"""
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
(
path
,
addr
)
=
BPF
.
_check_path_symbol
(
name
,
sym
,
addr
)
ev_name
=
"r_%s_0x%x"
%
(
cls
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
ev_name
=
"r_%s_0x%x"
%
(
self
.
_probe_repl
.
sub
(
"_"
,
path
),
addr
)
if
ev_name
not
in
open_uprobes
:
if
ev_name
not
in
self
.
open_uprobes
:
raise
Exception
(
"Kretprobe %s is not attached"
%
event
)
raise
Exception
(
"Kretprobe %s is not attached"
%
event
)
lib
.
perf_reader_free
(
open_uprobes
[
ev_name
])
lib
.
perf_reader_free
(
self
.
open_uprobes
[
ev_name
])
desc
=
"-:uprobes/%s"
%
ev_name
desc
=
"-:uprobes/%s"
%
ev_name
res
=
lib
.
bpf_detach_uprobe
(
desc
.
encode
(
"ascii"
))
res
=
lib
.
bpf_detach_uprobe
(
desc
.
encode
(
"ascii"
))
if
res
<
0
:
if
res
<
0
:
raise
Exception
(
"Failed to detach BPF from uprobe"
)
raise
Exception
(
"Failed to detach BPF from uprobe"
)
del
open_uprobes
[
ev_name
]
self
.
_del_uprobe
(
ev_name
)
def
_trace_autoload
(
self
):
def
_trace_autoload
(
self
):
for
i
in
range
(
0
,
lib
.
bpf_num_functions
(
self
.
module
)):
for
i
in
range
(
0
,
lib
.
bpf_num_functions
(
self
.
module
)):
func_name
=
lib
.
bpf_function_name
(
self
.
module
,
i
)
.
decode
()
func_name
=
lib
.
bpf_function_name
(
self
.
module
,
i
)
if
len
(
open_kprobes
)
==
0
and
func_name
.
startswith
(
"kprobe__"
):
if
func_name
.
startswith
(
"kprobe__"
):
fn
=
self
.
load_func
(
func_name
,
BPF
.
KPROBE
)
fn
=
self
.
load_func
(
func_name
,
BPF
.
KPROBE
)
self
.
attach_kprobe
(
event
=
fn
.
name
[
8
:],
fn_name
=
fn
.
name
)
self
.
attach_kprobe
(
event
=
fn
.
name
[
8
:],
fn_name
=
fn
.
name
)
elif
len
(
open_kprobes
)
==
0
and
func_name
.
startswith
(
"kretprobe__"
):
elif
func_name
.
startswith
(
"kretprobe__"
):
fn
=
self
.
load_func
(
func_name
,
BPF
.
KPROBE
)
fn
=
self
.
load_func
(
func_name
,
BPF
.
KPROBE
)
self
.
attach_kretprobe
(
event
=
fn
.
name
[
11
:],
fn_name
=
fn
.
name
)
self
.
attach_kretprobe
(
event
=
fn
.
name
[
11
:],
fn_name
=
fn
.
name
)
elif
func_name
.
startswith
(
"tracepoint__"
):
elif
func_name
.
startswith
(
"tracepoint__"
):
...
@@ -626,14 +616,13 @@ class BPF(object):
...
@@ -626,14 +616,13 @@ class BPF(object):
Open the trace_pipe if not already open
Open the trace_pipe if not already open
"""
"""
global
tracefile
if
not
self
.
tracefile
:
if
not
tracefile
:
self
.
tracefile
=
open
(
"%s/trace_pipe"
%
TRACEFS
)
tracefile
=
open
(
"%s/trace_pipe"
%
TRACEFS
)
if
nonblocking
:
if
nonblocking
:
fd
=
tracefile
.
fileno
()
fd
=
self
.
tracefile
.
fileno
()
fl
=
fcntl
.
fcntl
(
fd
,
fcntl
.
F_GETFL
)
fl
=
fcntl
.
fcntl
(
fd
,
fcntl
.
F_GETFL
)
fcntl
.
fcntl
(
fd
,
fcntl
.
F_SETFL
,
fl
|
os
.
O_NONBLOCK
)
fcntl
.
fcntl
(
fd
,
fcntl
.
F_SETFL
,
fl
|
os
.
O_NONBLOCK
)
return
tracefile
return
self
.
tracefile
def
trace_fields
(
self
,
nonblocking
=
False
):
def
trace_fields
(
self
,
nonblocking
=
False
):
"""trace_fields(nonblocking=False)
"""trace_fields(nonblocking=False)
...
@@ -750,14 +739,14 @@ class BPF(object):
...
@@ -750,14 +739,14 @@ class BPF(object):
ksymaddr. Returns -1 when the function name is unknown."""
ksymaddr. Returns -1 when the function name is unknown."""
return
BPF
.
_sym_cache
(
-
1
).
resolve_name
(
name
)
return
BPF
.
_sym_cache
(
-
1
).
resolve_name
(
name
)
@
staticmethod
def
num_open_kprobes
(
self
):
def
num_open_kprobes
():
"""num_open_kprobes()
"""num_open_kprobes()
Get the number of open K[ret]probes. Can be useful for scenarios where
Get the number of open K[ret]probes. Can be useful for scenarios where
event_re is used while attaching and detaching probes
event_re is used while attaching and detaching probes. Excludes
perf_events readers.
"""
"""
return
len
(
open_kprobes
)
return
len
(
[
k
for
k
in
self
.
open_kprobes
.
keys
()
if
isinstance
(
k
,
str
)]
)
def
kprobe_poll
(
self
,
timeout
=
-
1
):
def
kprobe_poll
(
self
,
timeout
=
-
1
):
"""kprobe_poll(self)
"""kprobe_poll(self)
...
@@ -766,12 +755,33 @@ class BPF(object):
...
@@ -766,12 +755,33 @@ class BPF(object):
cb() that was given in the BPF constructor for each entry.
cb() that was given in the BPF constructor for each entry.
"""
"""
try
:
try
:
readers
=
(
ct
.
c_void_p
*
len
(
open_kprobes
))()
readers
=
(
ct
.
c_void_p
*
len
(
self
.
open_kprobes
))()
for
i
,
v
in
enumerate
(
open_kprobes
.
values
()):
for
i
,
v
in
enumerate
(
self
.
open_kprobes
.
values
()):
readers
[
i
]
=
v
readers
[
i
]
=
v
lib
.
perf_reader_poll
(
len
(
open_kprobes
),
readers
,
timeout
)
lib
.
perf_reader_poll
(
len
(
self
.
open_kprobes
),
readers
,
timeout
)
except
KeyboardInterrupt
:
except
KeyboardInterrupt
:
exit
()
exit
()
from
.usdt
import
USDTReader
def
cleanup
(
self
):
for
k
,
v
in
self
.
open_kprobes
.
items
():
lib
.
perf_reader_free
(
v
)
# non-string keys here include the perf_events reader
if
isinstance
(
k
,
str
):
desc
=
"-:kprobes/%s"
%
k
lib
.
bpf_detach_kprobe
(
desc
.
encode
(
"ascii"
))
self
.
_del_kprobe
(
k
)
for
k
,
v
in
self
.
open_uprobes
.
items
():
lib
.
perf_reader_free
(
v
)
desc
=
"-:uprobes/%s"
%
k
lib
.
bpf_detach_uprobe
(
desc
.
encode
(
"ascii"
))
self
.
_del_uprobe
(
k
)
for
k
,
v
in
self
.
open_tracepoints
.
items
():
lib
.
perf_reader_free
(
v
)
(
tp_category
,
tp_name
)
=
k
.
split
(
':'
)
lib
.
bpf_detach_tracepoint
(
tp_category
,
tp_name
)
self
.
open_tracepoints
.
clear
()
if
self
.
tracefile
:
self
.
tracefile
.
close
()
from
.usdt
import
USDTReader
src/python/bcc/table.py
View file @
b755c709
...
@@ -393,15 +393,15 @@ class PerfEventArray(ArrayBase):
...
@@ -393,15 +393,15 @@ class PerfEventArray(ArrayBase):
raise
Exception
(
"Could not open perf buffer"
)
raise
Exception
(
"Could not open perf buffer"
)
fd
=
lib
.
perf_reader_fd
(
reader
)
fd
=
lib
.
perf_reader_fd
(
reader
)
self
[
self
.
Key
(
cpu
)]
=
self
.
Leaf
(
fd
)
self
[
self
.
Key
(
cpu
)]
=
self
.
Leaf
(
fd
)
self
.
bpf
.
open_kprobes
()[(
id
(
self
),
cpu
)]
=
reader
self
.
bpf
.
_add_kprobe
((
id
(
self
),
cpu
),
reader
)
# keep a refcnt
# keep a refcnt
self
.
_cbs
[
cpu
]
=
fn
self
.
_cbs
[
cpu
]
=
fn
def
close_perf_buffer
(
self
,
key
):
def
close_perf_buffer
(
self
,
key
):
reader
=
self
.
bpf
.
open_kprobes
()
.
get
((
id
(
self
),
key
))
reader
=
self
.
bpf
.
open_kprobes
.
get
((
id
(
self
),
key
))
if
reader
:
if
reader
:
lib
.
perf_reader_free
(
reader
)
lib
.
perf_reader_free
(
reader
)
del
(
self
.
bpf
.
open_kprobes
()[(
id
(
self
),
key
)]
)
self
.
bpf
.
_del_kprobe
((
id
(
self
),
key
)
)
del
self
.
_cbs
[
key
]
del
self
.
_cbs
[
key
]
class
PerCpuHash
(
HashTable
):
class
PerCpuHash
(
HashTable
):
...
...
tests/python/test_histogram.py
View file @
b755c709
...
@@ -31,6 +31,7 @@ int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *
...
@@ -31,6 +31,7 @@ int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *
try
:
del
b
[
"stub"
][
c_ulonglong
(
1
<<
i
)]
try
:
del
b
[
"stub"
][
c_ulonglong
(
1
<<
i
)]
except
:
pass
except
:
pass
b
[
"hist1"
].
print_log2_hist
()
b
[
"hist1"
].
print_log2_hist
()
b
.
cleanup
()
def
test_struct
(
self
):
def
test_struct
(
self
):
b
=
BPF
(
text
=
"""
b
=
BPF
(
text
=
"""
...
@@ -52,6 +53,7 @@ int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *
...
@@ -52,6 +53,7 @@ int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *
try
:
del
b
[
"stub2"
][
c_ulonglong
(
1
<<
i
)]
try
:
del
b
[
"stub2"
][
c_ulonglong
(
1
<<
i
)]
except
:
pass
except
:
pass
b
[
"hist1"
].
print_log2_hist
()
b
[
"hist1"
].
print_log2_hist
()
b
.
cleanup
()
def
test_chars
(
self
):
def
test_chars
(
self
):
b
=
BPF
(
text
=
"""
b
=
BPF
(
text
=
"""
...
@@ -68,6 +70,7 @@ int kprobe__finish_task_switch(struct pt_regs *ctx, struct task_struct *prev) {
...
@@ -68,6 +70,7 @@ int kprobe__finish_task_switch(struct pt_regs *ctx, struct task_struct *prev) {
"""
)
"""
)
for
i
in
range
(
0
,
100
):
time
.
sleep
(
0.01
)
for
i
in
range
(
0
,
100
):
time
.
sleep
(
0.01
)
b
[
"hist1"
].
print_log2_hist
()
b
[
"hist1"
].
print_log2_hist
()
b
.
cleanup
()
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
...
...
tests/python/test_probe_count.py
View file @
b755c709
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
# Copyright (c) Suchakra Sharma <suchakrapani.sharma@polymtl.ca>
# Copyright (c) Suchakra Sharma <suchakrapani.sharma@polymtl.ca>
# Licensed under the Apache License, Version 2.0 (the "License")
# Licensed under the Apache License, Version 2.0 (the "License")
from
bcc
import
BPF
from
bcc
import
BPF
,
_get_num_open_probes
import
os
import
os
import
sys
import
sys
from
unittest
import
main
,
TestCase
from
unittest
import
main
,
TestCase
...
@@ -25,6 +25,39 @@ class TestKprobeCnt(TestCase):
...
@@ -25,6 +25,39 @@ class TestKprobeCnt(TestCase):
open_cnt
=
self
.
b
.
num_open_kprobes
()
open_cnt
=
self
.
b
.
num_open_kprobes
()
self
.
assertEqual
(
actual_cnt
,
open_cnt
)
self
.
assertEqual
(
actual_cnt
,
open_cnt
)
def
tearDown
(
self
):
self
.
b
.
cleanup
()
class
TestProbeGlobalCnt
(
TestCase
):
def
setUp
(
self
):
self
.
b1
=
BPF
(
text
=
"""int count(void *ctx) { return 0; }"""
)
self
.
b2
=
BPF
(
text
=
"""int count(void *ctx) { return 0; }"""
)
def
test_probe_quota
(
self
):
self
.
b1
.
attach_kprobe
(
event
=
"schedule"
,
fn_name
=
"count"
)
self
.
b2
.
attach_kprobe
(
event
=
"submit_bio"
,
fn_name
=
"count"
)
self
.
assertEqual
(
1
,
self
.
b1
.
num_open_kprobes
())
self
.
assertEqual
(
1
,
self
.
b2
.
num_open_kprobes
())
self
.
assertEqual
(
2
,
_get_num_open_probes
())
self
.
b1
.
cleanup
()
self
.
b2
.
cleanup
()
self
.
assertEqual
(
0
,
_get_num_open_probes
())
class
TestAutoKprobe
(
TestCase
):
def
setUp
(
self
):
self
.
b
=
BPF
(
text
=
"""
int kprobe__schedule(void *ctx) { return 0; }
int kretprobe__schedule(void *ctx) { return 0; }
"""
)
def
test_count
(
self
):
self
.
assertEqual
(
2
,
self
.
b
.
num_open_kprobes
())
def
tearDown
(
self
):
self
.
b
.
cleanup
()
class
TestProbeQuota
(
TestCase
):
class
TestProbeQuota
(
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
...
@@ -34,6 +67,10 @@ class TestProbeQuota(TestCase):
...
@@ -34,6 +67,10 @@ class TestProbeQuota(TestCase):
with
self
.
assertRaises
(
Exception
):
with
self
.
assertRaises
(
Exception
):
self
.
b
.
attach_kprobe
(
event_re
=
".*"
,
fn_name
=
"count"
)
self
.
b
.
attach_kprobe
(
event_re
=
".*"
,
fn_name
=
"count"
)
def
tearDown
(
self
):
self
.
b
.
cleanup
()
class
TestProbeNotExist
(
TestCase
):
class
TestProbeNotExist
(
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
b
=
BPF
(
text
=
"""int count(void *ctx) { return 0; }"""
)
self
.
b
=
BPF
(
text
=
"""int count(void *ctx) { return 0; }"""
)
...
@@ -42,6 +79,9 @@ class TestProbeNotExist(TestCase):
...
@@ -42,6 +79,9 @@ class TestProbeNotExist(TestCase):
with
self
.
assertRaises
(
Exception
):
with
self
.
assertRaises
(
Exception
):
b
.
attach_kprobe
(
event
=
"___doesnotexist"
,
fn_name
=
"count"
)
b
.
attach_kprobe
(
event
=
"___doesnotexist"
,
fn_name
=
"count"
)
def
tearDown
(
self
):
self
.
b
.
cleanup
()
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
main
()
main
()
tools/argdist.py
View file @
b755c709
...
@@ -640,8 +640,8 @@ struct __string_t { char s[%d]; };
...
@@ -640,8 +640,8 @@ struct __string_t { char s[%d]; };
for
probe
in
self
.
probes
:
for
probe
in
self
.
probes
:
probe
.
attach
(
self
.
bpf
)
probe
.
attach
(
self
.
bpf
)
if
self
.
args
.
verbose
:
if
self
.
args
.
verbose
:
print
(
"open uprobes: %s"
%
BPF
.
open_uprobes
()
)
print
(
"open uprobes: %s"
%
self
.
bpf
.
open_uprobes
)
print
(
"open kprobes: %s"
%
BPF
.
open_kprobes
()
)
print
(
"open kprobes: %s"
%
self
.
bpf
.
open_kprobes
)
def
_main_loop
(
self
):
def
_main_loop
(
self
):
count_so_far
=
0
count_so_far
=
0
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment