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
6b0ed37f
Commit
6b0ed37f
authored
Sep 29, 2016
by
Teng Qin
Committed by
4ast
Sep 29, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add stack trace to trace.py (#712)
parent
0615bff0
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
64 additions
and
7 deletions
+64
-7
tools/trace.py
tools/trace.py
+64
-7
No files found.
tools/trace.py
View file @
6b0ed37f
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
# Copyright (C) 2016 Sasha Goldshtein.
# Copyright (C) 2016 Sasha Goldshtein.
from
bcc
import
BPF
,
Tracepoint
,
Perf
,
USDT
from
bcc
import
BPF
,
Tracepoint
,
Perf
,
USDT
from
functools
import
partial
from
time
import
sleep
,
strftime
from
time
import
sleep
,
strftime
import
argparse
import
argparse
import
re
import
re
...
@@ -58,10 +59,12 @@ class Probe(object):
...
@@ -58,10 +59,12 @@ class Probe(object):
cls
.
first_ts
=
Time
.
monotonic_time
()
cls
.
first_ts
=
Time
.
monotonic_time
()
cls
.
pid
=
args
.
pid
or
-
1
cls
.
pid
=
args
.
pid
or
-
1
def
__init__
(
self
,
probe
,
string_size
):
def
__init__
(
self
,
probe
,
string_size
,
kernel_stack
,
user_stack
):
self
.
usdt
=
None
self
.
usdt
=
None
self
.
raw_probe
=
probe
self
.
raw_probe
=
probe
self
.
string_size
=
string_size
self
.
string_size
=
string_size
self
.
kernel_stack
=
kernel_stack
self
.
user_stack
=
user_stack
Probe
.
probe_count
+=
1
Probe
.
probe_count
+=
1
self
.
_parse_probe
()
self
.
_parse_probe
()
self
.
probe_num
=
Probe
.
probe_count
self
.
probe_num
=
Probe
.
probe_count
...
@@ -236,6 +239,10 @@ class Probe(object):
...
@@ -236,6 +239,10 @@ class Probe(object):
]
]
for
i
in
range
(
0
,
len
(
self
.
types
)):
for
i
in
range
(
0
,
len
(
self
.
types
)):
self
.
_generate_python_field_decl
(
i
,
fields
)
self
.
_generate_python_field_decl
(
i
,
fields
)
if
self
.
kernel_stack
:
fields
.
append
((
"kernel_stack_id"
,
ct
.
c_int
))
if
self
.
user_stack
:
fields
.
append
((
"user_stack_id"
,
ct
.
c_int
))
return
type
(
self
.
python_struct_name
,
(
ct
.
Structure
,),
return
type
(
self
.
python_struct_name
,
(
ct
.
Structure
,),
dict
(
_fields_
=
fields
))
dict
(
_fields_
=
fields
))
...
@@ -260,12 +267,19 @@ class Probe(object):
...
@@ -260,12 +267,19 @@ class Probe(object):
# construct the final display string.
# construct the final display string.
self
.
events_name
=
"%s_events"
%
self
.
probe_name
self
.
events_name
=
"%s_events"
%
self
.
probe_name
self
.
struct_name
=
"%s_data_t"
%
self
.
probe_name
self
.
struct_name
=
"%s_data_t"
%
self
.
probe_name
self
.
stacks_name
=
"%s_stacks"
%
self
.
probe_name
stack_table
=
"BPF_STACK_TRACE(%s, 1024);"
%
self
.
stacks_name
\
if
(
self
.
kernel_stack
or
self
.
user_stack
)
else
""
data_fields
=
""
data_fields
=
""
for
i
,
field_type
in
enumerate
(
self
.
types
):
for
i
,
field_type
in
enumerate
(
self
.
types
):
data_fields
+=
" "
+
\
data_fields
+=
" "
+
\
self
.
_generate_field_decl
(
i
)
self
.
_generate_field_decl
(
i
)
kernel_stack_str
=
" int kernel_stack_id;"
\
if
self
.
kernel_stack
else
""
user_stack_str
=
" int user_stack_id;"
\
if
self
.
user_stack
else
""
text
=
"""
text
=
"""
struct %s
struct %s
{
{
...
@@ -273,11 +287,16 @@ struct %s
...
@@ -273,11 +287,16 @@ struct %s
u32 pid;
u32 pid;
char comm[TASK_COMM_LEN];
char comm[TASK_COMM_LEN];
%s
%s
%s
%s
};
};
BPF_PERF_OUTPUT(%s);
BPF_PERF_OUTPUT(%s);
%s
"""
"""
return
text
%
(
self
.
struct_name
,
data_fields
,
self
.
events_name
)
return
text
%
(
self
.
struct_name
,
data_fields
,
kernel_stack_str
,
user_stack_str
,
self
.
events_name
,
stack_table
)
def
_generate_field_assign
(
self
,
idx
):
def
_generate_field_assign
(
self
,
idx
):
field_type
=
self
.
types
[
idx
]
field_type
=
self
.
types
[
idx
]
...
@@ -346,6 +365,18 @@ BPF_PERF_OUTPUT(%s);
...
@@ -346,6 +365,18 @@ BPF_PERF_OUTPUT(%s);
for
i
,
expr
in
enumerate
(
self
.
values
):
for
i
,
expr
in
enumerate
(
self
.
values
):
data_fields
+=
self
.
_generate_field_assign
(
i
)
data_fields
+=
self
.
_generate_field_assign
(
i
)
stack_trace
=
""
if
self
.
user_stack
:
stack_trace
+=
"""
__data.user_stack_id = %s.get_stackid(
ctx, BPF_F_REUSE_STACKID | BPF_F_USER_STACK
);"""
%
self
.
stacks_name
if
self
.
kernel_stack
:
stack_trace
+=
"""
__data.kernel_stack_id = %s.get_stackid(
ctx, BPF_F_REUSE_STACKID
);"""
%
self
.
stacks_name
text
=
"""
text
=
"""
int %s(%s)
int %s(%s)
{
{
...
@@ -358,6 +389,7 @@ int %s(%s)
...
@@ -358,6 +389,7 @@ int %s(%s)
__data.timestamp_ns = bpf_ktime_get_ns();
__data.timestamp_ns = bpf_ktime_get_ns();
__data.pid = bpf_get_current_pid_tgid();
__data.pid = bpf_get_current_pid_tgid();
bpf_get_current_comm(&__data.comm, sizeof(__data.comm));
bpf_get_current_comm(&__data.comm, sizeof(__data.comm));
%s
%s
%s
%s.perf_submit(ctx, &__data, sizeof(__data));
%s.perf_submit(ctx, &__data, sizeof(__data));
return 0;
return 0;
...
@@ -366,7 +398,8 @@ int %s(%s)
...
@@ -366,7 +398,8 @@ int %s(%s)
text
=
text
%
(
self
.
probe_name
,
signature
,
text
=
text
%
(
self
.
probe_name
,
signature
,
pid_filter
,
prefix
,
pid_filter
,
prefix
,
self
.
_generate_usdt_filter_read
(),
self
.
filter
,
self
.
_generate_usdt_filter_read
(),
self
.
filter
,
self
.
struct_name
,
data_fields
,
self
.
events_name
)
self
.
struct_name
,
data_fields
,
stack_trace
,
self
.
events_name
)
return
data_decl
+
"
\
n
"
+
text
return
data_decl
+
"
\
n
"
+
text
...
@@ -382,7 +415,16 @@ int %s(%s)
...
@@ -382,7 +415,16 @@ int %s(%s)
else
:
# self.probe_type == 't'
else
:
# self.probe_type == 't'
return
self
.
tp_event
return
self
.
tp_event
def
print_event
(
self
,
cpu
,
data
,
size
):
def
print_stack
(
self
,
bpf
,
stack_id
,
pid
):
if
stack_id
<
0
:
print
(
" %d"
%
stack_id
)
return
stack
=
list
(
bpf
.
get_table
(
self
.
stacks_name
).
walk
(
stack_id
))
for
addr
in
stack
:
print
(
" %016x %s"
%
(
addr
,
bpf
.
sym
(
addr
,
pid
)))
def
print_event
(
self
,
bpf
,
cpu
,
data
,
size
):
# Cast as the generated structure type and display
# Cast as the generated structure type and display
# according to the format string in the probe.
# according to the format string in the probe.
event
=
ct
.
cast
(
data
,
ct
.
POINTER
(
self
.
python_struct
)).
contents
event
=
ct
.
cast
(
data
,
ct
.
POINTER
(
self
.
python_struct
)).
contents
...
@@ -395,6 +437,15 @@ int %s(%s)
...
@@ -395,6 +437,15 @@ int %s(%s)
(
time
[:
8
],
event
.
pid
,
event
.
comm
[:
12
],
(
time
[:
8
],
event
.
pid
,
event
.
comm
[:
12
],
self
.
_display_function
(),
msg
))
self
.
_display_function
(),
msg
))
if
self
.
user_stack
:
print
(
" User Stack Trace:"
)
self
.
print_stack
(
bpf
,
event
.
user_stack_id
,
event
.
pid
)
if
self
.
kernel_stack
:
print
(
" Kernel Stack Trace:"
)
self
.
print_stack
(
bpf
,
event
.
kernel_stack_id
,
-
1
)
if
self
.
user_stack
or
self
.
kernel_stack
:
print
(
""
)
Probe
.
event_count
+=
1
Probe
.
event_count
+=
1
if
Probe
.
max_events
is
not
None
and
\
if
Probe
.
max_events
is
not
None
and
\
Probe
.
event_count
>=
Probe
.
max_events
:
Probe
.
event_count
>=
Probe
.
max_events
:
...
@@ -406,7 +457,8 @@ int %s(%s)
...
@@ -406,7 +457,8 @@ int %s(%s)
else
:
else
:
self
.
_attach_u
(
bpf
)
self
.
_attach_u
(
bpf
)
self
.
python_struct
=
self
.
_generate_python_data_decl
()
self
.
python_struct
=
self
.
_generate_python_data_decl
()
bpf
[
self
.
events_name
].
open_perf_buffer
(
self
.
print_event
)
callback
=
partial
(
self
.
print_event
,
bpf
)
bpf
[
self
.
events_name
].
open_perf_buffer
(
callback
)
def
_attach_k
(
self
,
bpf
):
def
_attach_k
(
self
,
bpf
):
if
self
.
probe_type
==
"r"
:
if
self
.
probe_type
==
"r"
:
...
@@ -482,6 +534,10 @@ trace 'u:pthread:pthread_create (arg4 != 0)'
...
@@ -482,6 +534,10 @@ trace 'u:pthread:pthread_create (arg4 != 0)'
help
=
"number of events to print before quitting"
)
help
=
"number of events to print before quitting"
)
parser
.
add_argument
(
"-o"
,
"--offset"
,
action
=
"store_true"
,
parser
.
add_argument
(
"-o"
,
"--offset"
,
action
=
"store_true"
,
help
=
"use relative time from first traced message"
)
help
=
"use relative time from first traced message"
)
parser
.
add_argument
(
"-K"
,
"--kernel-stack"
,
action
=
"store_true"
,
help
=
"output kernel stack trace"
)
parser
.
add_argument
(
"-U"
,
"--user_stack"
,
action
=
"store_true"
,
help
=
"output user stack trace"
)
parser
.
add_argument
(
metavar
=
"probe"
,
dest
=
"probes"
,
nargs
=
"+"
,
parser
.
add_argument
(
metavar
=
"probe"
,
dest
=
"probes"
,
nargs
=
"+"
,
help
=
"probe specifier (see examples)"
)
help
=
"probe specifier (see examples)"
)
self
.
args
=
parser
.
parse_args
()
self
.
args
=
parser
.
parse_args
()
...
@@ -491,7 +547,8 @@ trace 'u:pthread:pthread_create (arg4 != 0)'
...
@@ -491,7 +547,8 @@ trace 'u:pthread:pthread_create (arg4 != 0)'
self
.
probes
=
[]
self
.
probes
=
[]
for
probe_spec
in
self
.
args
.
probes
:
for
probe_spec
in
self
.
args
.
probes
:
self
.
probes
.
append
(
Probe
(
self
.
probes
.
append
(
Probe
(
probe_spec
,
self
.
args
.
string_size
))
probe_spec
,
self
.
args
.
string_size
,
self
.
args
.
kernel_stack
,
self
.
args
.
user_stack
))
def
_generate_program
(
self
):
def
_generate_program
(
self
):
self
.
program
=
"""
self
.
program
=
"""
...
...
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