Commit 3953c708 authored by Nikita V. Shirokov's avatar Nikita V. Shirokov Committed by yonghong-song

[trace.py]: allow to use STRCMP helper with binary values (#1900)

* [trace.py]: allow to use STRCMP helper with binary values

Summary:
sometimes in probe you want to compare char* w/ some predefined value
which is not a string. e.g. setsockopt syscall has signature like this:
sys_setsockopt(int fd, int level, int optname, char* optval, int optlen)
and if you want to catch where/who is setting up specific value you are
forced to compare optval against some predefined array. it's not
possible today w/ trace.py and in this diff i'm adding such ability

Test Plan:
as example: we want to catch setsockopt when someone is setting up
IP_TOS equal to 108
trace.py 'sys_setsockopt(int fd, int level, int optname, char* optval,
int optlen)(level==0 && optname == 1 && STRCMP("{0x6C,0x00, 0x00,
0x00}", optval))' -U -M 1 --bin_cmp -v

without this new modifier:
static inline bool streq_0(char const *ignored, uintptr_t str) {
        char needle[] = "{0x6C,0x00, 0x00, 0x00}";
        char haystack[sizeof(needle)];
        bpf_probe_read(&haystack, sizeof(haystack), (void *)str);
        for (int i = 0; i < sizeof(needle) - 1; ++i) {
                if (needle[i] != haystack[i]) {
                        return false;
                }
        }
        return true;
}

// see needle is qouted above

with:

tatic inline bool streq_0(char const *ignored, uintptr_t str) {
        char needle[] = {0x6C,0x00, 0x00, 0x00};
        char haystack[sizeof(needle)];
        bpf_probe_read(&haystack, sizeof(haystack), (void *)str);
        for (int i = 0; i < sizeof(needle) - 1; ++i) {
                if (needle[i] != haystack[i]) {
                        return false;
                }
        }
        return true;
}

...
PID     TID     COMM            FUNC             -
1855611 1863183 worker          sys_setsockopt   found

* adding example of --bin_cmp flag usage
parent 230c9c00
...@@ -48,6 +48,9 @@ Print the time column. ...@@ -48,6 +48,9 @@ Print the time column.
\-C \-C
Print CPU id. Print CPU id.
.TP .TP
\-B
Treat argument of STRCMP helper as a binary value
.TP
\-K \-K
Print the kernel stack for each event. Print the kernel stack for each event.
.TP .TP
......
...@@ -48,6 +48,7 @@ class Probe(object): ...@@ -48,6 +48,7 @@ class Probe(object):
cls.tgid = args.tgid or -1 cls.tgid = args.tgid or -1
cls.pid = args.pid or -1 cls.pid = args.pid or -1
cls.page_cnt = args.buffer_pages cls.page_cnt = args.buffer_pages
cls.bin_cmp = args.bin_cmp
def __init__(self, probe, string_size, kernel_stack, user_stack): def __init__(self, probe, string_size, kernel_stack, user_stack):
self.usdt = None self.usdt = None
...@@ -271,7 +272,11 @@ static inline bool %s(char const *ignored, uintptr_t str) { ...@@ -271,7 +272,11 @@ static inline bool %s(char const *ignored, uintptr_t str) {
expr = expr.replace(alias, replacement) expr = expr.replace(alias, replacement)
for alias, replacement in Probe.aliases_common.items(): for alias, replacement in Probe.aliases_common.items():
expr = expr.replace(alias, replacement) expr = expr.replace(alias, replacement)
matches = re.finditer('STRCMP\\(("[^"]+\\")', expr) if self.bin_cmp:
STRCMP_RE = 'STRCMP\\(\"([^"]+)\\"'
else:
STRCMP_RE = 'STRCMP\\(("[^"]+\\")'
matches = re.finditer(STRCMP_RE, expr)
for match in matches: for match in matches:
string = match.group(1) string = match.group(1)
fname = self._generate_streq_function(string) fname = self._generate_streq_function(string)
...@@ -680,6 +685,8 @@ trace -I 'linux/fs_struct.h' 'mntns_install "users = %d", $task->fs->users' ...@@ -680,6 +685,8 @@ trace -I 'linux/fs_struct.h' 'mntns_install "users = %d", $task->fs->users'
help="print time column") help="print time column")
parser.add_argument("-C", "--print_cpu", action="store_true", parser.add_argument("-C", "--print_cpu", action="store_true",
help="print CPU id") help="print CPU id")
parser.add_argument("-B", "--bin_cmp", action="store_true",
help="allow to use STRCMP with binary values")
parser.add_argument("-K", "--kernel-stack", parser.add_argument("-K", "--kernel-stack",
action="store_true", help="output kernel stack trace") action="store_true", help="output kernel stack trace")
parser.add_argument("-U", "--user-stack", parser.add_argument("-U", "--user-stack",
......
...@@ -234,6 +234,18 @@ The perf ring buffer size can be changed with -b. The unit is size per-CPU buffe ...@@ -234,6 +234,18 @@ The perf ring buffer size can be changed with -b. The unit is size per-CPU buffe
size and is measured in pages. The value must be a power of two and defaults to size and is measured in pages. The value must be a power of two and defaults to
64 pages. 64 pages.
# trace.py 'sys_setsockopt(int fd, int level, int optname, char* optval, int optlen)(level==0 && optname == 1 && STRCMP("{0x6C, 0x00, 0x00, 0x00}", optval))' -U -M 1 --bin_cmp
PID TID COMM FUNC -
1855611 1863183 worker sys_setsockopt found
In this example we are catching setsockopt syscall to change IPv4 IP_TOS
value only for the cases where new TOS value is equal to 108. we are using
STRCMP helper in binary mode (--bin_cmp flag) to compare optval array
against int value of 108 (parametr of setsockopt call) in hex representation
(little endian format)
USAGE message: USAGE message:
...@@ -262,6 +274,7 @@ optional arguments: ...@@ -262,6 +274,7 @@ optional arguments:
-t, --timestamp print timestamp column (offset from trace start) -t, --timestamp print timestamp column (offset from trace start)
-T, --time print time column -T, --time print time column
-C, --print_cpu print CPU id -C, --print_cpu print CPU id
-B, --bin_cmp allow to use STRCMP with binary values
-K, --kernel-stack output kernel stack trace -K, --kernel-stack output kernel stack trace
-U, --user-stack output user stack trace -U, --user-stack output user stack trace
-a, --address print virtual address in stacks -a, --address print virtual address in stacks
......
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