Commit 50a66d23 authored by williangaspar's avatar williangaspar
parent 6da344b8
......@@ -53,7 +53,7 @@ This is a work in progress. If something is missing, check the bpftrace source t
- [3. `time()`: Time](#3-time-time)
- [4. `join()`: Join](#4-join-join)
- [5. `str()`: Strings](#5-str-strings)
- [6. `sym()`: Symbol Resolution, Kernel-Level](#6-str-symbol-resolution-kernel-level)
- [6. `ksym()`: Symbol Resolution, Kernel-Level](#6-str-symbol-resolution-kernel-level)
- [7. `usym()`: Symbol Resolution, User-Level](#7-usym-symbol-resolution-user-level)
- [8. `kaddr()`: Address Resolution, Kernel-Level](#8-kaddr-address-resolution-kernel-level)
- [9. `uaddr()`: Address Resolution, User-Level](#9-uaddr-address-resolution-user-level)
......@@ -1260,7 +1260,7 @@ Tracing block I/O sizes > 0 bytes
- `time(char *fmt)` - Print formatted time
- `join(char *arr[])` - Print the array
- `str(char *s [, int length])` - Returns the string pointed to by s
- `sym(void *p)` - Resolve kernel address
- `ksym(void *p)` - Resolve kernel address
- `usym(void *p)` - Resolve user space address
- `kaddr(char *name)` - Resolve kernel symbol name
- `uaddr(char *name)` - Resolve user-level symbol name
......@@ -1269,7 +1269,7 @@ Tracing block I/O sizes > 0 bytes
- `exit()` - Quit bpftrace
- `cgroupid(char *path)` - Resolve cgroup ID
Some of these are asynchronous: the kernel queues the event, but some time later (milliseconds) it is processed in user-space. The asynchronous actions are: <tt>printf()</tt>, <tt>time()</tt>, and <tt>join()</tt>. Both <tt>sym()</tt> and <tt>usym()</tt>, as well as the variables <tt>kstack</tt> and </tt>ustack</tt>, record addresses synchronously, but then do symbol translation asynchronously.
Some of these are asynchronous: the kernel queues the event, but some time later (milliseconds) it is processed in user-space. The asynchronous actions are: <tt>printf()</tt>, <tt>time()</tt>, and <tt>join()</tt>. Both <tt>ksym()</tt> and <tt>usym()</tt>, as well as the variables <tt>kstack</tt> and </tt>ustack</tt>, record addresses synchronously, but then do symbol translation asynchronously.
A selection of these are discussed in the following sections.
......@@ -1374,14 +1374,14 @@ We can trace strings that are displayed in a bash shell. Some length tuning is e
<anon@anon-VirtualBox:~$ >
```
## 6. `sym()`: Symbol resolution, kernel-level
## 6. `ksym()`: Symbol resolution, kernel-level
Syntax: `sym(addr)`
Syntax: `ksym(addr)`
Examples:
```
# ./build/src/bpftrace -e 'kprobe:do_nanosleep { printf("%s\n", sym(reg("ip"))); }'
# ./build/src/bpftrace -e 'kprobe:do_nanosleep { printf("%s\n", ksym(reg("ip"))); }'
Attaching 1 probe...
do_nanosleep
do_nanosleep
......@@ -1444,7 +1444,7 @@ Syntax: `reg(char *name)`
Examples:
```
# ./src/bpftrace -e 'kprobe:tcp_sendmsg { @[sym(reg("ip"))] = count(); }'
# ./src/bpftrace -e 'kprobe:tcp_sendmsg { @[ksym(reg("ip"))] = count(); }'
Attaching 1 probe...
^C
......
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include "utils.h"
#include "types.h"
namespace bpftrace {
namespace ast {
static bool PRINT_STACK_DEPRICATED = true;
class Visitor;
class Node {
......@@ -59,17 +57,7 @@ public:
class Builtin : public Expression {
public:
explicit Builtin(std::string ident) : ident(ident) {
if (ident == "stack") {
if (PRINT_STACK_DEPRICATED)
{
std::cerr << "warning: stack is deprecated and will be removed in the future. Use kstack instead" << std::endl;
PRINT_STACK_DEPRICATED = false;
}
this->ident = "kstack";
}
}
explicit Builtin(std::string ident) : ident(is_deprecated(ident)) {}
std::string ident;
int probe_id;
......@@ -78,8 +66,8 @@ public:
class Call : public Expression {
public:
explicit Call(std::string &func) : func(func), vargs(nullptr) { }
Call(std::string &func, ExpressionList *vargs) : func(func), vargs(vargs) { }
explicit Call(std::string &func) : func(is_deprecated(func)), vargs(nullptr) { }
Call(std::string &func, ExpressionList *vargs) : func(is_deprecated(func)), vargs(vargs) { }
std::string func;
ExpressionList *vargs;
......
......@@ -425,7 +425,7 @@ void CodegenLLVM::visit(Call &call)
b_.SetInsertPoint(zero);
expr_ = nullptr;
}
else if (call.func == "sym")
else if (call.func == "ksym")
{
// We want expr_ to just pass through from the child node - don't set it here
call.vargs->front()->accept(*this);
......
......@@ -78,7 +78,7 @@ void SemanticAnalyser::visit(Builtin &builtin)
if (type == ProbeType::kprobe ||
type == ProbeType::kretprobe ||
type == ProbeType::tracepoint)
builtin.type = SizedType(Type::sym, 8);
builtin.type = SizedType(Type::ksym, 8);
else if (type == ProbeType::uprobe || type == ProbeType::uretprobe)
builtin.type = SizedType(Type::usym, 16);
else
......@@ -235,12 +235,12 @@ void SemanticAnalyser::visit(Call &call)
}
}
}
else if (call.func == "sym" || call.func == "usym") {
else if (call.func == "ksym" || call.func == "usym") {
check_nargs(call, 1);
check_arg(call, Type::integer, 0);
if (call.func == "sym")
call.type = SizedType(Type::sym, 8);
if (call.func == "ksym")
call.type = SizedType(Type::ksym, 8);
else if (call.func == "usym")
call.type = SizedType(Type::usym, 16);
}
......
......@@ -389,10 +389,10 @@ std::vector<std::unique_ptr<IPrintable>> BPFtrace::get_arg_values(const std::vec
std::make_unique<PrintableCString>(
reinterpret_cast<char *>(arg_data+arg.offset)));
break;
case Type::sym:
case Type::ksym:
arg_values.push_back(
std::make_unique<PrintableString>(
resolve_sym(*reinterpret_cast<uint64_t*>(arg_data+arg.offset))));
resolve_ksym(*reinterpret_cast<uint64_t*>(arg_data+arg.offset))));
break;
case Type::usym:
arg_values.push_back(
......@@ -882,8 +882,8 @@ int BPFtrace::print_map(IMap &map, uint32_t top, uint32_t div)
std::cout << get_stack(*(uint64_t*)value.data(), false, 8);
else if (map.type_.type == Type::ustack)
std::cout << get_stack(*(uint64_t*)value.data(), true, 8);
else if (map.type_.type == Type::sym)
std::cout << resolve_sym(*(uintptr_t*)value.data());
else if (map.type_.type == Type::ksym)
std::cout << resolve_ksym(*(uintptr_t*)value.data());
else if (map.type_.type == Type::usym)
std::cout << resolve_usym(*(uintptr_t*)value.data(), *(uint64_t*)(value.data() + 8));
else if (map.type_.type == Type::inet)
......@@ -1435,7 +1435,7 @@ std::string BPFtrace::get_stack(uint64_t stackidpid, bool ustack, int indent)
if (addr == 0)
break;
if (!ustack)
stack << padding << resolve_sym(addr, true) << std::endl;
stack << padding << resolve_ksym(addr, true) << std::endl;
else
stack << padding << resolve_usym(addr, pid, true) << std::endl;
}
......@@ -1486,19 +1486,19 @@ std::vector<std::string> BPFtrace::split_string(std::string &str, char split_by)
return elems;
}
std::string BPFtrace::resolve_sym(uintptr_t addr, bool show_offset)
std::string BPFtrace::resolve_ksym(uintptr_t addr, bool show_offset)
{
struct bcc_symbol sym;
struct bcc_symbol ksym;
std::ostringstream symbol;
if (!ksyms_)
ksyms_ = bcc_symcache_new(-1, nullptr);
if (bcc_symcache_resolve(ksyms_, addr, &sym) == 0)
if (bcc_symcache_resolve(ksyms_, addr, &ksym) == 0)
{
symbol << sym.name;
symbol << ksym.name;
if (show_offset)
symbol << "+" << sym.offset;
symbol << "+" << ksym.offset;
}
else
{
......@@ -1606,7 +1606,7 @@ std::string BPFtrace::resolve_inet(int af, uint64_t inet)
std::string BPFtrace::resolve_usym(uintptr_t addr, int pid, bool show_offset)
{
struct bcc_symbol sym;
struct bcc_symbol usym;
std::ostringstream symbol;
struct bcc_symbol_option symopts;
void *psyms;
......@@ -1627,11 +1627,11 @@ std::string BPFtrace::resolve_usym(uintptr_t addr, int pid, bool show_offset)
psyms = pid_sym_[pid];
}
if (bcc_symcache_resolve(psyms, addr, &sym) == 0)
if (bcc_symcache_resolve(psyms, addr, &usym) == 0)
{
symbol << sym.name;
symbol << usym.name;
if (show_offset)
symbol << "+" << sym.offset;
symbol << "+" << usym.offset;
}
else
{
......
......@@ -58,7 +58,7 @@ public:
int clear_map_ident(const std::string &ident);
int zero_map_ident(const std::string &ident);
std::string get_stack(uint64_t stackidpid, bool ustack, int indent=0);
std::string resolve_sym(uintptr_t addr, bool show_offset=false);
std::string resolve_ksym(uintptr_t addr, bool show_offset=false);
std::string resolve_usym(uintptr_t addr, int pid, bool show_offset=false);
std::string resolve_inet(int af, uint64_t inet);
std::string resolve_uid(uintptr_t addr);
......
......@@ -75,8 +75,8 @@ std::string MapKey::argument_value(BPFtrace &bpftrace,
return bpftrace.get_stack(*(uint64_t*)data, false);
case Type::ustack:
return bpftrace.get_stack(*(uint64_t*)data, true);
case Type::sym:
return bpftrace.resolve_sym(*(uint64_t*)data);
case Type::ksym:
return bpftrace.resolve_ksym(*(uint64_t*)data);
case Type::usym:
return bpftrace.resolve_usym(*(uint64_t*)data, *(uint64_t*)(arg_data + 8));
case Type::inet:
......
......@@ -33,7 +33,7 @@ std::string verify_format_string(const std::string &fmt, std::vector<Field> args
for (int i=0; i<num_args; i++, token_iter++)
{
Type arg_type = args.at(i).type.type;
if (arg_type == Type::sym || arg_type == Type::usym || arg_type == Type::probe ||
if (arg_type == Type::ksym || arg_type == Type::usym || arg_type == Type::probe ||
arg_type == Type::username || arg_type == Type::kstack || arg_type == Type::ustack ||
arg_type == Type::inet)
arg_type = Type::string; // Symbols should be printed as strings
......
......@@ -46,7 +46,7 @@ std::string typestr(Type t)
case Type::kstack: return "kstack"; break;
case Type::ustack: return "ustack"; break;
case Type::string: return "string"; break;
case Type::sym: return "sym"; break;
case Type::ksym: return "ksym"; break;
case Type::usym: return "usym"; break;
case Type::inet: return "inet"; break;
case Type::cast: return "cast"; break;
......
......@@ -27,7 +27,7 @@ enum class Type
kstack,
ustack,
string,
sym,
ksym,
usym,
cast,
join,
......
......@@ -114,4 +114,27 @@ std::vector<std::string> get_kernel_cflags(
return cflags;
}
std::string is_deprecated(std::string &str)
{
std::vector<DeprecatedName>::iterator item;
for (item = DEPRECATED_LIST.begin(); item != DEPRECATED_LIST.end(); item++)
{
if (str.compare(item->old_name) == 0)
{
if (item->show_warning)
{
std::cerr << "warning: " << item->old_name << " is deprecated and will be removed in the future. ";
std::cerr << "Use " << item->new_name << "instead." << std::endl;
item->show_warning = false;
}
return item->new_name;
}
}
return str;
}
} // namespace bpftrace
......@@ -2,9 +2,24 @@
#include <string>
#include <vector>
#include <iostream>
namespace bpftrace {
struct DeprecatedName
{
std::string old_name;
std::string new_name;
bool show_warning = true;
};
static std::vector<DeprecatedName> DEPRECATED_LIST =
{
{ "stack", "kstack"},
{ "sym", "ksym"},
};
inline std::string GetProviderFromPath(std::string path);
bool has_wildcard(const std::string &str);
std::vector<int> get_online_cpus();
......@@ -12,6 +27,7 @@ std::vector<int> get_possible_cpus();
std::vector<std::string> get_kernel_cflags(
const char* uname_machine,
const std::string& kdir);
std::string is_deprecated(std::string &str);
} // namespace bpftrace
......
......@@ -29,8 +29,8 @@ BEFORE sleep 1s && /bin/sh -c 'exit 0' &
EXPECT P: /bin/sh
TIMEOUT 5
NAME sym
RUN bpftrace -e 'kprobe:do_nanosleep { printf("%s\n", sym(reg("ip"))); exit();}'
NAME ksym
RUN bpftrace -e 'kprobe:do_nanosleep { printf("%s\n", ksym(reg("ip"))); exit();}'
EXPECT P: /bin/sh
TIMEOUT 5
BEFORE sleep 1 && sleep 1 &
......
......@@ -89,6 +89,7 @@ TEST(semantic_analyser, builtin_functions)
test("kprobe:f { system(\"ls\\n\") }", 0);
test("kprobe:f { join(0) }", 0);
test("kprobe:f { sym(0xffff) }", 0);
test("kprobe:f { ksym(0xffff) }", 0);
test("kprobe:f { usym(0xffff) }", 0);
test("kprobe:f { ntop(2, 0xffff) }", 0);
test("kprobe:f { reg(\"ip\") }", 0);
......@@ -245,6 +246,11 @@ TEST(semantic_analyser, call_str_2_expr)
TEST(semantic_analyser, call_sym)
{
test("kprobe:f { ksym(arg0); }", 0);
test("kprobe:f { @x = ksym(arg0); }", 0);
test("kprobe:f { ksym(); }", 1);
test("kprobe:f { ksym(\"hello\"); }", 10);
test("kprobe:f { sym(arg0); }", 0);
test("kprobe:f { @x = sym(arg0); }", 0);
test("kprobe:f { sym(); }", 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment