Debugging 查找Linux内核硬件监视或断点的访问方向(读或写)?

Debugging 查找Linux内核硬件监视或断点的访问方向(读或写)?,debugging,linux-kernel,Debugging,Linux Kernel,考虑中给出的内核模块testhrarr.c,它跟踪对内存位置的写访问 现在,我正在尝试跟踪读/写访问,这是通过在testhrarr\u init函数中更改这一行来完成的: attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; 这里的第一个子问题是:在我的平台上(Linux内核2.6.38)HW_断点_W在其自身的工作中,以及HW_W | HW_断点_R用于读/写工作-但是尝试仅使用HW_断点_R进行读访问不起作用;当我在/var/log/syslo

考虑中给出的内核模块
testhrarr.c
,它跟踪对内存位置的写访问

现在,我正在尝试跟踪读/写访问,这是通过在
testhrarr\u init
函数中更改这一行来完成的:

attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
这里的第一个子问题是:在我的平台上(Linux内核2.6.38)
HW_断点_W
在其自身的工作中,以及
HW_W | HW_断点_R
用于读/写工作-但是尝试仅使用
HW_断点_R
进行读访问不起作用;当我在
/var/log/syslog
中得到“断点注册失败”时,
insmod
因“insmod:error inserting./testhrarr.ko':-1无效参数”而失败。有人知道为什么吗

无论如何,这里的问题是,一旦我使用
HW|HW|u BREAKPOINT_R
监视读/写访问,我就无法在处理程序中判断我获得的堆栈跟踪是由于读访问还是写访问。我经历过:

  • 结构
    perf\u event\u attr
    in
  • 结构
    hw\u性能事件
  • 对于
    HW\u断点*
    enum定义
。。。我在任何地方都找不到从hw断点处理程序中检索的显式技术,无论触发的是读访问还是写访问。我只在中找到了一些东西,但是
trace\u ksym
已经被弃用了(甚至在我的2.6.38中都没有),而且它只是读取
attr.bp\u type
,这是我们自己在内核模块中设置的

因此,在一些暴力强迫之后,我意识到
hw_perf_event->interrupts
可能包含这些信息;因此,我将处理程序回调修改为:

static void sample_hbp_handler(struct perf_event *bp,
             struct perf_sample_data *data,
             struct pt_regs *regs)
{
  struct perf_event_attr attr = bp->attr;
  struct hw_perf_event   hw  = bp->hw;
  char hwirep[8];
  //it looks like printing %llu, data->type here causes segfault/oops when `cat` runs?
  // apparently, hw.interrupts changes depending on read/write access (1 or 2)
  // when only HW_BREAKPOINT_W, getting hw.interrupts == 1 always;
  // only HW_BREAKPOINT_R - fails for me
  // when both, hw.interrupts is either 1 or 2
  // defined in include/linux/hw_breakpoint.h:
  // HW_BREAKPOINT_R        = 1,  HW_BREAKPOINT_W       = 2,
  if (hw.interrupts == HW_BREAKPOINT_R) {
    strcpy(hwirep, "_R");
  } else if (hw.interrupts == HW_BREAKPOINT_W) {
    strcpy(hwirep, "_W");
  } else {
    strcpy(hwirep, "__");
  }
  printk(KERN_INFO "+--- %s value is accessed (.bp_type %d, .type %d, state %d htype %d hwi %llu / %s ) ---+\n", ksym_name, attr.bp_type, attr.type, hw.state, hw.info.type, hw.interrupts, hwirep);
  dump_stack();
  printk(KERN_INFO "|___ Dump stack from sample_hbp_handler ___|\n");
}
。。。这似乎有些效果;当我在系统日志中看到以下内容时:

$ grep "testhrarr_arr_first value" /var/log/syslog
kernel: [  200.887620] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
kernel: [  200.892163] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
kernel: [  200.892634] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 2 / _W ) ---+
kernel: [  200.912192] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
kernel: [  200.912713] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 2 / _W ) ---+
kernel: [  200.932138] +--- testhrarr_arr_first value is accessed (.bp_type 3, .type 5, state 0 htype 131 hwi 1 / _R ) ---+
。。。但是,如果
attr.bp\u type
只是
HW\u断点
,则只报告三个
HW.interrupts==1
(然后将其错误地报告为
\R

因此,如果我只是颠倒
\u R
\u W
的含义,我可能会得到一些与我猜测应该发生的事情相匹配的东西-但这显然是一个暗箱操作,因为我不知道
hw\u perf\u event->interrupts
应该代表什么

那么,有人知道确定访问硬件监视内存位置的“方向”(读或写)的正确方法吗


编辑:我的第一个子问题的答案是:对于我的体系结构x86,有以下代码:

。。。它清楚地表明X86具有
\u WRITE
\u RW
断点;因此,如果我们尝试只为
HW\u断点\u R
设置,则进程将无法返回-EINVAL

所以,我想,这里我需要的答案主要是针对X86的,尽管如果有一种通用的可移植机制来确定读/写访问,我更希望了解这一点

static int arch_build_bp_info(struct perf_event *bp)
{
  struct arch_hw_breakpoint *info = counter_arch_bp(bp);

  info->address = bp->attr.bp_addr;

  /* Type */
  switch (bp->attr.bp_type) {
  case HW_BREAKPOINT_W:
          info->type = X86_BREAKPOINT_WRITE;
          break;
  case HW_BREAKPOINT_W | HW_BREAKPOINT_R:
          info->type = X86_BREAKPOINT_RW;
          break;
  case HW_BREAKPOINT_X:
          info->type = X86_BREAKPOINT_EXECUTE;
          // ...
  default:
          return -EINVAL;
  }
...
}