Beispiel #1
0
    def gen_prog(self):
        for lang, _ in self.config.items():
            c = self.config[lang]
            if lang == 'DEFAULT':
                continue

            pids = [
                int(n) for n in check_output(
                    ["pidof", "-s", c['proccess_name_or_path']]).split()
            ]

            self.process.append({lang: pids})
            usdts = []
            for pid in pids:
                program = self.render(
                    prog=c['prog'],
                    pid=pid,
                    read_class=c['read_class'],
                    read_method=c['read_method'],
                )
                usdt = USDT(pid=pid)
                usdt.enable_probe_or_bail(c['entry_probe'], 'trace_entry')
                usdt.enable_probe_or_bail(c['return_probe'], 'trace_return')
                usdts.append(usdt)
            if len(usdts) > 0:
                self.attached_bpf.append(
                    {lang: BPF(text=program, usdt_contexts=usdts)})
Beispiel #2
0
 def generate(self, pids):
     for probe_name, func_name in self.probes:
         for pid in pids:
             usdt = USDT(pid=pid)
             usdt.enable_probe_or_bail(probe_name, func_name)
             self.usdt_tab.append(usdt)
     return "".join(self.txt)
Beispiel #3
0
 def __init__(self, usdt_name, pids, *args, **kwargs):
     # TODO(javierhonduco): Check what happens if we call this more than once on the same
     # Ruby binary
     for pid in pids:
         usdt = USDT(pid=pid)
         usdt.enable_probe_or_bail(usdt_name, self.BPF_FUNCTION_NAME.decode())
         self.usdt_contexts.append(usdt)
     super().__init__(pids, *args, **kwargs)
Beispiel #4
0
BPF_PERF_OUTPUT(threads);

int trace_pthread(struct pt_regs *ctx) {
    struct thread_event_t te = {};
    u64 start_routine = 0;
    char type[] = "pthread";
    te.native_id = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
    bpf_usdt_readarg(2, ctx, &start_routine);
    te.runtime_id = start_routine;  // This is really a function pointer
    __builtin_memcpy(&te.type, type, sizeof(te.type));
    threads.perf_submit(ctx, &te, sizeof(te));
    return 0;
}
"""
usdt.enable_probe_or_bail("pthread_start", "trace_pthread")

if args.language == "java":
    template = """
int %s(struct pt_regs *ctx) {
    char type[] = "%s";
    struct thread_event_t te = {};
    u64 nameptr = 0, id = 0, native_id = 0;
    bpf_usdt_readarg(1, ctx, &nameptr);
    bpf_usdt_readarg(3, ctx, &id);
    bpf_usdt_readarg(4, ctx, &native_id);
    bpf_probe_read(&te.name, sizeof(te.name), (void *)nameptr);
    te.runtime_id = id;
    te.native_id = native_id;
    __builtin_memcpy(&te.type, type, sizeof(te.type));
    threads.perf_submit(ctx, &te, sizeof(te));
Beispiel #5
0
    }
    sysentry.delete(&pid);
    return 0;
}
#endif  // LATENCY
#endif  // SYSCALLS
""".replace("READ_CLASS", read_class) \
   .replace("READ_METHOD", read_method) \
   .replace("PID_FILTER", "if ((pid >> 32) != %d) { return 0; }" % args.pid) \
   .replace("DEFINE_NOLANG", "#define NOLANG" if not language else "") \
   .replace("DEFINE_LATENCY", "#define LATENCY" if args.latency else "") \
   .replace("DEFINE_SYSCALLS", "#define SYSCALLS" if args.syscalls else "")

if language:
    usdt = USDT(pid=args.pid)
    usdt.enable_probe_or_bail(entry_probe, "trace_entry")
    if args.latency:
        usdt.enable_probe_or_bail(return_probe, "trace_return")
else:
    usdt = None

if args.ebpf or args.verbose:
    if args.verbose and usdt:
        print(usdt.get_text())
    print(program)
    if args.ebpf:
        exit()

bpf = BPF(text=program, usdt_contexts=[usdt] if usdt else [])
if args.syscalls:
    print("Attached kernel tracepoints for syscall tracing.")
Beispiel #6
0
def randomword(length):
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for i in range(length))


randprefix = randomword(4)

parser = argparse.ArgumentParser(
    description="Trace quic events",
    formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("pid", type=int, help="pid to attach to")
args = parser.parse_args()

usdt = USDT(pid=args.pid)
usdt.enable_probe_or_bail("packet_acked", "on_packet_acked")
usdt.enable_probe_or_bail("packet_sent", "on_packet_sent")
usdt.enable_probe("packets_lost", "on_packets_lost")
usdt.enable_probe("packet_recvd", "on_packet_recvd")
usdt.enable_probe("rto_alarm", "on_rto_alarm")
usdt.enable_probe("tlp_alarm", "on_tlp_alarm")
usdt.enable_probe("handshake_alarm", "on_handshake_alarm")
usdt.enable_probe("rto_verified", "on_rto_verified")
#usdt.enable_probe("packet_clone", "on_packet_clone")
usdt.enable_probe("packet_drop", "on_packet_drop")
usdt.enable_probe("conn_close", "on_close")
usdt.enable_probe("recvd_close", "on_recvd_close")
usdt.enable_probe("cubic_ack", "on_cubic_ack")
usdt.enable_probe("cubic_steady_cwnd", "on_cubic_steady_cwnd_changed")
usdt.enable_probe("pacing_update", "on_pacing_update")
try:
Beispiel #7
0
    info->total_ns += bpf_ktime_get_ns() - e->timestamp;
    sysentry.delete(&pid);
    return 0;
}
#endif  // LATENCY
#endif  // SYSCALLS
""".replace("READ_CLASS", read_class) \
   .replace("READ_METHOD", read_method) \
   .replace("PID_FILTER", "if ((pid >> 32) != %d) { return 0; }" % args.pid) \
   .replace("DEFINE_NOLANG", "#define NOLANG" if not language else "") \
   .replace("DEFINE_LATENCY", "#define LATENCY" if args.latency else "") \
   .replace("DEFINE_SYSCALLS", "#define SYSCALLS" if args.syscalls else "")

if language:
    usdt = USDT(pid=args.pid)
    usdt.enable_probe_or_bail(entry_probe, "trace_entry")
    if args.latency:
        usdt.enable_probe_or_bail(return_probe, "trace_return")
else:
    usdt = None

if args.ebpf or args.verbose:
    if args.verbose and usdt:
        print(usdt.get_text())
    print(program)
    if args.ebpf:
        exit()

bpf = BPF(text=program, usdt_contexts=[usdt] if usdt else [])
if args.syscalls:
    syscall_regex = "^[Ss]y[Ss]_.*"
Beispiel #8
0
int alloc_entry(struct pt_regs *ctx) {
    struct key_t key = {};
    struct val_t *valp, zero = {};
    u64 classptr = 0, size = 0;
    bpf_usdt_readarg(2, ctx, &classptr);
    bpf_usdt_readarg(4, ctx, &size);
    bpf_probe_read_user(&key.name, sizeof(key.name), (void *)classptr);
    valp = allocs.lookup_or_try_init(&key, &zero);
    if (valp) {
        valp->total_size += size;
        valp->num_allocs += 1;
    }
    return 0;
}
    """
    usdt.enable_probe_or_bail("object__alloc", "alloc_entry")
#
# Ruby
#
elif language == "ruby":
    create_template = """
int THETHING_alloc_entry(struct pt_regs *ctx) {
    struct key_t key = { .name = "THETHING" };
    struct val_t *valp, zero = {};
    u64 size = 0;
    bpf_usdt_readarg(1, ctx, &size);
    valp = allocs.lookup_or_try_init(&key, &zero);
    if (valp) {
        valp->total_size += size;
        valp->num_allocs += 1;
    }
Beispiel #9
0
BPF_PERF_OUTPUT(threads);

int trace_pthread(struct pt_regs *ctx) {
    struct thread_event_t te = {};
    u64 start_routine = 0;
    char type[] = "pthread";
    te.native_id = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
    bpf_usdt_readarg(2, ctx, &start_routine);
    te.runtime_id = start_routine;  // This is really a function pointer
    __builtin_memcpy(&te.type, type, sizeof(te.type));
    threads.perf_submit(ctx, &te, sizeof(te));
    return 0;
}
"""
usdt.enable_probe_or_bail("pthread_start", "trace_pthread")

language = args.language
if not language:
    language = utils.detect_language(languages, args.pid)

if language == "java":
    template = """
int %s(struct pt_regs *ctx) {
    char type[] = "%s";
    struct thread_event_t te = {};
    u64 nameptr = 0, id = 0, native_id = 0;
    bpf_usdt_readarg(1, ctx, &nameptr);
    bpf_usdt_readarg(3, ctx, &id);
    bpf_usdt_readarg(4, ctx, &native_id);
    bpf_probe_read(&te.name, sizeof(te.name), (void *)nameptr);
Beispiel #10
0
if language == "java":
    program += """
int alloc_entry(struct pt_regs *ctx) {
    struct key_t key = {};
    struct val_t *valp, zero = {};
    u64 classptr = 0, size = 0;
    bpf_usdt_readarg(2, ctx, &classptr);
    bpf_usdt_readarg(4, ctx, &size);
    bpf_probe_read(&key.name, sizeof(key.name), (void *)classptr);
    valp = allocs.lookup_or_init(&key, &zero);
    valp->total_size += size;
    valp->num_allocs += 1;
    return 0;
}
    """
    usdt.enable_probe_or_bail("object__alloc", "alloc_entry")
#
# Ruby
#
elif language == "ruby":
    create_template = """
int THETHING_alloc_entry(struct pt_regs *ctx) {
    struct key_t key = { .name = "THETHING" };
    struct val_t *valp, zero = {};
    u64 size = 0;
    bpf_usdt_readarg(1, ctx, &size);
    valp = allocs.lookup_or_init(&key, &zero);
    valp->total_size += size;
    valp->num_allocs += 1;
    return 0;
}