Ptrace

GDB 计划支持 BookE 处理器的以下硬件调试功能

4 个硬件断点 (IAC) 2 个硬件观察点(读、写和读写)(DAC) 2 个用于硬件观察点的值条件 (DVC)

为此,我们需要扩展 ptrace,以便 GDB 可以查询和设置这些资源。由于我们正在扩展,我们尝试创建一个可扩展的接口,该接口涵盖 BookE 和服务器处理器,以便 GDB 不需要针对每个处理器进行特殊处理。我们添加了以下 3 个新的 ptrace 请求。

1. PPC_PTRACE_GETHWDBGINFO

用于 GDB 发现硬件调试功能的查询。此处要返回的主要信息是硬件观察点的最小对齐方式。BookE 处理器在此处没有限制,但服务器处理器对硬件观察点有 8 字节的对齐限制。我们希望避免根据 GDB 在 AUXV 中看到的内容向 GDB 添加特殊情况。

由于我们正在进行这项工作,我们添加了内核可以返回给 GDB 的其他有用信息:此查询将返回硬件断点数、硬件观察点数以及它是否支持地址范围和条件。该查询将填充请求进程提供的以下结构

struct ppc_debug_info {
     unit32_t version;
     unit32_t num_instruction_bps;
     unit32_t num_data_bps;
     unit32_t num_condition_regs;
     unit32_t data_bp_alignment;
     unit32_t sizeof_condition; /* size of the DVC register */
     uint64_t features; /* bitmask of the individual flags */
};

功能将具有指示是否支持的位

#define PPC_DEBUG_FEATURE_INSN_BP_RANGE               0x1
#define PPC_DEBUG_FEATURE_INSN_BP_MASK                0x2
#define PPC_DEBUG_FEATURE_DATA_BP_RANGE               0x4
#define PPC_DEBUG_FEATURE_DATA_BP_MASK                0x8
#define PPC_DEBUG_FEATURE_DATA_BP_DAWR                0x10
#define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31             0x20
  1. PPC_PTRACE_SETHWDEBUG

根据提供的结构设置硬件断点或观察点

 struct ppc_hw_breakpoint {
       uint32_t version;
 #define PPC_BREAKPOINT_TRIGGER_EXECUTE  0x1
 #define PPC_BREAKPOINT_TRIGGER_READ     0x2
#define PPC_BREAKPOINT_TRIGGER_WRITE    0x4
       uint32_t trigger_type;       /* only some combinations allowed */
 #define PPC_BREAKPOINT_MODE_EXACT               0x0
 #define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE     0x1
 #define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE     0x2
 #define PPC_BREAKPOINT_MODE_MASK                0x3
       uint32_t addr_mode;          /* address match mode */

 #define PPC_BREAKPOINT_CONDITION_MODE   0x3
 #define PPC_BREAKPOINT_CONDITION_NONE   0x0
 #define PPC_BREAKPOINT_CONDITION_AND    0x1
 #define PPC_BREAKPOINT_CONDITION_EXACT  0x1   /* different name for the same thing as above */
 #define PPC_BREAKPOINT_CONDITION_OR     0x2
 #define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
 #define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000    /* byte enable bits */
 #define PPC_BREAKPOINT_CONDITION_BE(n)  (1<<((n)+16))
       uint32_t condition_mode;     /* break/watchpoint condition flags */

       uint64_t addr;
       uint64_t addr2;
       uint64_t condition_value;
 };

一个请求指定一个事件,而不一定只是要设置的一个寄存器。例如,如果请求是具有条件的观察点,则 DAC 和 DVC 寄存器将在同一请求中设置。

使用此功能,GDB 可以请求 BookE 支持的所有类型的硬件断点和观察点。服务器处理器中可用的 COMEFROM 断点未考虑在内,但这超出了本工作的范围。

ptrace 将返回一个唯一标识刚刚创建的断点或观察点的整数(句柄)。此整数将用于 PPC_PTRACE_DELHWDEBUG 请求中,以请求删除该断点或观察点。如果无法在寄存器上分配请求的断点,则返回 -ENOSPC。

使用该结构的一些示例

  • 在第一个断点寄存器中设置断点

    p.version         = PPC_DEBUG_CURRENT_VERSION;
    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
    p.addr            = (uint64_t) address;
    p.addr2           = 0;
    p.condition_value = 0;
    
  • 在第二个观察点寄存器中设置在读取时触发的观察点

    p.version         = PPC_DEBUG_CURRENT_VERSION;
    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
    p.addr            = (uint64_t) address;
    p.addr2           = 0;
    p.condition_value = 0;
    
  • 设置仅在具有特定值时触发的观察点

    p.version         = PPC_DEBUG_CURRENT_VERSION;
    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
    p.condition_mode  = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
    p.addr            = (uint64_t) address;
    p.addr2           = 0;
    p.condition_value = (uint64_t) condition;
    
  • 设置范围硬件断点

    p.version         = PPC_DEBUG_CURRENT_VERSION;
    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
    p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
    p.addr            = (uint64_t) begin_range;
    p.addr2           = (uint64_t) end_range;
    p.condition_value = 0;
    
  • 在服务器处理器 (BookS) 中设置观察点

    p.version         = 1;
    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_RW;
    p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
    or
    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
    
    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
    p.addr            = (uint64_t) begin_range;
    /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
     * addr2 - addr <= 8 Bytes.
     */
    p.addr2           = (uint64_t) end_range;
    p.condition_value = 0;
    
  1. PPC_PTRACE_DELHWDEBUG

获取一个整数,该整数标识现有断点或观察点(即,从 PTRACE_SETHWDEBUG 返回的值),并删除相应的断点或观察点。