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
fafbf3ca
Commit
fafbf3ca
authored
Feb 27, 2018
by
Teng Qin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Do not use perf reader for TRACEPOINT events
parent
abef8350
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
232 additions
and
321 deletions
+232
-321
src/cc/api/BPF.cc
src/cc/api/BPF.cc
+18
-31
src/cc/api/BPF.h
src/cc/api/BPF.h
+4
-9
src/cc/libbpf.c
src/cc/libbpf.c
+54
-68
src/cc/libbpf.h
src/cc/libbpf.h
+7
-12
src/lua/bcc/bpf.lua
src/lua/bcc/bpf.lua
+32
-20
src/lua/bcc/libbcc.lua
src/lua/bcc/libbcc.lua
+6
-7
src/lua/bcc/table.lua
src/lua/bcc/table.lua
+1
-1
src/python/bcc/__init__.py
src/python/bcc/__init__.py
+100
-125
src/python/bcc/libbcc.py
src/python/bcc/libbcc.py
+6
-10
src/python/bcc/table.py
src/python/bcc/table.py
+4
-4
tests/python/CMakeLists.txt
tests/python/CMakeLists.txt
+0
-2
tests/python/test_callchain.py
tests/python/test_callchain.py
+0
-32
No files found.
src/cc/api/BPF.cc
View file @
fafbf3ca
...
...
@@ -159,8 +159,7 @@ StatusTuple BPF::detach_all() {
StatusTuple
BPF
::
attach_kprobe
(
const
std
::
string
&
kernel_func
,
const
std
::
string
&
probe_func
,
bpf_probe_attach_type
attach_type
,
perf_reader_cb
cb
,
void
*
cb_cookie
)
{
bpf_probe_attach_type
attach_type
)
{
std
::
string
probe_event
=
get_kprobe_event
(
kernel_func
,
attach_type
);
if
(
kprobes_
.
find
(
probe_event
)
!=
kprobes_
.
end
())
return
StatusTuple
(
-
1
,
"kprobe %s already attached"
,
probe_event
.
c_str
());
...
...
@@ -168,10 +167,10 @@ StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
int
probe_fd
;
TRY2
(
load_func
(
probe_func
,
BPF_PROG_TYPE_KPROBE
,
probe_fd
));
void
*
res
=
bpf_attach_kprobe
(
probe_fd
,
attach_type
,
probe_event
.
c_str
(),
kernel_func
.
c_str
(),
cb
,
cb_cookie
);
int
res_fd
=
bpf_attach_kprobe
(
probe_fd
,
attach_type
,
probe_event
.
c_str
(),
kernel_func
.
c_str
()
);
if
(
!
res
)
{
if
(
res_fd
<
0
)
{
TRY2
(
unload_func
(
probe_func
));
return
StatusTuple
(
-
1
,
"Unable to attach %skprobe for %s using %s"
,
attach_type_debug
(
attach_type
).
c_str
(),
...
...
@@ -179,7 +178,7 @@ StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
}
open_probe_t
p
=
{};
p
.
reader_ptr
=
res
;
p
.
perf_event_fd
=
res_fd
;
p
.
func
=
probe_func
;
kprobes_
[
probe_event
]
=
std
::
move
(
p
);
return
StatusTuple
(
0
);
...
...
@@ -189,8 +188,7 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
const
std
::
string
&
symbol
,
const
std
::
string
&
probe_func
,
uint64_t
symbol_addr
,
bpf_probe_attach_type
attach_type
,
pid_t
pid
,
perf_reader_cb
cb
,
void
*
cb_cookie
)
{
bpf_probe_attach_type
attach_type
,
pid_t
pid
)
{
std
::
string
module
;
uint64_t
offset
;
TRY2
(
check_binary_symbol
(
binary_path
,
symbol
,
symbol_addr
,
module
,
offset
));
...
...
@@ -202,11 +200,10 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
int
probe_fd
;
TRY2
(
load_func
(
probe_func
,
BPF_PROG_TYPE_KPROBE
,
probe_fd
));
void
*
res
=
bpf_attach_uprobe
(
probe_fd
,
attach_type
,
probe_event
.
c_str
(),
binary_path
.
c_str
(),
offset
,
pid
,
cb
,
cb_cookie
);
int
res_fd
=
bpf_attach_uprobe
(
probe_fd
,
attach_type
,
probe_event
.
c_str
(),
binary_path
.
c_str
(),
offset
,
pid
);
if
(
!
res
)
{
if
(
res_fd
<
0
)
{
TRY2
(
unload_func
(
probe_func
));
return
StatusTuple
(
-
1
,
...
...
@@ -216,7 +213,7 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
}
open_probe_t
p
=
{};
p
.
reader_ptr
=
res
;
p
.
perf_event_fd
=
res_fd
;
p
.
func
=
probe_func
;
uprobes_
[
probe_event
]
=
std
::
move
(
p
);
return
StatusTuple
(
0
);
...
...
@@ -253,8 +250,7 @@ StatusTuple BPF::attach_usdt(const USDT& usdt, pid_t pid) {
}
StatusTuple
BPF
::
attach_tracepoint
(
const
std
::
string
&
tracepoint
,
const
std
::
string
&
probe_func
,
perf_reader_cb
cb
,
void
*
cb_cookie
)
{
const
std
::
string
&
probe_func
)
{
if
(
tracepoints_
.
find
(
tracepoint
)
!=
tracepoints_
.
end
())
return
StatusTuple
(
-
1
,
"Tracepoint %s already attached"
,
tracepoint
.
c_str
());
...
...
@@ -268,17 +264,17 @@ StatusTuple BPF::attach_tracepoint(const std::string& tracepoint,
int
probe_fd
;
TRY2
(
load_func
(
probe_func
,
BPF_PROG_TYPE_TRACEPOINT
,
probe_fd
));
void
*
res
=
bpf_attach_tracepoint
(
probe_fd
,
tp_category
.
c_str
(),
tp_name
.
c_str
()
,
cb
,
cb_cookie
);
int
res_fd
=
bpf_attach_tracepoint
(
probe_fd
,
tp_category
.
c_str
(),
tp_name
.
c_str
());
if
(
!
res
)
{
if
(
res_fd
<
0
)
{
TRY2
(
unload_func
(
probe_func
));
return
StatusTuple
(
-
1
,
"Unable to attach Tracepoint %s using %s"
,
tracepoint
.
c_str
(),
probe_func
.
c_str
());
}
open_probe_t
p
=
{};
p
.
reader_ptr
=
res
;
p
.
perf_event_fd
=
res_fd
;
p
.
func
=
probe_func
;
tracepoints_
[
tracepoint
]
=
std
::
move
(
p
);
return
StatusTuple
(
0
);
...
...
@@ -558,10 +554,7 @@ std::string BPF::get_uprobe_event(const std::string& binary_path,
StatusTuple
BPF
::
detach_kprobe_event
(
const
std
::
string
&
event
,
open_probe_t
&
attr
)
{
if
(
attr
.
reader_ptr
)
{
perf_reader_free
(
attr
.
reader_ptr
);
attr
.
reader_ptr
=
nullptr
;
}
bpf_close_perf_event_fd
(
attr
.
perf_event_fd
);
TRY2
(
unload_func
(
attr
.
func
));
if
(
bpf_detach_kprobe
(
event
.
c_str
())
<
0
)
return
StatusTuple
(
-
1
,
"Unable to detach kprobe %s"
,
event
.
c_str
());
...
...
@@ -570,10 +563,7 @@ StatusTuple BPF::detach_kprobe_event(const std::string& event,
StatusTuple
BPF
::
detach_uprobe_event
(
const
std
::
string
&
event
,
open_probe_t
&
attr
)
{
if
(
attr
.
reader_ptr
)
{
perf_reader_free
(
attr
.
reader_ptr
);
attr
.
reader_ptr
=
nullptr
;
}
bpf_close_perf_event_fd
(
attr
.
perf_event_fd
);
TRY2
(
unload_func
(
attr
.
func
));
if
(
bpf_detach_uprobe
(
event
.
c_str
())
<
0
)
return
StatusTuple
(
-
1
,
"Unable to detach uprobe %s"
,
event
.
c_str
());
...
...
@@ -582,10 +572,7 @@ StatusTuple BPF::detach_uprobe_event(const std::string& event,
StatusTuple
BPF
::
detach_tracepoint_event
(
const
std
::
string
&
tracepoint
,
open_probe_t
&
attr
)
{
if
(
attr
.
reader_ptr
)
{
perf_reader_free
(
attr
.
reader_ptr
);
attr
.
reader_ptr
=
nullptr
;
}
bpf_close_perf_event_fd
(
attr
.
perf_event_fd
);
TRY2
(
unload_func
(
attr
.
func
));
// TODO: bpf_detach_tracepoint currently does nothing.
...
...
src/cc/api/BPF.h
View file @
fafbf3ca
...
...
@@ -34,7 +34,7 @@ static const int DEFAULT_PERF_BUFFER_PAGE_CNT = 8;
namespace
ebpf
{
struct
open_probe_t
{
void
*
reader_ptr
;
int
perf_event_fd
;
std
::
string
func
;
std
::
map
<
int
,
int
>*
per_cpu_fd
;
};
...
...
@@ -57,9 +57,7 @@ class BPF {
StatusTuple
attach_kprobe
(
const
std
::
string
&
kernel_func
,
const
std
::
string
&
probe_func
,
bpf_probe_attach_type
=
BPF_PROBE_ENTRY
,
perf_reader_cb
cb
=
nullptr
,
void
*
cb_cookie
=
nullptr
);
bpf_probe_attach_type
=
BPF_PROBE_ENTRY
);
StatusTuple
detach_kprobe
(
const
std
::
string
&
kernel_func
,
bpf_probe_attach_type
attach_type
=
BPF_PROBE_ENTRY
);
...
...
@@ -69,8 +67,7 @@ class BPF {
const
std
::
string
&
probe_func
,
uint64_t
symbol_addr
=
0
,
bpf_probe_attach_type
attach_type
=
BPF_PROBE_ENTRY
,
pid_t
pid
=
-
1
,
perf_reader_cb
cb
=
nullptr
,
void
*
cb_cookie
=
nullptr
);
pid_t
pid
=
-
1
);
StatusTuple
detach_uprobe
(
const
std
::
string
&
binary_path
,
const
std
::
string
&
symbol
,
uint64_t
symbol_addr
=
0
,
bpf_probe_attach_type
attach_type
=
BPF_PROBE_ENTRY
,
...
...
@@ -79,9 +76,7 @@ class BPF {
StatusTuple
detach_usdt
(
const
USDT
&
usdt
);
StatusTuple
attach_tracepoint
(
const
std
::
string
&
tracepoint
,
const
std
::
string
&
probe_func
,
perf_reader_cb
cb
=
nullptr
,
void
*
cb_cookie
=
nullptr
);
const
std
::
string
&
probe_func
);
StatusTuple
detach_tracepoint
(
const
std
::
string
&
tracepoint
);
StatusTuple
attach_perf_event
(
uint32_t
ev_type
,
uint32_t
ev_config
,
...
...
src/cc/libbpf.c
View file @
fafbf3ca
...
...
@@ -151,8 +151,6 @@ static struct bpf_helper helpers[] = {
{
"sock_ops_cb_flags_set"
,
"4.16"
},
};
static
int
probe_perf_reader_page_cnt
=
8
;
static
uint64_t
ptr_to_u64
(
void
*
ptr
)
{
return
(
uint64_t
)
(
unsigned
long
)
ptr
;
...
...
@@ -682,7 +680,6 @@ static int bpf_try_perf_event_open_with_probe(const char *name, uint64_t offs,
if
(
type
<
0
||
is_return_bit
<
0
)
return
-
1
;
attr
.
sample_type
=
PERF_SAMPLE_RAW
|
PERF_SAMPLE_CALLCHAIN
;
attr
.
sample_period
=
1
;
attr
.
wakeup_events
=
1
;
if
(
is_return
)
...
...
@@ -724,16 +721,23 @@ static int bpf_try_perf_event_open_with_probe(const char *name, uint64_t offs,
PERF_FLAG_FD_CLOEXEC
);
}
static
int
bpf_attach_tracing_event
(
int
progfd
,
const
char
*
event_path
,
struct
perf_reader
*
reader
,
int
pid
,
int
pfd
)
// When a valid Perf Event FD provided through pfd, it will be used to enable
// and attach BPF program to the event, and event_path will be ignored.
// Otherwise, event_path is expected to contain the path to the event in debugfs
// and it will be used to open the Perf Event FD.
// In either case, if the attach partially failed (such as issue with the
// ioctl operations), the **caller** need to clean up the Perf Event FD, either
// provided by the caller or opened here.
static
int
bpf_attach_tracing_event
(
int
progfd
,
const
char
*
event_path
,
int
pid
,
int
*
pfd
)
{
int
efd
,
cpu
=
0
;
ssize_t
bytes
;
char
buf
[
PATH_MAX
];
struct
perf_event_attr
attr
=
{};
if
(
pfd
<
0
)
{
// Caller did not provided a valid Perf Event FD. Create one with the debugfs
// event path provided.
if
(
*
pfd
<
0
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"%s/id"
,
event_path
);
efd
=
open
(
buf
,
O_RDONLY
,
0
);
if
(
efd
<
0
)
{
...
...
@@ -751,7 +755,6 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
buf
[
bytes
]
=
'\0'
;
attr
.
config
=
strtol
(
buf
,
NULL
,
0
);
attr
.
type
=
PERF_TYPE_TRACEPOINT
;
attr
.
sample_type
=
PERF_SAMPLE_RAW
|
PERF_SAMPLE_CALLCHAIN
;
attr
.
sample_period
=
1
;
attr
.
wakeup_events
=
1
;
// PID filter is only possible for uprobe events.
...
...
@@ -762,22 +765,18 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
// Tracing events do not do CPU filtering in any cases.
if
(
pid
!=
-
1
)
cpu
=
-
1
;
pfd
=
syscall
(
__NR_perf_event_open
,
&
attr
,
pid
,
cpu
,
-
1
/* group_fd */
,
PERF_FLAG_FD_CLOEXEC
);
if
(
pfd
<
0
)
{
*
pfd
=
syscall
(
__NR_perf_event_open
,
&
attr
,
pid
,
cpu
,
-
1
/* group_fd */
,
PERF_FLAG_FD_CLOEXEC
);
if
(
*
pfd
<
0
)
{
fprintf
(
stderr
,
"perf_event_open(%s/id): %s
\n
"
,
event_path
,
strerror
(
errno
));
return
-
1
;
}
}
perf_reader_set_fd
(
reader
,
pfd
);
if
(
perf_reader_mmap
(
reader
,
attr
.
type
,
attr
.
sample_type
)
<
0
)
return
-
1
;
if
(
ioctl
(
pfd
,
PERF_EVENT_IOC_SET_BPF
,
progfd
)
<
0
)
{
if
(
ioctl
(
*
pfd
,
PERF_EVENT_IOC_SET_BPF
,
progfd
)
<
0
)
{
perror
(
"ioctl(PERF_EVENT_IOC_SET_BPF)"
);
return
-
1
;
}
if
(
ioctl
(
pfd
,
PERF_EVENT_IOC_ENABLE
,
0
)
<
0
)
{
if
(
ioctl
(
*
pfd
,
PERF_EVENT_IOC_ENABLE
,
0
)
<
0
)
{
perror
(
"ioctl(PERF_EVENT_IOC_ENABLE)"
);
return
-
1
;
}
...
...
@@ -785,24 +784,19 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
return
0
;
}
void
*
bpf_attach_kprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
fn_name
,
perf_reader_cb
cb
,
void
*
cb_cookie
)
int
bpf_attach_kprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
fn_name
)
{
int
kfd
;
int
pfd
;
int
kfd
,
pfd
=
-
1
;
char
buf
[
256
];
char
event_alias
[
128
];
struct
perf_reader
*
reader
=
NULL
;
static
char
*
event_type
=
"kprobe"
;
reader
=
perf_reader_new
(
cb
,
NULL
,
NULL
,
cb_cookie
,
probe_perf_reader_page_cnt
);
if
(
!
reader
)
goto
error
;
// Try create the kprobe Perf Event with perf_event_open API.
pfd
=
bpf_try_perf_event_open_with_probe
(
fn_name
,
0
,
-
1
,
event_type
,
attach_type
!=
BPF_PROBE_ENTRY
);
// If failed, most likely Kernel doesn't support the new perf_event_open API
// yet. Try create the event using debugfs.
if
(
pfd
<
0
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/%s_events"
,
event_type
);
kfd
=
open
(
buf
,
O_WRONLY
|
O_APPEND
,
0
);
...
...
@@ -823,15 +817,16 @@ void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
close
(
kfd
);
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/events/%ss/%s"
,
event_type
,
event_alias
);
}
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
reader
,
-
1
/* PID */
,
pfd
)
<
0
)
goto
error
;
return
reader
;
// If perf_event_open succeeded, bpf_attach_tracing_event will use the created
// Perf Event FD directly and buf would be empty and unused.
// Otherwise it will read the event ID from the path in buf, create the
// Perf Event event using that ID, and updated value of pfd.
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
-
1
/* PID */
,
&
pfd
)
==
0
)
return
pfd
;
error:
perf_reader_free
(
reader
);
return
NULL
;
bpf_close_perf_event_fd
(
pfd
);
return
-
1
;
}
static
int
enter_mount_ns
(
int
pid
)
{
...
...
@@ -895,24 +890,19 @@ static void exit_mount_ns(int fd) {
perror
(
"setns"
);
}
void
*
bpf_attach_uprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
binary_path
,
uint64_t
offset
,
pid_t
pid
,
perf_reader_cb
cb
,
void
*
cb_cookie
)
int
bpf_attach_uprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
binary_path
,
uint64_t
offset
,
pid_t
pid
)
{
char
buf
[
PATH_MAX
];
char
event_alias
[
PATH_MAX
];
struct
perf_reader
*
reader
=
NULL
;
static
char
*
event_type
=
"uprobe"
;
int
res
,
kfd
=
-
1
,
ns_fd
=
-
1
;
int
pfd
;
reader
=
perf_reader_new
(
cb
,
NULL
,
NULL
,
cb_cookie
,
probe_perf_reader_page_cnt
);
if
(
!
reader
)
goto
error
;
int
res
,
kfd
=
-
1
,
pfd
=
-
1
,
ns_fd
=
-
1
;
// Try create the uprobe Perf Event with perf_event_open API.
pfd
=
bpf_try_perf_event_open_with_probe
(
binary_path
,
offset
,
pid
,
event_type
,
attach_type
!=
BPF_PROBE_ENTRY
);
// If failed, most likely Kernel doesn't support the new perf_event_open API
// yet. Try create the event using debugfs.
if
(
pfd
<
0
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/%s_events"
,
event_type
);
kfd
=
open
(
buf
,
O_WRONLY
|
O_APPEND
,
0
);
...
...
@@ -940,22 +930,25 @@ void *bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
goto
error
;
}
close
(
kfd
);
kfd
=
-
1
;
exit_mount_ns
(
ns_fd
);
ns_fd
=
-
1
;
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/events/%ss/%s"
,
event_type
,
event_alias
);
}
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
reader
,
pid
,
pfd
)
<
0
)
goto
error
;
return
reader
;
// If perf_event_open succeeded, bpf_attach_tracing_event will use the created
// Perf Event FD directly and buf would be empty and unused.
// Otherwise it will read the event ID from the path in buf, create the
// Perf Event event using that ID, and updated value of pfd.
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
pid
,
&
pfd
)
==
0
)
return
pfd
;
error:
if
(
kfd
>=
0
)
close
(
kfd
);
exit_mount_ns
(
ns_fd
);
perf_reader_free
(
reader
);
return
NULL
;
bpf_close_perf_event_fd
(
pfd
);
return
-
1
;
}
static
int
bpf_detach_probe
(
const
char
*
ev_name
,
const
char
*
event_type
)
...
...
@@ -1036,26 +1029,19 @@ int bpf_detach_uprobe(const char *ev_name)
}
void
*
bpf_attach_tracepoint
(
int
progfd
,
const
char
*
tp_category
,
const
char
*
tp_name
,
perf_reader_cb
cb
,
void
*
cb_cookie
)
{
int
bpf_attach_tracepoint
(
int
progfd
,
const
char
*
tp_category
,
const
char
*
tp_name
)
{
char
buf
[
256
];
struct
perf_reader
*
reader
=
NULL
;
reader
=
perf_reader_new
(
cb
,
NULL
,
NULL
,
cb_cookie
,
probe_perf_reader_page_cnt
);
if
(
!
reader
)
goto
error
;
int
pfd
=
-
1
;
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/events/%s/%s"
,
tp_category
,
tp_name
);
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
reader
,
-
1
/* PID */
,
-
1
/* pfd */
)
<
0
)
goto
error
;
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
-
1
/* PID */
,
&
pfd
)
==
0
)
return
pfd
;
return
reader
;
error:
perf_reader_free
(
reader
);
return
NULL
;
bpf_close_perf_event_fd
(
pfd
);
return
-
1
;
}
int
bpf_detach_tracepoint
(
const
char
*
tp_category
,
const
char
*
tp_name
)
{
...
...
src/cc/libbpf.h
View file @
fafbf3ca
...
...
@@ -70,22 +70,17 @@ typedef void (*perf_reader_cb)(void *cb_cookie, int pid, uint64_t callchain_num,
typedef
void
(
*
perf_reader_raw_cb
)(
void
*
cb_cookie
,
void
*
raw
,
int
raw_size
);
typedef
void
(
*
perf_reader_lost_cb
)(
void
*
cb_cookie
,
uint64_t
lost
);
void
*
bpf_attach_kprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
fn_name
,
perf_reader_cb
cb
,
void
*
cb_cookie
);
int
bpf_attach_kprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
fn_name
);
int
bpf_detach_kprobe
(
const
char
*
ev_name
);
void
*
bpf_attach_uprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
binary_path
,
uint64_t
offset
,
pid_t
pid
,
perf_reader_cb
cb
,
void
*
cb_cookie
);
int
bpf_attach_uprobe
(
int
progfd
,
enum
bpf_probe_attach_type
attach_type
,
const
char
*
ev_name
,
const
char
*
binary_path
,
uint64_t
offset
,
pid_t
pid
);
int
bpf_detach_uprobe
(
const
char
*
ev_name
);
void
*
bpf_attach_tracepoint
(
int
progfd
,
const
char
*
tp_category
,
const
char
*
tp_name
,
perf_reader_cb
cb
,
void
*
cb_cookie
);
int
bpf_attach_tracepoint
(
int
progfd
,
const
char
*
tp_category
,
const
char
*
tp_name
);
int
bpf_detach_tracepoint
(
const
char
*
tp_category
,
const
char
*
tp_name
);
void
*
bpf_open_perf_buffer
(
perf_reader_raw_cb
raw_cb
,
...
...
src/lua/bcc/bpf.lua
View file @
fafbf3ca
...
...
@@ -24,6 +24,7 @@ local Bpf = class("BPF")
Bpf
.
static
.
open_kprobes
=
{}
Bpf
.
static
.
open_uprobes
=
{}
Bpf
.
static
.
perf_buffers
=
{}
Bpf
.
static
.
KPROBE_LIMIT
=
1000
Bpf
.
static
.
tracer_pipe
=
nil
Bpf
.
static
.
DEFAULT_CFLAGS
=
{
...
...
@@ -39,8 +40,8 @@ end
function
Bpf
.
static
.
cleanup
()
local
function
detach_all
(
probe_type
,
all_probes
)
for
key
,
probe
in
pairs
(
all_probes
)
do
libbcc
.
perf_reader_free
(
probe
)
for
key
,
fd
in
pairs
(
all_probes
)
do
libbcc
.
bpf_close_perf_event_fd
(
fd
)
-- skip bcc-specific kprobes
if
not
key
:
starts
(
"bcc:"
)
then
if
probe_type
==
"kprobes"
then
...
...
@@ -55,6 +56,12 @@ function Bpf.static.cleanup()
detach_all
(
"kprobes"
,
Bpf
.
static
.
open_kprobes
)
detach_all
(
"uprobes"
,
Bpf
.
static
.
open_uprobes
)
for
key
,
perf_buffer
in
pairs
(
Bpf
.
static
.
perf_buffers
)
do
libbcc
.
perf_reader_free
(
perf_buffer
)
Bpf
.
static
.
perf_buffers
[
key
]
=
nil
end
if
Bpf
.
static
.
tracer_pipe
~=
nil
then
Bpf
.
static
.
tracer_pipe
:
close
()
end
...
...
@@ -189,9 +196,9 @@ function Bpf:attach_uprobe(args)
local
retprobe
=
args
.
retprobe
and
1
or
0
local
res
=
libbcc
.
bpf_attach_uprobe
(
fn
.
fd
,
retprobe
,
ev_name
,
path
,
addr
,
args
.
pid
or
-
1
,
nil
,
nil
)
-- TODO; reader callback
args
.
pid
or
-
1
)
assert
(
res
~=
nil
,
"failed to attach BPF to uprobe"
)
assert
(
res
>=
0
,
"failed to attach BPF to uprobe"
)
self
:
probe_store
(
"uprobe"
,
ev_name
,
res
)
return
self
end
...
...
@@ -206,10 +213,9 @@ function Bpf:attach_kprobe(args)
local
ev_name
=
string.format
(
"%s_%s"
,
ptype
,
event
:
gsub
(
"
[
%+%.
]
"
,
"_"
))
local
retprobe
=
args
.
retprobe
and
1
or
0
local
res
=
libbcc
.
bpf_attach_kprobe
(
fn
.
fd
,
retprobe
,
ev_name
,
event
,
nil
,
nil
)
-- TODO; reader callback
local
res
=
libbcc
.
bpf_attach_kprobe
(
fn
.
fd
,
retprobe
,
ev_name
,
event
)
assert
(
res
~=
nil
,
"failed to attach BPF to kprobe"
)
assert
(
res
>=
0
,
"failed to attach BPF to kprobe"
)
self
:
probe_store
(
"kprobe"
,
ev_name
,
res
)
return
self
end
...
...
@@ -228,16 +234,22 @@ function Bpf:get_table(name, key_type, leaf_type)
return
self
.
tables
[
name
]
end
function
Bpf
:
probe_store
(
t
,
id
,
reader
)
function
Bpf
:
probe_store
(
t
,
id
,
fd
)
if
t
==
"kprobe"
then
Bpf
.
open_kprobes
[
id
]
=
reader
Bpf
.
open_kprobes
[
id
]
=
fd
elseif
t
==
"uprobe"
then
Bpf
.
open_uprobes
[
id
]
=
reader
Bpf
.
open_uprobes
[
id
]
=
fd
else
error
(
"unknown probe type '%s'"
%
t
)
end
log
.
info
(
"%s -> %s"
,
id
,
reader
)
log
.
info
(
"%s -> %s"
,
id
,
fd
)
end
function
Bpf
:
perf_buffer_store
(
t
,
id
,
reader
)
Bpf
.
perf_buffers
[
id
]
=
reader
log
.
info
(
"%s -> %s"
,
id
,
fd
)
end
function
Bpf
:
probe_lookup
(
t
,
id
)
...
...
@@ -250,32 +262,32 @@ function Bpf:probe_lookup(t, id)
end
end
function
Bpf
:
_
kprobe
_array
()
local
kprobe_count
=
table
.
count
(
Bpf
.
open_kprobe
s
)
local
readers
=
ffi
.
new
(
"struct perf_reader*[?]"
,
kprobe
_count
)
function
Bpf
:
_
perf_buffer
_array
()
local
perf_buffer_count
=
table
.
count
(
Bpf
.
perf_buffer
s
)
local
readers
=
ffi
.
new
(
"struct perf_reader*[?]"
,
perf_buffer
_count
)
local
n
=
0
for
_
,
r
in
pairs
(
Bpf
.
open_kprobe
s
)
do
for
_
,
r
in
pairs
(
Bpf
.
perf_buffer
s
)
do
readers
[
n
]
=
r
n
=
n
+
1
end
assert
(
n
==
kprobe
_count
)
assert
(
n
==
perf_buffer
_count
)
return
readers
,
n
end
function
Bpf
:
kprobe_poll_loop
()
local
p
robes
,
probe_count
=
self
:
_kprobe
_array
()
local
p
erf_buffer
,
perf_buffer_count
=
self
:
_perf_buffer
_array
()
return
pcall
(
function
()
while
true
do
libbcc
.
perf_reader_poll
(
p
robe_count
,
probe
s
,
-
1
)
libbcc
.
perf_reader_poll
(
p
erf_buffer_count
,
perf_buffer
s
,
-
1
)
end
end
)
end
function
Bpf
:
kprobe_poll
(
timeout
)
local
p
robes
,
probe_count
=
self
:
_kprobe
_array
()
libbcc
.
perf_reader_poll
(
p
robe_count
,
probe
s
,
timeout
or
-
1
)
local
p
erf_buffer
,
perf_buffer_count
=
self
:
_perf_buffer
_array
()
libbcc
.
perf_reader_poll
(
p
erf_buffer_count
,
perf_buffer
s
,
timeout
or
-
1
)
end
return
Bpf
src/lua/bcc/libbcc.lua
View file @
fafbf3ca
...
...
@@ -39,23 +39,22 @@ int bpf_attach_socket(int sockfd, int progfd);
/* create RAW socket and bind to interface 'name' */
int bpf_open_raw_sock(const char *name);
typedef void (*perf_reader_cb)(void *cb_cookie, int pid, uint64_t callchain_num, void *callchain);
typedef void (*perf_reader_raw_cb)(void *cb_cookie, void *raw, int raw_size);
typedef void (*perf_reader_lost_cb)(void *cb_cookie, uint64_t lost);
void *bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
const char *fn_name, perf_reader_cb cb,
void *cb_cookie);
int bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
const char *fn_name);
int bpf_detach_kprobe(const char *ev_name);
void *bpf_attach_uprobe(int progfd, int attach_type, const char *ev_name,
const char *binary_path, uint64_t offset, int pid,
perf_reader_cb cb, void *cb_cookie);
int bpf_attach_uprobe(int progfd, int attach_type, const char *ev_name,
const char *binary_path, uint64_t offset, int pid);
int bpf_detach_uprobe(const char *ev_name);
void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, perf_reader_lost_cb lost_cb, void *cb_cookie, int pid, int cpu, int page_cnt);
int bpf_close_perf_event_fd(int fd);
]]
ffi
.
cdef
[[
...
...
src/lua/bcc/table.lua
View file @
fafbf3ca
...
...
@@ -263,7 +263,7 @@ function PerfEventArray:_open_perf_buffer(cpu, callback, ctype, page_cnt, lost_c
local
fd
=
libbcc
.
perf_reader_fd
(
reader
)
self
:
set
(
cpu
,
fd
)
self
.
bpf
:
p
robe_store
(
"kprobe"
,
_perf_id
(
self
.
map_id
,
cpu
),
reader
)
self
.
bpf
:
p
erf_buffer_store
(
_perf_id
(
self
.
map_id
,
cpu
),
reader
)
self
.
_callbacks
[
cpu
]
=
_cb
end
...
...
src/python/bcc/__init__.py
View file @
fafbf3ca
This diff is collapsed.
Click to expand it.
src/python/bcc/libbcc.py
View file @
fafbf3ca
...
...
@@ -85,23 +85,19 @@ lib.bpf_attach_socket.argtypes = [ct.c_int, ct.c_int]
lib
.
bpf_prog_load
.
restype
=
ct
.
c_int
lib
.
bpf_prog_load
.
argtypes
=
[
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_void_p
,
ct
.
c_size_t
,
ct
.
c_char_p
,
ct
.
c_uint
,
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_uint
]
lib
.
bpf_attach_kprobe
.
restype
=
ct
.
c_void_p
_CB_TYPE
=
ct
.
CFUNCTYPE
(
None
,
ct
.
py_object
,
ct
.
c_int
,
ct
.
c_ulonglong
,
ct
.
POINTER
(
ct
.
c_ulonglong
))
_RAW_CB_TYPE
=
ct
.
CFUNCTYPE
(
None
,
ct
.
py_object
,
ct
.
c_void_p
,
ct
.
c_int
)
_LOST_CB_TYPE
=
ct
.
CFUNCTYPE
(
None
,
ct
.
py_object
,
ct
.
c_ulonglong
)
lib
.
bpf_attach_kprobe
.
argtypes
=
[
ct
.
c_int
,
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_char_p
,
_CB_TYPE
,
ct
.
py_object
]
lib
.
bpf_attach_kprobe
.
restype
=
ct
.
c_int
lib
.
bpf_attach_kprobe
.
argtypes
=
[
ct
.
c_int
,
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_char_p
]
lib
.
bpf_detach_kprobe
.
restype
=
ct
.
c_int
lib
.
bpf_detach_kprobe
.
argtypes
=
[
ct
.
c_char_p
]
lib
.
bpf_attach_uprobe
.
restype
=
ct
.
c_
void_p
lib
.
bpf_attach_uprobe
.
restype
=
ct
.
c_
int
lib
.
bpf_attach_uprobe
.
argtypes
=
[
ct
.
c_int
,
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_char_p
,
ct
.
c_ulonglong
,
ct
.
c_int
,
_CB_TYPE
,
ct
.
py_object
]
ct
.
c_ulonglong
,
ct
.
c_int
]
lib
.
bpf_detach_uprobe
.
restype
=
ct
.
c_int
lib
.
bpf_detach_uprobe
.
argtypes
=
[
ct
.
c_char_p
]
lib
.
bpf_attach_tracepoint
.
restype
=
ct
.
c_void_p
lib
.
bpf_attach_tracepoint
.
argtypes
=
[
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_char_p
,
_CB_TYPE
,
ct
.
py_object
]
lib
.
bpf_attach_tracepoint
.
restype
=
ct
.
c_int
lib
.
bpf_attach_tracepoint
.
argtypes
=
[
ct
.
c_int
,
ct
.
c_char_p
,
ct
.
c_char_p
]
lib
.
bpf_detach_tracepoint
.
restype
=
ct
.
c_int
lib
.
bpf_detach_tracepoint
.
argtypes
=
[
ct
.
c_char_p
,
ct
.
c_char_p
]
lib
.
bpf_open_perf_buffer
.
restype
=
ct
.
c_void_p
...
...
src/python/bcc/table.py
View file @
fafbf3ca
...
...
@@ -494,10 +494,10 @@ class PerfEventArray(ArrayBase):
# Delete entry from the array
super
(
PerfEventArray
,
self
).
__delitem__
(
key
)
key_id
=
(
id
(
self
),
key
)
if
key_id
in
self
.
bpf
.
open_kprobe
s
:
if
key_id
in
self
.
bpf
.
perf_buffer
s
:
# The key is opened for perf ring buffer
lib
.
perf_reader_free
(
self
.
bpf
.
open_kprobe
s
[
key_id
])
self
.
bpf
.
_del_kprobe
(
key_id
)
lib
.
perf_reader_free
(
self
.
bpf
.
perf_buffer
s
[
key_id
])
del
self
.
bpf
.
perf_buffers
[
key_id
]
del
self
.
_cbs
[
key
]
else
:
# The key is opened for perf event read
...
...
@@ -544,7 +544,7 @@ class PerfEventArray(ArrayBase):
raise
Exception
(
"Could not open perf buffer"
)
fd
=
lib
.
perf_reader_fd
(
reader
)
self
[
self
.
Key
(
cpu
)]
=
self
.
Leaf
(
fd
)
self
.
bpf
.
_add_kprobe
((
id
(
self
),
cpu
),
reader
)
self
.
bpf
.
perf_buffers
[(
id
(
self
),
cpu
)]
=
reader
# keep a refcnt
self
.
_cbs
[
cpu
]
=
(
fn
,
lost_fn
)
# The actual fd is held by the perf reader, add to track opened keys
...
...
tests/python/CMakeLists.txt
View file @
fafbf3ca
...
...
@@ -46,8 +46,6 @@ add_test(NAME py_test_clang WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND
${
TEST_WRAPPER
}
py_clang sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_clang.py
)
add_test
(
NAME py_test_histogram WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
COMMAND
${
TEST_WRAPPER
}
py_histogram sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_histogram.py
)
add_test
(
NAME py_test_callchain WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
COMMAND
${
TEST_WRAPPER
}
py_callchain sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_callchain.py
)
add_test
(
NAME py_array WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
COMMAND
${
TEST_WRAPPER
}
py_array sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_array.py
)
add_test
(
NAME py_uprobes WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
...
...
tests/python/test_callchain.py
deleted
100755 → 0
View file @
abef8350
#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from
bcc
import
BPF
import
time
from
unittest
import
main
,
TestCase
class
TestCallchain
(
TestCase
):
def
test_callchain1
(
self
):
hist
=
{}
def
cb
(
pid
,
callchain
):
counter
=
hist
.
get
(
callchain
,
0
)
counter
+=
1
hist
[
callchain
]
=
counter
b
=
BPF
(
text
=
"""
#include <linux/ptrace.h>
int kprobe__finish_task_switch(struct pt_regs *ctx) {
return 1;
}
"""
,
cb
=
cb
)
start
=
time
.
time
()
while
time
.
time
()
<
start
+
1
:
b
.
kprobe_poll
()
for
k
,
v
in
hist
.
items
():
syms
=
[
b
.
ksym
(
addr
)
for
addr
in
k
]
print
(
"%-08d:"
%
v
,
syms
)
if
__name__
==
"__main__"
:
main
()
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