【问题标题】:bpftrace doesn’t recognise a syscall argument as negativebpftrace 无法将系统调用参数识别为负数
【发布时间】:2020-04-17 14:00:45
【问题描述】:

这是一个简单的 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

奇怪的是,对于比较运算符来说,正负 pid 似乎都是正的。

出于理智,检查一下,如果我将赋值行替换为:

  $tpid = -10;

我得到的正是我所期望的:

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

我做错了什么?

【问题讨论】:

  • 你的tpids 不是长整数吗?通过使用printf("%ld %d %d\n", $tpid, $tpid &lt; 0, $tpid &gt;= 0); 打印,我得到了一致的结果。如果我输入kill -- -12345,我还可以在第三列中观察到1
  • 啊,对不起,他们不是。
  • 你运行的是什么内核版本?
  • 你能报告grep " pid;" /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format(以root身份运行)的输出吗?
  • @pchaigno Linux 5.4.20。您询问的有关报告的命令field:pid_t pid; offset:16; size:8; signed:0;

标签: comparison trace pid ebpf


【解决方案1】:

正如您所发现的,bpftrace 将 u64 类型分配给您的 $tpid 变量。然而,根据跟踪点格式文档,args-&gt;pid 的类型应该是 pid_tor 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

对于上面的tracepoint描述,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 上打开一个问题。

【讨论】:

    【解决方案2】:

    bpftrace 中的整数类型发生了一些奇怪的事情(有关详细信息,请参阅 #554#772#834)。

    在我的情况下,arg-&gt;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
    

    【讨论】:

      猜你喜欢
      • 2020-07-17
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      • 2021-08-16
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      • 2013-06-14
      相关资源
      最近更新 更多