bpftrace не распознает аргумент системного вызова как отрицательный - PullRequest
1 голос
/ 17 апреля 2020

Вот простой скрипт bpftrace:

#!/usr/bin/env bpftrace

tracepoint:syscalls:sys_enter_kill
{
  $tpid = args->pid;
  printf("%d %d %d\n", $tpid, $tpid < 0, $tpid >= 0);
}

Он отслеживает kill системных вызовов, печатает целевой PID и два дополнительных значения: является ли он отрицательным и неотрицательным.

Вот вывод, который я получаю:

# ./test.bt
Attaching 1 probe...
-1746 0 1
-2202 0 1
4160 0 1
4197 0 1
4197 0 1
-2202 0 1
-1746 0 1

Странно, но и положительные, и отрицательные пиды кажутся положительными для оператора сравнения.

Так же, как здравый смысл, проверьте, если я заменю строку назначения на:

  $tpid = -10;

то, что я получаю, именно то, что я ожидаю:

# ./test.bt
Attaching 1 probe...
-10 1 0
-10 1 0
-10 1 0

Что я делаю неправильно?

Ответы [ 2 ]

2 голосов
/ 20 апреля 2020

Как вы обнаружили, bpftrace назначает тип u64 вашей переменной $tpid. Тем не менее, в соответствии с форматом трассировки do c., args->pid должен иметь тип pid_t, или int.

# cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format
name: sys_enter_kill
ID: 185
format:
    field:unsigned short common_type;   offset:0;   size:2; signed:0;
    field:unsigned char common_flags;   offset:2;   size:1; signed:0;
    field:unsigned char common_preempt_count;   offset:3;   size:1; signed:0;
    field:int common_pid;   offset:4;   size:4; signed:1;

    field:int __syscall_nr; offset:8;   size:4; signed:1;
    field:pid_t pid;    offset:16;  size:8; signed:0;
    field:int sig;  offset:24;  size:8; signed:0;

print fmt: "pid: 0x%08lx, sig: 0x%08lx", ((unsigned long)(REC->pid)), ((unsigned long)(REC->sig))

Функция bpftrace, которая назначает эту тип TracepointFormatParser::adjust_integer_types(). Это изменение было введено коммитом 42ce08f для решения проблемы # 124 .

Для приведенного выше описания точки трассировки bpftrace генерирует следующую структуру:

struct _tracepoint_syscalls_sys_enter_kill
{
  unsigned short common_type;
  unsigned char common_flags;
  unsigned char common_preempt_count;
  int common_pid;
  int __syscall_nr;
  u64 pid;
  s64 sig;
};

Когда он, вероятно, должен генерировать:

struct _tracepoint_syscalls_sys_enter_kill
{
  unsigned short common_type;
  unsigned char common_flags;
  unsigned char common_preempt_count;
  int common_pid;
  int __syscall_nr;
  u32 pad1;
  pid_t pid;
  u32 pad2;
  int sig;
};

bpftrace, похоже, смущен параметром size, который не соответствует типу в приведенном выше описании. Все аргументы системного вызова имеют размер 8 (по крайней мере на 64-битной версии), но это не означает, что используются все 8 байтов. Думаю, стоило бы открыть вопрос о bpftrace.

0 голосов
/ 17 апреля 2020

Что-то странное происходит с целочисленными типами в bpftrace (подробности см. # 554 , # 772 , # 834 ).

Похоже, что в моем случае arg->pids по умолчанию обрабатывается как 64-битное значение, хотя на самом деле это не так. Таким образом, решение состоит в том, чтобы явно привести его:

  $tpid = (int32)args->pid;

И теперь он работает, как и ожидалось:

# bpftrace test.bt
Attaching 1 probe...
-2202 1 0
-1746 1 0
-2202 1 0
4160 0 1
4197 0 1
...