forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
491 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
set(EXAMPLE_PROGRAMS hello_world.py) | ||
install(PROGRAMS ${EXAMPLE_PROGRAMS} DESTINATION share/bcc/examples) | ||
|
||
add_subdirectory(cpp) | ||
add_subdirectory(lua) | ||
add_subdirectory(networking) | ||
add_subdirectory(tracing) | ||
add_subdirectory(lua) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Copyright (c) Facebook, Inc. | ||
# Licensed under the Apache License, Version 2.0 (the "License") | ||
|
||
include_directories(${CMAKE_SOURCE_DIR}/src/cc) | ||
|
||
add_executable(HelloWorld HelloWorld.cc) | ||
target_link_libraries(HelloWorld bcc-static) | ||
install (TARGETS HelloWorld DESTINATION share/bcc/examples/cpp) | ||
|
||
add_executable(CPUDistribution CPUDistribution.cc) | ||
target_link_libraries(CPUDistribution bcc-static) | ||
install (TARGETS CPUDistribution DESTINATION share/bcc/examples/cpp) | ||
|
||
add_executable(RecordMySQLQuery RecordMySQLQuery.cc) | ||
target_link_libraries(RecordMySQLQuery bcc-static) | ||
install (TARGETS RecordMySQLQuery DESTINATION share/bcc/examples/cpp) | ||
|
||
add_executable(TCPSendStack TCPSendStack.cc) | ||
target_link_libraries(TCPSendStack bcc-static) | ||
install (TARGETS TCPSendStack DESTINATION share/bcc/examples/cpp) | ||
|
||
add_executable(RandomRead RandomRead.cc) | ||
target_link_libraries(RandomRead bcc-static) | ||
install (TARGETS RandomRead DESTINATION share/bcc/examples/cpp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* CPUDistribution Show load distribution across CPU cores during a period of | ||
* time. For Linux, uses BCC, eBPF. Embedded C. | ||
* | ||
* Basic example of BCC and kprobes. | ||
* | ||
* USAGE: CPUDistribution [duration] | ||
* | ||
* Copyright (c) Facebook, Inc. | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <cstdlib> | ||
#include <iomanip> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include "BPF.h" | ||
|
||
const std::string BPF_PROGRAM = R"( | ||
#include <linux/sched.h> | ||
#include <uapi/linux/ptrace.h> | ||
BPF_HASH(pid_to_cpu, pid_t, int); | ||
BPF_HASH(pid_to_ts, pid_t, uint64_t); | ||
BPF_HASH(cpu_time, int, uint64_t); | ||
int task_switch_event(struct pt_regs *ctx, struct task_struct *prev) { | ||
pid_t prev_pid = prev->pid; | ||
int* prev_cpu = pid_to_cpu.lookup(&prev_pid); | ||
uint64_t* prev_ts = pid_to_ts.lookup(&prev_pid); | ||
pid_t cur_pid = bpf_get_current_pid_tgid(); | ||
int cur_cpu = bpf_get_smp_processor_id(); | ||
uint64_t cur_ts = bpf_ktime_get_ns(); | ||
uint64_t this_cpu_time = 0; | ||
if (prev_ts) { | ||
pid_to_ts.delete(&prev_pid); | ||
this_cpu_time = (cur_ts - *prev_ts); | ||
} | ||
if (prev_cpu) { | ||
pid_to_cpu.delete(&prev_pid); | ||
if (this_cpu_time > 0) { | ||
int cpu_key = *prev_cpu; | ||
uint64_t* history_time = cpu_time.lookup(&cpu_key); | ||
if (history_time) | ||
this_cpu_time += *history_time; | ||
cpu_time.update(&cpu_key, &this_cpu_time); | ||
} | ||
} | ||
pid_to_cpu.update(&cur_pid, &cur_cpu); | ||
pid_to_ts.update(&cur_pid, &cur_ts); | ||
return 0; | ||
} | ||
)"; | ||
|
||
int main(int argc, char** argv) { | ||
ebpf::BPF bpf; | ||
auto init_res = bpf.init(BPF_PROGRAM); | ||
if (std::get<0>(init_res) != 0) { | ||
std::cerr << std::get<1>(init_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
auto attach_res = | ||
bpf.attach_kprobe("finish_task_switch", "task_switch_event"); | ||
if (std::get<0>(attach_res) != 0) { | ||
std::cerr << std::get<1>(attach_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
int probe_time = 10; | ||
if (argc == 2) { | ||
probe_time = atoi(argv[1]); | ||
} | ||
std::cout << "Probing for " << probe_time << " seconds" << std::endl; | ||
sleep(probe_time); | ||
|
||
auto table = bpf.get_hash_table<int, uint64_t>("cpu_time"); | ||
auto num_cores = sysconf(_SC_NPROCESSORS_ONLN); | ||
for (int i = 0; i < num_cores; i++) { | ||
std::cout << "CPU " << std::setw(2) << i << " worked for "; | ||
std::cout << (table[i] / 1000000.0) << " ms." << std::endl; | ||
} | ||
|
||
auto detach_res = bpf.detach_kprobe("finish_task_switch"); | ||
if (std::get<0>(detach_res) != 0) { | ||
std::cerr << std::get<1>(detach_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <fstream> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include "BPF.h" | ||
|
||
const std::string BPF_PROGRAM = R"( | ||
int on_sys_clone(void *ctx) { | ||
bpf_trace_printk("Hello, World! Here I did a sys_clone call!\n"); | ||
return 0; | ||
} | ||
)"; | ||
|
||
int main() { | ||
ebpf::BPF bpf; | ||
auto init_res = bpf.init(BPF_PROGRAM); | ||
if (std::get<0>(init_res) != 0) { | ||
std::cerr << std::get<1>(init_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
std::ifstream pipe("/sys/kernel/debug/tracing/trace_pipe"); | ||
std::string line; | ||
|
||
auto attach_res = bpf.attach_kprobe("sys_clone", "on_sys_clone"); | ||
if (std::get<0>(attach_res) != 0) { | ||
std::cerr << std::get<1>(attach_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
while (true) { | ||
if (std::getline(pipe, line)) { | ||
std::cout << line << std::endl; | ||
// Detach the probe if we got at least one line. | ||
auto detach_res = bpf.detach_kprobe("sys_clone"); | ||
if (std::get<0>(detach_res) != 0) { | ||
std::cerr << std::get<1>(detach_res) << std::endl; | ||
return 1; | ||
} | ||
break; | ||
} else { | ||
std::cout << "Waiting for a sys_clone event" << std::endl; | ||
sleep(1); | ||
} | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* RandomRead Monitor random number read events. | ||
* For Linux, uses BCC, eBPF. Embedded C. | ||
* | ||
* Basic example of BCC Tracepoint and perf buffer. | ||
* | ||
* USAGE: RandomRead | ||
* | ||
* Copyright (c) Facebook, Inc. | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
*/ | ||
|
||
#include <signal.h> | ||
#include <iostream> | ||
|
||
#include "BPF.h" | ||
|
||
const std::string BPF_PROGRAM = R"( | ||
#include <linux/sched.h> | ||
#include <uapi/linux/ptrace.h> | ||
struct urandom_read_args { | ||
// See /sys/kernel/debug/tracing/events/random/urandom_read/format | ||
uint64_t common__unused; | ||
int got_bits; | ||
int pool_left; | ||
int input_left; | ||
}; | ||
struct event_t { | ||
int pid; | ||
char comm[16]; | ||
int got_bits; | ||
}; | ||
BPF_PERF_OUTPUT(events); | ||
int on_urandom_read(struct urandom_read_args* attr) { | ||
struct event_t event = {}; | ||
event.pid = bpf_get_current_pid_tgid(); | ||
bpf_get_current_comm(&event.comm, sizeof(event.comm)); | ||
event.got_bits = attr->got_bits; | ||
events.perf_submit(attr, &event, sizeof(event)); | ||
return 0; | ||
} | ||
)"; | ||
|
||
// Define the same struct to use in user space. | ||
struct event_t { | ||
int pid; | ||
char comm[16]; | ||
int got_bits; | ||
}; | ||
|
||
void handle_output(void* cb_cookie, void* data, int data_size) { | ||
auto event = static_cast<event_t*>(data); | ||
std::cout << "PID: " << event->pid << " (" << event->comm << ") " | ||
<< "Read " << event->got_bits << " bits" << std::endl; | ||
} | ||
|
||
ebpf::BPF* bpf; | ||
|
||
void signal_handler(int s) { | ||
std::cerr << "Terminating..." << std::endl; | ||
delete bpf; | ||
exit(0); | ||
} | ||
|
||
int main(int argc, char** argv) { | ||
bpf = new ebpf::BPF(); | ||
auto init_res = bpf->init(BPF_PROGRAM); | ||
if (std::get<0>(init_res) != 0) { | ||
std::cerr << std::get<1>(init_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
auto attach_res = | ||
bpf->attach_tracepoint("random:urandom_read", "on_urandom_read"); | ||
if (std::get<0>(attach_res) != 0) { | ||
std::cerr << std::get<1>(attach_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
auto open_res = bpf->open_perf_buffer("events", &handle_output); | ||
if (std::get<0>(open_res) != 0) { | ||
std::cerr << std::get<1>(open_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
signal(SIGINT, signal_handler); | ||
std::cout << "Started tracing, hit Ctrl-C to terminate." << std::endl; | ||
while (true) | ||
bpf->poll_perf_buffer("events"); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* RecordMySQLQuery Record MySQL queries by probing the alloc_query() function | ||
* in mysqld. For Linux, uses BCC, eBPF. Embedded C. | ||
* | ||
* Basic example of BCC and uprobes. | ||
* | ||
* Copyright (c) Facebook, Inc. | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <algorithm> | ||
#include <cstdlib> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#include "BPF.h" | ||
|
||
const std::string BPF_PROGRAM = R"( | ||
#include <linux/ptrace.h> | ||
struct query_probe_t { | ||
uint64_t ts; | ||
pid_t pid; | ||
char query[100]; | ||
}; | ||
BPF_HASH(queries, struct query_probe_t, int); | ||
int probe_mysql_query(struct pt_regs *ctx, void* thd, char* query, size_t len) { | ||
if (query) { | ||
struct query_probe_t key = {}; | ||
key.ts = bpf_ktime_get_ns(); | ||
key.pid = bpf_get_current_pid_tgid(); | ||
bpf_probe_read(&key.query, sizeof(key.query), query); | ||
int one = 1; | ||
queries.update(&key, &one); | ||
} | ||
return 0; | ||
} | ||
)"; | ||
const std::string ALLOC_QUERY_FUNC = "_Z11alloc_queryP3THDPKcj"; | ||
|
||
// Define the same struct to use in user space. | ||
struct query_probe_t { | ||
uint64_t ts; | ||
pid_t pid; | ||
char query[100]; | ||
}; | ||
|
||
int main(int argc, char** argv) { | ||
if (argc < 2) { | ||
std::cout << "USAGE: RecordMySQLQuery PATH_TO_MYSQLD [duration]" | ||
<< std::endl; | ||
exit(1); | ||
} | ||
|
||
std::string mysql_path(argv[1]); | ||
std::cout << "Using mysqld path: " << mysql_path << std::endl; | ||
|
||
ebpf::BPF bpf; | ||
auto init_res = bpf.init(BPF_PROGRAM); | ||
if (std::get<0>(init_res) != 0) { | ||
std::cerr << std::get<1>(init_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
auto attach_res = | ||
bpf.attach_uprobe(mysql_path, ALLOC_QUERY_FUNC, "probe_mysql_query"); | ||
if (std::get<0>(attach_res) != 0) { | ||
std::cerr << std::get<1>(attach_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
int probe_time = 10; | ||
if (argc >= 3) | ||
probe_time = atoi(argv[2]); | ||
std::cout << "Probing for " << probe_time << " seconds" << std::endl; | ||
sleep(probe_time); | ||
|
||
auto table_handle = bpf.get_hash_table<query_probe_t, int>("queries"); | ||
auto table = table_handle.get_table_offline(); | ||
std::sort(table.begin(), table.end(), [](std::pair<query_probe_t, int> a, | ||
std::pair<query_probe_t, int> b) { | ||
return a.first.ts < b.first.ts; | ||
}); | ||
std::cout << table.size() << " queries recorded:" << std::endl; | ||
for (auto it : table) { | ||
std::cout << "Time: " << it.first.ts << " PID: " << it.first.pid | ||
<< " Query: " << it.first.query << std::endl; | ||
} | ||
|
||
auto detach_res = bpf.detach_uprobe(mysql_path, ALLOC_QUERY_FUNC); | ||
if (std::get<0>(detach_res) != 0) { | ||
std::cerr << std::get<1>(detach_res) << std::endl; | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} |
Oops, something went wrong.