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
f654c792
Commit
f654c792
authored
Jan 10, 2018
by
yonghong-song
Committed by
GitHub
Jan 10, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1518 from liu-song-6/perf_event_open_v02
Try use new API to create [k,u]probe with perf_event_open
parents
3558d5a8
0e9ed200
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
225 additions
and
69 deletions
+225
-69
src/cc/libbpf.c
src/cc/libbpf.c
+225
-69
No files found.
src/cc/libbpf.c
View file @
f654c792
...
...
@@ -536,13 +536,121 @@ int bpf_attach_socket(int sock, int prog) {
return
setsockopt
(
sock
,
SOL_SOCKET
,
SO_ATTACH_BPF
,
&
prog
,
sizeof
(
prog
));
}
#define PMU_TYPE_FILE "/sys/bus/event_source/devices/%s/type"
static
int
bpf_find_probe_type
(
const
char
*
event_type
)
{
int
fd
;
int
ret
;
char
buf
[
PATH_MAX
];
ret
=
snprintf
(
buf
,
sizeof
(
buf
),
PMU_TYPE_FILE
,
event_type
);
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
return
-
1
;
fd
=
open
(
buf
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
1
;
ret
=
read
(
fd
,
buf
,
sizeof
(
buf
));
close
(
fd
);
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
return
-
1
;
errno
=
0
;
ret
=
(
int
)
strtol
(
buf
,
NULL
,
10
);
return
errno
?
-
1
:
ret
;
}
#define PMU_RETPROBE_FILE "/sys/bus/event_source/devices/%s/format/retprobe"
static
int
bpf_get_retprobe_bit
(
const
char
*
event_type
)
{
int
fd
;
int
ret
;
char
buf
[
PATH_MAX
];
ret
=
snprintf
(
buf
,
sizeof
(
buf
),
PMU_RETPROBE_FILE
,
event_type
);
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
return
-
1
;
fd
=
open
(
buf
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
1
;
ret
=
read
(
fd
,
buf
,
sizeof
(
buf
));
close
(
fd
);
if
(
ret
<
0
||
ret
>=
sizeof
(
buf
))
return
-
1
;
if
(
strlen
(
buf
)
<
strlen
(
"config:"
))
return
-
1
;
errno
=
0
;
ret
=
(
int
)
strtol
(
buf
+
strlen
(
"config:"
),
NULL
,
10
);
return
errno
?
-
1
:
ret
;
}
/*
* new kernel API allows creating [k,u]probe with perf_event_open, which
* makes it easier to clean up the [k,u]probe. This function tries to
* create pfd with the new API.
*/
static
int
bpf_try_perf_event_open_with_probe
(
const
char
*
name
,
uint64_t
offs
,
int
pid
,
char
*
event_type
,
int
is_return
)
{
struct
perf_event_attr
attr
=
{};
int
type
=
bpf_find_probe_type
(
event_type
);
int
is_return_bit
=
bpf_get_retprobe_bit
(
event_type
);
int
cpu
=
0
;
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
)
attr
.
config
|=
1
<<
is_return_bit
;
/*
* struct perf_event_attr in latest perf_event.h has the following
* extension to config1 and config2. To keep bcc compatibe with
* older perf_event.h, we use config1 and config2 here instead of
* kprobe_func, uprobe_path, kprobe_addr, and probe_offset.
*
* union {
* __u64 bp_addr;
* __u64 kprobe_func;
* __u64 uprobe_path;
* __u64 config1;
* };
* union {
* __u64 bp_len;
* __u64 kprobe_addr;
* __u64 probe_offset;
* __u64 config2;
* };
*/
attr
.
config2
=
offs
;
/* config2 here is kprobe_addr or probe_offset */
attr
.
size
=
sizeof
(
attr
);
attr
.
type
=
type
;
/* config1 here is kprobe_func or uprobe_path */
attr
.
config1
=
ptr_to_u64
((
void
*
)
name
);
// PID filter is only possible for uprobe events.
if
(
pid
<
0
)
pid
=
-
1
;
// perf_event_open API doesn't allow both pid and cpu to be -1.
// So only set it to -1 when PID is not -1.
// Tracing events do not do CPU filtering in any cases.
if
(
pid
!=
-
1
)
cpu
=
-
1
;
return
syscall
(
__NR_perf_event_open
,
&
attr
,
pid
,
cpu
,
-
1
/* group_fd */
,
PERF_FLAG_FD_CLOEXEC
);
}
static
int
bpf_attach_tracing_event
(
int
progfd
,
const
char
*
event_path
,
struct
perf_reader
*
reader
,
int
pid
)
{
int
efd
,
pfd
,
cpu
=
0
;
struct
perf_reader
*
reader
,
int
pid
,
int
pfd
)
{
int
efd
,
cpu
=
0
;
ssize_t
bytes
;
char
buf
[
PATH_MAX
];
struct
perf_event_attr
attr
=
{};
if
(
pfd
<
0
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"%s/id"
,
event_path
);
efd
=
open
(
buf
,
O_RDONLY
,
0
);
if
(
efd
<
0
)
{
...
...
@@ -576,6 +684,7 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
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
)
...
...
@@ -598,6 +707,7 @@ void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
perf_reader_cb
cb
,
void
*
cb_cookie
)
{
int
kfd
;
int
pfd
;
char
buf
[
256
];
char
event_alias
[
128
];
struct
perf_reader
*
reader
=
NULL
;
...
...
@@ -607,6 +717,10 @@ void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
if
(
!
reader
)
goto
error
;
pfd
=
bpf_try_perf_event_open_with_probe
(
fn_name
,
0
,
-
1
,
event_type
,
attach_type
!=
BPF_PROBE_ENTRY
);
if
(
pfd
<
0
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/%s_events"
,
event_type
);
kfd
=
open
(
buf
,
O_WRONLY
|
O_APPEND
,
0
);
if
(
kfd
<
0
)
{
...
...
@@ -624,9 +738,9 @@ void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
goto
error
;
}
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 */
)
<
0
)
}
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
reader
,
-
1
/* PID */
,
pfd
)
<
0
)
goto
error
;
return
reader
;
...
...
@@ -708,11 +822,15 @@ void *bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
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
;
pfd
=
bpf_try_perf_event_open_with_probe
(
binary_path
,
offset
,
pid
,
event_type
,
attach_type
!=
BPF_PROBE_ENTRY
);
if
(
pfd
<
0
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/%s_events"
,
event_type
);
kfd
=
open
(
buf
,
O_WRONLY
|
O_APPEND
,
0
);
if
(
kfd
<
0
)
{
...
...
@@ -743,7 +861,8 @@ void *bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
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
)
<
0
)
}
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
reader
,
pid
,
pfd
)
<
0
)
goto
error
;
return
reader
;
...
...
@@ -758,8 +877,43 @@ error:
static
int
bpf_detach_probe
(
const
char
*
ev_name
,
const
char
*
event_type
)
{
int
kfd
,
res
;
int
kfd
=
-
1
,
res
;
char
buf
[
PATH_MAX
];
int
found_event
=
0
;
size_t
bufsize
=
0
;
char
*
cptr
=
NULL
;
FILE
*
fp
;
/*
* For [k,u]probe created with perf_event_open (on newer kernel), it is
* not necessary to clean it up in [k,u]probe_events. We first look up
* the %s_bcc_%d line in [k,u]probe_events. If the event is not found,
* it is safe to skip the cleaning up process (write -:... to the file).
*/
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/%s_events"
,
event_type
);
fp
=
fopen
(
buf
,
"r"
);
if
(
!
fp
)
{
fprintf
(
stderr
,
"open(%s): %s
\n
"
,
buf
,
strerror
(
errno
));
goto
error
;
}
res
=
snprintf
(
buf
,
sizeof
(
buf
),
"%ss/%s_bcc_%d"
,
event_type
,
ev_name
,
getpid
());
if
(
res
<
0
||
res
>=
sizeof
(
buf
))
{
fprintf
(
stderr
,
"snprintf(%s): %d
\n
"
,
ev_name
,
res
);
goto
error
;
}
while
(
getline
(
&
cptr
,
&
bufsize
,
fp
)
!=
-
1
)
if
(
strstr
(
cptr
,
buf
)
!=
NULL
)
{
found_event
=
1
;
break
;
}
fclose
(
fp
);
fp
=
NULL
;
if
(
!
found_event
)
return
0
;
snprintf
(
buf
,
sizeof
(
buf
),
"/sys/kernel/debug/tracing/%s_events"
,
event_type
);
kfd
=
open
(
buf
,
O_WRONLY
|
O_APPEND
,
0
);
if
(
kfd
<
0
)
{
...
...
@@ -783,6 +937,8 @@ static int bpf_detach_probe(const char *ev_name, const char *event_type)
error:
if
(
kfd
>=
0
)
close
(
kfd
);
if
(
fp
)
fclose
(
fp
);
return
-
1
;
}
...
...
@@ -809,7 +965,7 @@ void *bpf_attach_tracepoint(int progfd, const char *tp_category,
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 */
)
<
0
)
if
(
bpf_attach_tracing_event
(
progfd
,
buf
,
reader
,
-
1
/* PID */
,
-
1
/* pfd */
)
<
0
)
goto
error
;
return
reader
;
...
...
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