Showing posts with label Tracing. Show all posts
Showing posts with label Tracing. Show all posts

Thursday, September 16, 2021

USDT Python Tracing 範例

 Reference for USDT Tracepoint for Python

https://github.com/paulross/dtrace-py
https://www.collabora.com/news-and-blog/blog/2019/05/14/an-ebpf-overview-part-5-tracing-user-processes/
https://github.com/iovisor/bcc/pull/698

Install build tools and python prerequisites
sudo apt install systemtap-sdt-dev

sudo apt install build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev tk-dev libffi-dev

Download and extract python
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
tar xf Python-3.7.0.tar.xz
cd Python-3.7.0
curl -o Python-3.7.0.tgz https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
tar -xzf Python-3.7.0.tgz
cd Python-3.7.0

Wednesday, September 15, 2021

[eBPF] An example of Userspace Tracing

#!/usr/bin/python

from __future__ import print_function
from bcc import BPF
from time import sleep

# load BPF program

b = BPF(text="""
#include <uapi/linux/ptrace.h>
struct key_t {
    char c[80];
};
BPF_HASH(counts, struct key_t);

int count(struct pt_regs *ctx) {
    if (!PT_REGS_PARM1(ctx))
        return 0;

    struct key_t key = {};
    u64 zero = 0, *val;
    bpf_probe_read(&key.c, sizeof(key.c), (void *)PT_REGS_PARM1(ctx));
    val = counts.lookup_or_init(&key, &zero);
    (*val)++;
    return 0;
};
""")

b.attach_uprobe(name="c", sym="strlen", fn_name="count")

# header
print("Tracing strlen()... Hit Ctrl-C to end.")

# sleep until Ctrl-C
try:
    sleep(99999999)
except KeyboardInterrupt:
    pass

# print output
print("%10s %s" % ("COUNT", "STRING"))
counts = b.get_table("counts")
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
    print("%10d \"%s\"" % (v.value, k.c.encode('string-escape')))


Reference:
https://github.com/iovisor/bcc/blob/master/tools/bashreadline.py
https://github.com/iovisor/bcc/blob/master/tools/gethostlatency.py
https://github.com/iovisor/bcc/blob/master/tools/funccount.py
https://github.com/iovisor/bcc/blob/master/tools/memleak.py
https://github.com/iovisor/bcc/blob/master/tools/dbslower.py
https://github.com/iovisor/bcc/blob/master/tools/trace.py


Friday, February 21, 2020

[Tracing] Use BCC tools to do dynamic tracing in Linux user space

Here is a very simple example of using BCC to trace a program and get the data from the function's argument.

A Simple Test Code in C: "test.c"
#include <stdio.h>

// student structure
struct student {
  char id[15];
  char firstname[64];
  char lastname[64];
  float points;
};
// function declaration
void getDetail(struct student *);
void displayDetail(struct student *);

int main(void) {
  // student structure variable
  struct student std[1];
  // get student detail
  getDetail(std);
  // display student detail
  displayDetail(std);
  return 0;
}

// function definition
void getDetail(struct student *ptr) {
  int i;
  for (i = 0; i < 1; i++) {
    printf("Enter detail of student #%d\n", (i + 1));
    printf("Enter ID: ");
    scanf("%s", ptr->id);
    printf("Enter first name: ");
    scanf("%s", ptr->firstname);
    printf("Enter last name: ");
    scanf("%s", ptr->lastname);
    printf("Enter Points: ");
    scanf("%f", &ptr->points);
    // update pointer to point at next element
    // of the array std
    ptr++;
  }
}

void displayDetail(struct student *ptr) {
  int i;
  for (i = 0; i < 1; i++) {
    printf("\nDetail of student #%d\n", (i + 1));
    // display result via ptr variable
    printf("\nResult via ptr\n");
    printf("ID: %s\n", ptr->id);
    printf("First Name: %s\n", ptr->firstname);
    printf("Last Name: %s\n", ptr->lastname);
    printf("Points: %f\n", ptr->points);
    // update pointer to point at next element
    // of the array std
    ptr++;
  }
}

The simple BCC example code: "mytrace.py"
It will get and print out the string of firstname when it runs
from __future__ import print_function
from bcc import BPF
from time import strftime
import argparse


# load BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
struct str_t {
    u64 pid;
    char str[80];
};

// student structure
struct student {
  char id[15];
  char firstname[64];
  char lastname[64];
  float points;
};

BPF_PERF_OUTPUT(events);
int printret(struct pt_regs *ctx) {
    struct str_t data  = {};
    char comm[TASK_COMM_LEN] = {};
    u32 pid;
    if (!PT_REGS_RC(ctx))
        return 0;
    pid = bpf_get_current_pid_tgid();
    data.pid = pid;
    bpf_probe_read(&data.str, sizeof(data.str),
        ((struct student *)PT_REGS_RC(ctx))->firstname);
    bpf_get_current_comm(&comm, sizeof(comm));
    events.perf_submit(ctx,&data,sizeof(data));
    return 0;
};
"""

b = BPF(text=bpf_text)
b.attach_uprobe(name="<...your test binary file location...>/test",
        sym="displayDetail", fn_name="printret")

# header
print("%-9s %-6s %s" % ("TIME", "PID", "ARGUMENT"))

def print_event(cpu, data, size):
    event = b["events"].event(data)
    print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid,
                            event.str.decode('utf-8', 'replace')))

b["events"].open_perf_buffer(print_event)
while 1:
    try:
        b.perf_buffer_poll()
    except KeyboardInterrupt:
        exit()
Here is the steps:
$ sudo python mytrace.py

# open another terminal
$ gcc -o test test.c
$ ./test
Enter detail of student #1
Enter ID: 1234
Enter first name: Danny
Enter last name: Liu
Enter Points: 100

Detail of student #1

Result via ptr
ID: 1234
First Name: Danny
Last Name: Liu
Points: 100.000000
Then you will see the tracing message in your previous terminal as follows:
(print out the first name from function's argument)
$ sudo python mytrace.py
TIME      PID    ARGUMENT
17:01:32  7265   Danny

Thursday, February 20, 2020