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
b57abde0
Commit
b57abde0
authored
Aug 28, 2018
by
Brendan Gregg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add name builtin
parent
282748b0
Changes
16
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
314 additions
and
74 deletions
+314
-74
src/ast/ast.h
src/ast/ast.h
+2
-0
src/ast/codegen_llvm.cpp
src/ast/codegen_llvm.cpp
+69
-12
src/ast/codegen_llvm.h
src/ast/codegen_llvm.h
+1
-0
src/ast/semantic_analyser.cpp
src/ast/semantic_analyser.cpp
+4
-0
src/attached_probe.cpp
src/attached_probe.cpp
+12
-2
src/bpftrace.cpp
src/bpftrace.cpp
+33
-6
src/bpftrace.h
src/bpftrace.h
+3
-1
src/lexer.l
src/lexer.l
+1
-1
src/mapkey.cpp
src/mapkey.cpp
+2
-0
src/printf.cpp
src/printf.cpp
+1
-1
src/types.cpp
src/types.cpp
+1
-0
src/types.h
src/types.h
+6
-4
tests/bpftrace.cpp
tests/bpftrace.cpp
+47
-47
tests/codegen.cpp
tests/codegen.cpp
+112
-0
tests/parser.cpp
tests/parser.cpp
+1
-0
tests/semantic_analyser.cpp
tests/semantic_analyser.cpp
+19
-0
No files found.
src/ast/ast.h
View file @
b57abde0
...
...
@@ -49,6 +49,7 @@ class Builtin : public Expression {
public:
explicit
Builtin
(
std
::
string
ident
)
:
ident
(
ident
)
{
}
std
::
string
ident
;
int
name_id
;
void
accept
(
Visitor
&
v
)
override
;
};
...
...
@@ -196,6 +197,7 @@ public:
void
accept
(
Visitor
&
v
)
override
;
std
::
string
name
()
const
;
bool
need_expansion
=
false
;
// must build a BPF program per wildcard match
};
using
ProbeList
=
std
::
vector
<
Probe
*>
;
...
...
src/ast/codegen_llvm.cpp
View file @
b57abde0
...
...
@@ -97,6 +97,14 @@ void CodegenLLVM::visit(Builtin &builtin)
expr_
=
b_
.
CreateLoad
(
dst
);
b_
.
CreateLifetimeEnd
(
dst
);
}
else
if
(
builtin
.
ident
==
"name"
)
{
static
int
name_id
=
0
;
bpftrace_
.
name_ids_
.
push_back
(
probefull_
);
builtin
.
name_id
=
name_id
;
name_id
++
;
expr_
=
b_
.
getInt64
(
builtin
.
name_id
);
}
else
{
abort
();
...
...
@@ -659,6 +667,16 @@ void CodegenLLVM::visit(Probe &probe)
b_
.
getInt64Ty
(),
{
b_
.
getInt8PtrTy
()},
// struct pt_regs *ctx
false
);
/*
* Most of the time, we can take a probe like kprobe:do_f* and build a
* single BPF program for that, called "s_kprobe:do_f*", and attach it to
* each wildcard match. An exception is the "name" builtin, where we need
* to build different BPF programs for each wildcard match that cantains an
* ID for the match. Those programs will be called "s_kprobe:do_fcntl" etc.
*/
if
(
probe
.
need_expansion
==
false
)
{
// build a single BPF program pre-wildcards
Function
*
func
=
Function
::
Create
(
func_type
,
Function
::
ExternalLinkage
,
probe
.
name
(),
module_
.
get
());
func
->
setSection
(
"s_"
+
probe
.
name
());
BasicBlock
*
entry
=
BasicBlock
::
Create
(
module_
->
getContext
(),
"entry"
,
func
);
...
...
@@ -674,6 +692,45 @@ void CodegenLLVM::visit(Probe &probe)
}
b_
.
CreateRet
(
ConstantInt
::
get
(
module_
->
getContext
(),
APInt
(
64
,
0
)));
}
else
{
// build a separate BPF programs for each wildcard match
for
(
auto
&
attach_point
:
*
probe
.
attach_points
)
{
std
::
string
file_name
;
switch
(
probetype
(
attach_point
->
provider
))
{
case
ProbeType
:
:
kprobe
:
case
ProbeType
:
:
kretprobe
:
file_name
=
"/sys/kernel/debug/tracing/available_filter_functions"
;
break
;
case
ProbeType
:
:
tracepoint
:
file_name
=
"/sys/kernel/debug/tracing/available_events"
;
break
;
default:
std
::
cerr
<<
"Wildcard matches aren't available on probe type '"
<<
attach_point
->
provider
<<
"'"
<<
std
::
endl
;
return
;
}
auto
matches
=
bpftrace_
.
find_wildcard_matches
(
attach_point
->
target
,
attach_point
->
func
,
file_name
);
for
(
auto
&
match
:
matches
)
{
probefull_
=
attach_point
->
name
(
match
);
Function
*
func
=
Function
::
Create
(
func_type
,
Function
::
ExternalLinkage
,
attach_point
->
name
(
match
),
module_
.
get
());
func
->
setSection
(
"s_"
+
attach_point
->
name
(
match
));
BasicBlock
*
entry
=
BasicBlock
::
Create
(
module_
->
getContext
(),
"entry"
,
func
);
b_
.
SetInsertPoint
(
entry
);
// check: do the following 8 lines need to be in the wildcard loop?
ctx_
=
func
->
arg_begin
();
if
(
probe
.
pred
)
{
probe
.
pred
->
accept
(
*
this
);
}
for
(
Statement
*
stmt
:
*
probe
.
stmts
)
{
stmt
->
accept
(
*
this
);
}
b_
.
CreateRet
(
ConstantInt
::
get
(
module_
->
getContext
(),
APInt
(
64
,
0
)));
}
}
}
}
void
CodegenLLVM
::
visit
(
Include
&
include
)
...
...
src/ast/codegen_llvm.h
View file @
b57abde0
...
...
@@ -65,6 +65,7 @@ private:
Value
*
expr_
=
nullptr
;
Value
*
ctx_
;
BPFtrace
&
bpftrace_
;
std
::
string
probefull_
;
std
::
map
<
std
::
string
,
Value
*>
variables_
;
};
...
...
src/ast/semantic_analyser.cpp
View file @
b57abde0
...
...
@@ -68,6 +68,10 @@ void SemanticAnalyser::visit(Builtin &builtin)
err_
<<
arch
::
name
()
<<
" doesn't support "
<<
builtin
.
ident
<<
std
::
endl
;
builtin
.
type
=
SizedType
(
Type
::
integer
,
8
);
}
else
if
(
builtin
.
ident
==
"name"
)
{
builtin
.
type
=
SizedType
(
Type
::
name
,
8
);
probe_
->
need_expansion
=
true
;
}
else
{
builtin
.
type
=
SizedType
(
Type
::
none
,
0
);
err_
<<
"Unknown builtin variable: '"
<<
builtin
.
ident
<<
"'"
<<
std
::
endl
;
...
...
src/attached_probe.cpp
View file @
b57abde0
...
...
@@ -55,6 +55,8 @@ AttachedProbe::AttachedProbe(Probe &probe, std::tuple<uint8_t *, uintptr_t> func
:
probe_
(
probe
),
func_
(
func
)
{
load_prog
();
if
(
bt_verbose
)
std
::
cerr
<<
"Attaching "
<<
probe_
.
name
<<
std
::
endl
;
switch
(
probe_
.
type
)
{
case
ProbeType
:
:
kprobe
:
...
...
@@ -277,8 +279,16 @@ void AttachedProbe::attach_kprobe()
int
perf_event_fd
=
bpf_attach_kprobe
(
progfd_
,
attachtype
(
probe_
.
type
),
eventname
().
c_str
(),
probe_
.
attach_point
.
c_str
(),
0
);
if
(
perf_event_fd
<
0
)
if
(
perf_event_fd
<
0
)
{
if
(
probe_
.
orig_name
!=
probe_
.
name
)
{
// a wildcard expansion couldn't probe something, just print a warning
// as this is normal for some kernel functions (eg, do_debug())
std
::
cerr
<<
"Warning: could not attach probe "
<<
probe_
.
name
<<
", skipping."
<<
std
::
endl
;
}
else
{
// an explicit match failed, so fail as the user must have wanted it
throw
std
::
runtime_error
(
"Error attaching probe: '"
+
probe_
.
name
+
"'"
);
}
}
perf_event_fds_
.
push_back
(
perf_event_fd
);
}
...
...
src/bpftrace.cpp
View file @
b57abde0
...
...
@@ -30,7 +30,7 @@ int BPFtrace::add_probe(ast::Probe &p)
probe
.
path
=
"/proc/self/exe"
;
probe
.
attach_point
=
"BEGIN_trigger"
;
probe
.
type
=
probetype
(
attach_point
->
provider
);
probe
.
pro
g_name
=
p
.
name
();
probe
.
ori
g_name
=
p
.
name
();
probe
.
name
=
p
.
name
();
special_probes_
.
push_back
(
probe
);
continue
;
...
...
@@ -41,7 +41,7 @@ int BPFtrace::add_probe(ast::Probe &p)
probe
.
path
=
"/proc/self/exe"
;
probe
.
attach_point
=
"END_trigger"
;
probe
.
type
=
probetype
(
attach_point
->
provider
);
probe
.
pro
g_name
=
p
.
name
();
probe
.
ori
g_name
=
p
.
name
();
probe
.
name
=
p
.
name
();
special_probes_
.
push_back
(
probe
);
continue
;
...
...
@@ -83,7 +83,7 @@ int BPFtrace::add_probe(ast::Probe &p)
probe
.
path
=
attach_point
->
target
;
probe
.
attach_point
=
func
;
probe
.
type
=
probetype
(
attach_point
->
provider
);
probe
.
pro
g_name
=
p
.
name
();
probe
.
ori
g_name
=
p
.
name
();
probe
.
name
=
attach_point
->
name
(
func
);
probe
.
freq
=
attach_point
->
freq
;
probes_
.
push_back
(
probe
);
...
...
@@ -117,6 +117,8 @@ std::set<std::string> BPFtrace::find_wildcard_matches(const std::string &prefix,
if
(
std
::
regex_search
(
line
,
match
,
func_regex
))
{
assert
(
match
.
size
()
==
2
);
// skip the ".part.N" kprobe variants, as they can't be traced:
if
(
std
::
strstr
(
match
.
str
(
1
).
c_str
(),
".part."
)
==
NULL
)
matches
.
insert
(
match
[
1
]);
}
}
...
...
@@ -201,6 +203,7 @@ void perf_event_printer(void *cb_cookie, void *data, int size)
auto
args
=
std
::
get
<
1
>
(
bpftrace
->
printf_args_
[
printf_id
]);
std
::
vector
<
uint64_t
>
arg_values
;
std
::
vector
<
std
::
unique_ptr
<
char
>>
resolved_symbols
;
char
*
name
;
for
(
auto
arg
:
args
)
{
switch
(
arg
.
type
)
...
...
@@ -221,6 +224,10 @@ void perf_event_printer(void *cb_cookie, void *data, int size)
bpftrace
->
resolve_usym
(
*
(
uint64_t
*
)
arg_data
).
c_str
()));
arg_values
.
push_back
((
uint64_t
)
resolved_symbols
.
back
().
get
());
break
;
case
Type
:
:
name
:
name
=
strdup
(
bpftrace
->
resolve_name
(
*
(
uint64_t
*
)
arg_data
).
c_str
());
arg_values
.
push_back
((
uint64_t
)
name
);
break
;
default:
abort
();
}
...
...
@@ -265,9 +272,18 @@ void perf_event_lost(void *cb_cookie, uint64_t lost)
std
::
unique_ptr
<
AttachedProbe
>
BPFtrace
::
attach_probe
(
Probe
&
probe
,
const
BpfOrc
&
bpforc
)
{
auto
func
=
bpforc
.
sections_
.
find
(
"s_"
+
probe
.
prog_name
);
// use the single-probe program if it exists (as is the case with wildcards
// and the name builtin, which must be expanded into separate programs per
// probe), else try to find a the program based on the original probe name
// that includes wildcards.
auto
func
=
bpforc
.
sections_
.
find
(
"s_"
+
probe
.
name
);
if
(
func
==
bpforc
.
sections_
.
end
())
func
=
bpforc
.
sections_
.
find
(
"s_"
+
probe
.
orig_name
);
if
(
func
==
bpforc
.
sections_
.
end
())
{
if
(
probe
.
name
!=
probe
.
orig_name
)
std
::
cerr
<<
"Code not generated for probe: "
<<
probe
.
name
<<
" from: "
<<
probe
.
orig_name
<<
std
::
endl
;
else
std
::
cerr
<<
"Code not generated for probe: "
<<
probe
.
name
<<
std
::
endl
;
return
nullptr
;
}
...
...
@@ -309,6 +325,9 @@ int BPFtrace::run(std::unique_ptr<BpfOrc> bpforc)
attached_probes_
.
push_back
(
std
::
move
(
attached_probe
));
}
if
(
bt_verbose
)
std
::
cerr
<<
"Running..."
<<
std
::
endl
;
poll_perf_events
(
epollfd
);
attached_probes_
.
clear
();
...
...
@@ -623,6 +642,8 @@ int BPFtrace::print_map(IMap &map, uint32_t top, uint32_t div)
std
::
cout
<<
min_value
(
value
,
ncpus_
)
/
div
<<
std
::
endl
;
else
if
(
map
.
type_
.
type
==
Type
::
max
)
std
::
cout
<<
max_value
(
value
,
ncpus_
)
/
div
<<
std
::
endl
;
else
if
(
map
.
type_
.
type
==
Type
::
name
)
std
::
cout
<<
resolve_name
(
*
(
uint64_t
*
)
value
.
data
())
<<
std
::
endl
;
else
std
::
cout
<<
*
(
int64_t
*
)
value
.
data
()
/
div
<<
std
::
endl
;
}
...
...
@@ -1044,6 +1065,12 @@ std::string BPFtrace::resolve_usym(uintptr_t addr) const
return
symbol
.
str
();
}
std
::
string
BPFtrace
::
resolve_name
(
uint64_t
name_id
)
{
assert
(
name_id
<
name_ids_
.
size
());
return
name_ids_
[
name_id
];
}
void
BPFtrace
::
sort_by_key
(
std
::
vector
<
SizedType
>
key_args
,
std
::
vector
<
std
::
pair
<
std
::
vector
<
uint8_t
>
,
std
::
vector
<
uint8_t
>>>
&
values_by_key
)
{
...
...
src/bpftrace.h
View file @
b57abde0
...
...
@@ -37,6 +37,7 @@ public:
std
::
string
get_stack
(
uint32_t
stackid
,
bool
ustack
,
int
indent
=
0
);
std
::
string
resolve_sym
(
uintptr_t
addr
,
bool
show_offset
=
false
);
std
::
string
resolve_usym
(
uintptr_t
addr
)
const
;
std
::
string
resolve_name
(
uint64_t
name_id
);
int
pid_
;
std
::
map
<
std
::
string
,
std
::
unique_ptr
<
IMap
>>
maps_
;
...
...
@@ -46,14 +47,15 @@ public:
std
::
unique_ptr
<
IMap
>
stackid_map_
;
std
::
unique_ptr
<
IMap
>
join_map_
;
std
::
unique_ptr
<
IMap
>
perf_event_map_
;
std
::
vector
<
std
::
string
>
name_ids_
;
int
join_argnum_
;
int
join_argsize_
;
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
);
virtual
std
::
set
<
std
::
string
>
find_wildcard_matches
(
const
std
::
string
&
prefix
,
const
std
::
string
&
attach_point
,
const
std
::
string
&
file_name
);
protected:
virtual
std
::
set
<
std
::
string
>
find_wildcard_matches
(
const
std
::
string
&
prefix
,
const
std
::
string
&
attach_point
,
const
std
::
string
&
file_name
);
std
::
vector
<
Probe
>
probes_
;
std
::
vector
<
Probe
>
special_probes_
;
...
...
src/lexer.l
View file @
b57abde0
...
...
@@ -38,7 +38,7 @@ header <(\\.|[_\-\./a-zA-Z0-9])*>
{vspace}+ { loc.lines(yyleng); loc.step(); }
"//".*$ // Comments
pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func {
pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func
|name
{
return Parser::make_BUILTIN(yytext, loc); }
{ident} { return Parser::make_IDENT(yytext, loc); }
{path} { return Parser::make_PATH(yytext, loc); }
...
...
src/mapkey.cpp
View file @
b57abde0
...
...
@@ -73,6 +73,8 @@ std::string MapKey::argument_value(BPFtrace &bpftrace,
return
bpftrace
.
resolve_sym
(
*
(
uint64_t
*
)
data
);
case
Type
:
:
usym
:
return
bpftrace
.
resolve_usym
(
*
(
uint64_t
*
)
data
);
case
Type
:
:
name
:
return
bpftrace
.
name_ids_
[
*
(
uint64_t
*
)
data
];
case
Type
:
:
string
:
return
std
::
string
((
char
*
)
data
);
}
...
...
src/printf.cpp
View file @
b57abde0
...
...
@@ -32,7 +32,7 @@ std::string verify_format_string(const std::string &fmt, std::vector<SizedType>
for
(
int
i
=
0
;
i
<
num_args
;
i
++
,
token_iter
++
)
{
Type
arg_type
=
args
.
at
(
i
).
type
;
if
(
arg_type
==
Type
::
sym
||
arg_type
==
Type
::
usym
)
if
(
arg_type
==
Type
::
sym
||
arg_type
==
Type
::
usym
||
arg_type
==
Type
::
name
)
arg_type
=
Type
::
string
;
// Symbols should be printed as strings
int
offset
=
1
;
...
...
src/types.cpp
View file @
b57abde0
...
...
@@ -41,6 +41,7 @@ std::string typestr(Type t)
case
Type
:
:
sym
:
return
"sym"
;
break
;
case
Type
:
:
usym
:
return
"usym"
;
break
;
case
Type
:
:
cast
:
return
"cast"
;
break
;
case
Type
:
:
name
:
return
"name"
;
break
;
default:
abort
();
}
}
...
...
src/types.h
View file @
b57abde0
...
...
@@ -30,6 +30,7 @@ enum class Type
usym
,
cast
,
join
,
name
,
};
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Type
type
);
...
...
@@ -71,10 +72,11 @@ class Probe
{
public:
ProbeType
type
;
std
::
string
path
;
std
::
string
attach_point
;
std
::
string
prog_name
;
std
::
string
name
;
std
::
string
path
;
// file path if used
std
::
string
attach_point
;
// probe name (last component)
std
::
string
orig_name
;
// original full probe name,
// before wildcard expansion
std
::
string
name
;
// full probe name
uint64_t
loc
;
int
freq
;
};
...
...
tests/bpftrace.cpp
View file @
b57abde0
This diff is collapsed.
Click to expand it.
tests/codegen.cpp
View file @
b57abde0
...
...
@@ -667,6 +667,118 @@ attributes #1 = { argmemonly nounwind }
)EXPECTED"
);
}
TEST
(
codegen
,
builtin_name
)
{
test
(
"tracepoint:syscalls:sys_enter_nanosleep { @x = name }"
,
R"EXPECTED(; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
define i64 @"tracepoint:syscalls:sys_enter_nanosleep"(i8* nocapture readnone) local_unnamed_addr section "s_tracepoint:syscalls:sys_enter_nanosleep" {
entry:
%"@x_val" = alloca i64, align 8
%"@x_key" = alloca i64, align 8
%1 = bitcast i64* %"@x_key" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %1)
store i64 0, i64* %"@x_key", align 8
%2 = bitcast i64* %"@x_val" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %2)
store i64 0, i64* %"@x_val", align 8
%pseudo = tail call i64 @llvm.bpf.pseudo(i64 1, i64 1)
%update_elem = call i64 inttoptr (i64 2 to i64 (i8*, i8*, i8*, i64)*)(i64 %pseudo, i64* nonnull %"@x_key", i64* nonnull %"@x_val", i64 0)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %1)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %2)
ret i64 0
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { nounwind }
attributes #1 = { argmemonly nounwind }
)EXPECTED"
);
}
TEST
(
codegen
,
builtin_func_wild
)
{
test
(
"tracepoint:syscalls:sys_enter_nanoslee* { @x = func }"
,
R"EXPECTED(; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
define i64 @"tracepoint:syscalls:sys_enter_nanoslee*"(i8*) local_unnamed_addr section "s_tracepoint:syscalls:sys_enter_nanoslee*" {
entry:
%"@x_val" = alloca i64, align 8
%"@x_key" = alloca i64, align 8
%func = alloca i64, align 8
%1 = bitcast i64* %func to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %1)
%2 = getelementptr i8, i8* %0, i64 128
%probe_read = call i64 inttoptr (i64 4 to i64 (i8*, i64, i8*)*)(i64* nonnull %func, i64 8, i8* %2)
%3 = load i64, i64* %func, align 8
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %1)
%4 = bitcast i64* %"@x_key" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %4)
store i64 0, i64* %"@x_key", align 8
%5 = bitcast i64* %"@x_val" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %5)
store i64 %3, i64* %"@x_val", align 8
%pseudo = call i64 @llvm.bpf.pseudo(i64 1, i64 1)
%update_elem = call i64 inttoptr (i64 2 to i64 (i8*, i8*, i8*, i64)*)(i64 %pseudo, i64* nonnull %"@x_key", i64* nonnull %"@x_val", i64 0)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %4)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %5)
ret i64 0
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { nounwind }
attributes #1 = { argmemonly nounwind }
)EXPECTED"
);
}
TEST
(
codegen
,
builtin_name_wild
)
{
test
(
"tracepoint:syscalls:sys_enter_nanoslee* { @x = name }"
,
R"EXPECTED(; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
define i64 @"tracepoint:syscalls:sys_enter_nanosleep"(i8* nocapture readnone) local_unnamed_addr section "s_tracepoint:syscalls:sys_enter_nanosleep" {
entry:
%"@x_val" = alloca i64, align 8
%"@x_key" = alloca i64, align 8
%1 = bitcast i64* %"@x_key" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %1)
store i64 0, i64* %"@x_key", align 8
%2 = bitcast i64* %"@x_val" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %2)
store i64 1, i64* %"@x_val", align 8
%pseudo = tail call i64 @llvm.bpf.pseudo(i64 1, i64 1)
%update_elem = call i64 inttoptr (i64 2 to i64 (i8*, i8*, i8*, i64)*)(i64 %pseudo, i64* nonnull %"@x_key", i64* nonnull %"@x_val", i64 0)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %1)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %2)
ret i64 0
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { nounwind }
attributes #1 = { argmemonly nounwind }
)EXPECTED"
);
}
TEST
(
codegen
,
call_reg
)
// Identical to builtin_func apart from variable names
{
test
(
"kprobe:f { @x = reg(
\"
ip
\"
) }"
,
...
...
tests/parser.cpp
View file @
b57abde0
...
...
@@ -35,6 +35,7 @@ TEST(Parser, builtin_variables)
test
(
"kprobe:f { arg0 }"
,
"Program
\n
kprobe:f
\n
builtin: arg0
\n
"
);
test
(
"kprobe:f { retval }"
,
"Program
\n
kprobe:f
\n
builtin: retval
\n
"
);
test
(
"kprobe:f { func }"
,
"Program
\n
kprobe:f
\n
builtin: func
\n
"
);
test
(
"kprobe:f { name }"
,
"Program
\n
kprobe:f
\n
builtin: name
\n
"
);
}
TEST
(
Parser
,
map_assign
)
...
...
tests/semantic_analyser.cpp
View file @
b57abde0
...
...
@@ -73,6 +73,7 @@ TEST(semantic_analyser, builtin_variables)
test
(
"kprobe:f { arg0 }"
,
0
);
test
(
"kprobe:f { retval }"
,
0
);
test
(
"kprobe:f { func }"
,
0
);
test
(
"kprobe:f { name }"
,
0
);
// test("kprobe:f { fake }", 1);
}
...
...
@@ -260,6 +261,24 @@ TEST(semantic_analyser, call_reg)
test
(
"kprobe:f { reg(123); }"
,
1
);
}
TEST
(
semantic_analyser
,
call_func
)
{
test
(
"kprobe:f { @[func] = count(); }"
,
0
);
test
(
"kprobe:f { printf(
\"
%s
\"
, func); }"
,
0
);
test
(
"kprobe:f { func(
\"
blah
\"
); }"
,
1
);
test
(
"kprobe:f { func(); }"
,
1
);
test
(
"kprobe:f { func(123); }"
,
1
);
}
TEST
(
semantic_analyser
,
call_name
)
{
test
(
"kprobe:f { @[name] = count(); }"
,
0
);
test
(
"kprobe:f { printf(
\"
%s
\"
, name); }"
,
0
);
test
(
"kprobe:f { name(
\"
blah
\"
); }"
,
1
);
test
(
"kprobe:f { name(); }"
,
1
);
test
(
"kprobe:f { name(123); }"
,
1
);
}
TEST
(
semantic_analyser
,
map_reassignment
)
{
test
(
"kprobe:f { @x = 1; @x = 2; }"
,
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