Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bpftrace
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
bpftrace
Commits
5def5f7f
Commit
5def5f7f
authored
Dec 29, 2018
by
Alex Birch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support on-stack strings of size up to about 240
parent
35b88a83
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
73 additions
and
8 deletions
+73
-8
src/ast/codegen_llvm.cpp
src/ast/codegen_llvm.cpp
+27
-3
src/ast/codegen_llvm.h
src/ast/codegen_llvm.h
+1
-0
src/ast/irbuilderbpf.cpp
src/ast/irbuilderbpf.cpp
+6
-1
src/ast/irbuilderbpf.h
src/ast/irbuilderbpf.h
+1
-0
src/ast/semantic_analyser.cpp
src/ast/semantic_analyser.cpp
+18
-4
src/bpftrace.h
src/bpftrace.h
+2
-0
src/main.cpp
src/main.cpp
+18
-0
No files found.
src/ast/codegen_llvm.cpp
View file @
5def5f7f
...
@@ -329,11 +329,27 @@ void CodegenLLVM::visit(Call &call)
...
@@ -329,11 +329,27 @@ void CodegenLLVM::visit(Call &call)
}
}
else
if
(
call
.
func
==
"str"
)
else
if
(
call
.
func
==
"str"
)
{
{
AllocaInst
*
buf
=
b_
.
CreateAllocaBPF
(
call
.
type
,
"str"
);
AllocaInst
*
strlen
=
b_
.
CreateAllocaBPF
(
b_
.
getInt64Ty
(),
"strlen"
);
b_
.
CreateMemSet
(
buf
,
b_
.
getInt8
(
0
),
call
.
type
.
size
,
1
);
b_
.
CreateMemSet
(
strlen
,
b_
.
getInt8
(
0
),
sizeof
(
uint64_t
),
1
);
if
(
call
.
vargs
->
size
()
>
1
)
{
call
.
vargs
->
at
(
1
)
->
accept
(
*
this
);
Value
*
proposed_strlen
=
b_
.
CreateAdd
(
expr_
,
b_
.
getInt64
(
1
));
// add 1 to accommodate probe_read_str's null byte
Value
*
max
=
b_
.
getInt64
(
bpftrace_
.
strlen_
);
CmpInst
::
Predicate
P
=
CmpInst
::
ICMP_ULE
;
Value
*
Cmp
=
b_
.
CreateICmp
(
P
,
proposed_strlen
,
max
,
"str.min.cmp"
);
Value
*
Select
=
b_
.
CreateSelect
(
Cmp
,
proposed_strlen
,
max
,
"str.min.select"
);
b_
.
CreateStore
(
Select
,
strlen
);
}
else
{
b_
.
CreateStore
(
b_
.
getInt64
(
bpftrace_
.
strlen_
),
strlen
);
}
AllocaInst
*
buf
=
b_
.
CreateAllocaBPF
(
bpftrace_
.
strlen_
,
"str"
);
b_
.
CreateMemSet
(
buf
,
b_
.
getInt8
(
0
),
bpftrace_
.
strlen_
,
1
);
call
.
vargs
->
front
()
->
accept
(
*
this
);
call
.
vargs
->
front
()
->
accept
(
*
this
);
b_
.
CreateProbeReadStr
(
buf
,
call
.
type
.
size
,
expr_
);
b_
.
CreateProbeReadStr
(
buf
,
b_
.
CreateLoad
(
strlen
),
expr_
);
b_
.
CreateLifetimeEnd
(
strlen
);
expr_
=
buf
;
expr_
=
buf
;
expr_deleter_
=
[
this
,
buf
]()
{
b_
.
CreateLifetimeEnd
(
buf
);
};
}
}
else
if
(
call
.
func
==
"kaddr"
)
else
if
(
call
.
func
==
"kaddr"
)
{
{
...
@@ -470,12 +486,16 @@ void CodegenLLVM::visit(Call &call)
...
@@ -470,12 +486,16 @@ void CodegenLLVM::visit(Call &call)
for
(
int
i
=
1
;
i
<
call
.
vargs
->
size
();
i
++
)
for
(
int
i
=
1
;
i
<
call
.
vargs
->
size
();
i
++
)
{
{
Expression
&
arg
=
*
call
.
vargs
->
at
(
i
);
Expression
&
arg
=
*
call
.
vargs
->
at
(
i
);
expr_deleter_
=
nullptr
;
arg
.
accept
(
*
this
);
arg
.
accept
(
*
this
);
Value
*
offset
=
b_
.
CreateGEP
(
printf_args
,
{
b_
.
getInt32
(
0
),
b_
.
getInt32
(
i
)});
Value
*
offset
=
b_
.
CreateGEP
(
printf_args
,
{
b_
.
getInt32
(
0
),
b_
.
getInt32
(
i
)});
if
(
arg
.
type
.
IsArray
())
if
(
arg
.
type
.
IsArray
())
b_
.
CREATE_MEMCPY
(
offset
,
expr_
,
arg
.
type
.
size
,
1
);
b_
.
CREATE_MEMCPY
(
offset
,
expr_
,
arg
.
type
.
size
,
1
);
else
else
b_
.
CreateStore
(
expr_
,
offset
);
b_
.
CreateStore
(
expr_
,
offset
);
if
(
expr_deleter_
)
expr_deleter_
();
}
}
printf_id_
++
;
printf_id_
++
;
...
@@ -519,12 +539,16 @@ void CodegenLLVM::visit(Call &call)
...
@@ -519,12 +539,16 @@ void CodegenLLVM::visit(Call &call)
for
(
int
i
=
1
;
i
<
call
.
vargs
->
size
();
i
++
)
for
(
int
i
=
1
;
i
<
call
.
vargs
->
size
();
i
++
)
{
{
Expression
&
arg
=
*
call
.
vargs
->
at
(
i
);
Expression
&
arg
=
*
call
.
vargs
->
at
(
i
);
expr_deleter_
=
nullptr
;
arg
.
accept
(
*
this
);
arg
.
accept
(
*
this
);
Value
*
offset
=
b_
.
CreateGEP
(
system_args
,
{
b_
.
getInt32
(
0
),
b_
.
getInt32
(
i
)});
Value
*
offset
=
b_
.
CreateGEP
(
system_args
,
{
b_
.
getInt32
(
0
),
b_
.
getInt32
(
i
)});
if
(
arg
.
type
.
IsArray
())
if
(
arg
.
type
.
IsArray
())
b_
.
CREATE_MEMCPY
(
offset
,
expr_
,
arg
.
type
.
size
,
1
);
b_
.
CREATE_MEMCPY
(
offset
,
expr_
,
arg
.
type
.
size
,
1
);
else
else
b_
.
CreateStore
(
expr_
,
offset
);
b_
.
CreateStore
(
expr_
,
offset
);
if
(
expr_deleter_
)
expr_deleter_
();
}
}
system_id_
++
;
system_id_
++
;
...
...
src/ast/codegen_llvm.h
View file @
5def5f7f
...
@@ -66,6 +66,7 @@ private:
...
@@ -66,6 +66,7 @@ private:
IRBuilderBPF
b_
;
IRBuilderBPF
b_
;
DataLayout
layout_
;
DataLayout
layout_
;
Value
*
expr_
=
nullptr
;
Value
*
expr_
=
nullptr
;
std
::
function
<
void
()
>
expr_deleter_
;
// intentionally empty
Value
*
ctx_
;
Value
*
ctx_
;
AttachPoint
*
current_attach_point_
=
nullptr
;
AttachPoint
*
current_attach_point_
=
nullptr
;
BPFtrace
&
bpftrace_
;
BPFtrace
&
bpftrace_
;
...
...
src/ast/irbuilderbpf.cpp
View file @
5def5f7f
...
@@ -267,6 +267,11 @@ void IRBuilderBPF::CreateProbeRead(AllocaInst *dst, size_t size, Value *src)
...
@@ -267,6 +267,11 @@ void IRBuilderBPF::CreateProbeRead(AllocaInst *dst, size_t size, Value *src)
}
}
CallInst
*
IRBuilderBPF
::
CreateProbeReadStr
(
AllocaInst
*
dst
,
size_t
size
,
Value
*
src
)
CallInst
*
IRBuilderBPF
::
CreateProbeReadStr
(
AllocaInst
*
dst
,
size_t
size
,
Value
*
src
)
{
return
CreateProbeReadStr
(
dst
,
getInt64
(
size
),
src
);
}
CallInst
*
IRBuilderBPF
::
CreateProbeReadStr
(
AllocaInst
*
dst
,
llvm
::
Value
*
size
,
Value
*
src
)
{
{
// int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
// int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
FunctionType
*
probereadstr_func_type
=
FunctionType
::
get
(
FunctionType
*
probereadstr_func_type
=
FunctionType
::
get
(
...
@@ -278,7 +283,7 @@ CallInst *IRBuilderBPF::CreateProbeReadStr(AllocaInst *dst, size_t size, Value *
...
@@ -278,7 +283,7 @@ CallInst *IRBuilderBPF::CreateProbeReadStr(AllocaInst *dst, size_t size, Value *
Instruction
::
IntToPtr
,
Instruction
::
IntToPtr
,
getInt64
(
BPF_FUNC_probe_read_str
),
getInt64
(
BPF_FUNC_probe_read_str
),
probereadstr_func_ptr_type
);
probereadstr_func_ptr_type
);
return
CreateCall
(
probereadstr_func
,
{
dst
,
getInt64
(
size
)
,
src
},
"probe_read_str"
);
return
CreateCall
(
probereadstr_func
,
{
dst
,
size
,
src
},
"probe_read_str"
);
}
}
CallInst
*
IRBuilderBPF
::
CreateProbeReadStr
(
Value
*
dst
,
size_t
size
,
Value
*
src
)
CallInst
*
IRBuilderBPF
::
CreateProbeReadStr
(
Value
*
dst
,
size_t
size
,
Value
*
src
)
...
...
src/ast/irbuilderbpf.h
View file @
5def5f7f
...
@@ -41,6 +41,7 @@ public:
...
@@ -41,6 +41,7 @@ public:
void
CreateMapUpdateElem
(
Map
&
map
,
AllocaInst
*
key
,
Value
*
val
);
void
CreateMapUpdateElem
(
Map
&
map
,
AllocaInst
*
key
,
Value
*
val
);
void
CreateMapDeleteElem
(
Map
&
map
,
AllocaInst
*
key
);
void
CreateMapDeleteElem
(
Map
&
map
,
AllocaInst
*
key
);
void
CreateProbeRead
(
AllocaInst
*
dst
,
size_t
size
,
Value
*
src
);
void
CreateProbeRead
(
AllocaInst
*
dst
,
size_t
size
,
Value
*
src
);
CallInst
*
CreateProbeReadStr
(
AllocaInst
*
dst
,
llvm
::
Value
*
size
,
Value
*
src
);
CallInst
*
CreateProbeReadStr
(
AllocaInst
*
dst
,
size_t
size
,
Value
*
src
);
CallInst
*
CreateProbeReadStr
(
AllocaInst
*
dst
,
size_t
size
,
Value
*
src
);
CallInst
*
CreateProbeReadStr
(
Value
*
dst
,
size_t
size
,
Value
*
src
);
CallInst
*
CreateProbeReadStr
(
Value
*
dst
,
size_t
size
,
Value
*
src
);
Value
*
CreateUSDTReadArgument
(
Value
*
ctx
,
AttachPoint
*
attach_point
,
int
arg_name
,
Builtin
&
builtin
);
Value
*
CreateUSDTReadArgument
(
Value
*
ctx
,
AttachPoint
*
attach_point
,
int
arg_name
,
Builtin
&
builtin
);
...
...
src/ast/semantic_analyser.cpp
View file @
5def5f7f
...
@@ -202,13 +202,27 @@ void SemanticAnalyser::visit(Call &call)
...
@@ -202,13 +202,27 @@ void SemanticAnalyser::visit(Call &call)
call
.
type
=
SizedType
(
Type
::
none
,
0
);
call
.
type
=
SizedType
(
Type
::
none
,
0
);
}
}
else
if
(
call
.
func
==
"str"
||
call
.
func
==
"sym"
||
call
.
func
==
"usym"
)
{
else
if
(
call
.
func
==
"str"
)
{
if
(
check_varargs
(
call
,
1
,
2
))
{
check_arg
(
call
,
Type
::
integer
,
0
);
if
(
is_final_pass
())
{
uint64_t
strlen
=
bpftrace_
.
strlen_
;
if
(
call
.
vargs
->
size
()
>
1
)
{
check_arg
(
call
,
Type
::
integer
,
1
,
false
);
auto
&
strlen_arg
=
*
call
.
vargs
->
at
(
1
);
if
(
strlen_arg
.
is_literal
)
{
strlen
=
static_cast
<
Integer
&>
(
strlen_arg
).
n
;
}
}
call
.
type
=
SizedType
(
Type
::
string
,
strlen
);
}
}
}
else
if
(
call
.
func
==
"sym"
||
call
.
func
==
"usym"
)
{
check_nargs
(
call
,
1
);
check_nargs
(
call
,
1
);
check_arg
(
call
,
Type
::
integer
,
0
);
check_arg
(
call
,
Type
::
integer
,
0
);
if
(
call
.
func
==
"str"
)
if
(
call
.
func
==
"sym"
)
call
.
type
=
SizedType
(
Type
::
string
,
STRING_SIZE
);
else
if
(
call
.
func
==
"sym"
)
call
.
type
=
SizedType
(
Type
::
sym
,
8
);
call
.
type
=
SizedType
(
Type
::
sym
,
8
);
else
if
(
call
.
func
==
"usym"
)
else
if
(
call
.
func
==
"usym"
)
call
.
type
=
SizedType
(
Type
::
usym
,
16
);
call
.
type
=
SizedType
(
Type
::
usym
,
16
);
...
...
src/bpftrace.h
View file @
5def5f7f
...
@@ -84,6 +84,8 @@ public:
...
@@ -84,6 +84,8 @@ public:
int
join_argnum_
;
int
join_argnum_
;
int
join_argsize_
;
int
join_argsize_
;
uint64_t
strlen_
;
static
void
sort_by_key
(
std
::
vector
<
SizedType
>
key_args
,
static
void
sort_by_key
(
std
::
vector
<
SizedType
>
key_args
,
std
::
vector
<
std
::
pair
<
std
::
vector
<
uint8_t
>
,
std
::
vector
<
uint8_t
>>>
&
values_by_key
);
std
::
vector
<
std
::
pair
<
std
::
vector
<
uint8_t
>
,
std
::
vector
<
uint8_t
>>>
&
values_by_key
);
virtual
std
::
set
<
std
::
string
>
find_wildcard_matches
(
const
std
::
string
&
prefix
,
const
std
::
string
&
func
,
std
::
istream
&
symbol_name_stream
);
virtual
std
::
set
<
std
::
string
>
find_wildcard_matches
(
const
std
::
string
&
prefix
,
const
std
::
string
&
func
,
std
::
istream
&
symbol_name_stream
);
...
...
src/main.cpp
View file @
5def5f7f
...
@@ -29,6 +29,11 @@ void usage()
...
@@ -29,6 +29,11 @@ void usage()
std
::
cerr
<<
" -p PID enable USDT probes on PID"
<<
std
::
endl
;
std
::
cerr
<<
" -p PID enable USDT probes on PID"
<<
std
::
endl
;
std
::
cerr
<<
" -c 'CMD' run CMD and enable USDT probes on resulting process"
<<
std
::
endl
;
std
::
cerr
<<
" -c 'CMD' run CMD and enable USDT probes on resulting process"
<<
std
::
endl
;
std
::
cerr
<<
" -v verbose messages"
<<
std
::
endl
<<
std
::
endl
;
std
::
cerr
<<
" -v verbose messages"
<<
std
::
endl
<<
std
::
endl
;
std
::
cerr
<<
"ENVIRONMENT:"
<<
std
::
endl
;
std
::
cerr
<<
" BPFTRACE_STRLEN [default: 64] bytes allocated on BPF stack by str()."
<<
std
::
endl
;
std
::
cerr
<<
" Tune this to read in larger strings from userspace."
<<
std
::
endl
;
std
::
cerr
<<
" Beware that BPF stack is small (512 bytes)."
<<
std
::
endl
;
std
::
cerr
<<
" Beware that printf() and system() allocate strlen again when composing perf event output."
<<
std
::
endl
;
std
::
cerr
<<
"EXAMPLES:"
<<
std
::
endl
;
std
::
cerr
<<
"EXAMPLES:"
<<
std
::
endl
;
std
::
cerr
<<
"bpftrace -l '*sleep*'"
<<
std
::
endl
;
std
::
cerr
<<
"bpftrace -l '*sleep*'"
<<
std
::
endl
;
std
::
cerr
<<
" list probes containing
\"
sleep
\"
"
<<
std
::
endl
;
std
::
cerr
<<
" list probes containing
\"
sleep
\"
"
<<
std
::
endl
;
...
@@ -36,6 +41,8 @@ void usage()
...
@@ -36,6 +41,8 @@ void usage()
std
::
cerr
<<
" trace processes calling sleep"
<<
std
::
endl
;
std
::
cerr
<<
" trace processes calling sleep"
<<
std
::
endl
;
std
::
cerr
<<
"bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'"
<<
std
::
endl
;
std
::
cerr
<<
"bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'"
<<
std
::
endl
;
std
::
cerr
<<
" count syscalls by process name"
<<
std
::
endl
;
std
::
cerr
<<
" count syscalls by process name"
<<
std
::
endl
;
std
::
cerr
<<
"BPFTRACE_STRLEN=200 bpftrace -e 'tracepoint:syscalls:sys_enter_write /pid == 25783/ { printf(
\"
<%s>
\\
n
\"
, str(args->buf, args->count)); }'"
<<
std
::
endl
;
std
::
cerr
<<
" trace input & output of terminal with specified PID"
<<
std
::
endl
;
}
}
static
void
enforce_infinite_rlimit
()
{
static
void
enforce_infinite_rlimit
()
{
...
@@ -176,6 +183,17 @@ int main(int argc, char *argv[])
...
@@ -176,6 +183,17 @@ int main(int argc, char *argv[])
bpftrace
.
join_argnum_
=
16
;
bpftrace
.
join_argnum_
=
16
;
bpftrace
.
join_argsize_
=
1024
;
bpftrace
.
join_argsize_
=
1024
;
bpftrace
.
strlen_
=
64
;
if
(
const
char
*
env_p
=
std
::
getenv
(
"BPFTRACE_STRLEN"
))
{
uint64_t
proposed
;
std
::
istringstream
stringstream
(
env_p
);
if
(
!
(
stringstream
>>
proposed
))
{
std
::
cerr
<<
"Env var 'BPFTRACE_STRLEN' did not contain a valid uint64_t, or was zero-valued."
<<
std
::
endl
;
return
1
;
}
bpftrace
.
strlen_
=
proposed
;
}
// PID is currently only used for USDT probes that need enabling. Future work:
// PID is currently only used for USDT probes that need enabling. Future work:
// - make PID a filter for all probe types: pass to perf_event_open(), etc.
// - make PID a filter for all probe types: pass to perf_event_open(), etc.
// - provide PID in USDT probe specification as a way to override -p.
// - provide PID in USDT probe specification as a way to override -p.
...
...
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