1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#ifndef _ASM_GENERIC_HW_BREAKPOINT_H
#define _ASM_GENERIC_HW_BREAKPOINT_H
#ifndef __ARCH_HW_BREAKPOINT_H
#error "Please don't include this file directly"
#endif
#ifdef __KERNEL__
#include <linux/list.h>
#include <linux/types.h>
#include <linux/kallsyms.h>
/**
* struct hw_breakpoint - unified kernel/user-space hardware breakpoint
* @triggered: callback invoked after target address access
* @info: arch-specific breakpoint info (address, length, and type)
*
* %hw_breakpoint structures are the kernel's way of representing
* hardware breakpoints. These are data breakpoints
* (also known as "watchpoints", triggered on data access), and the breakpoint's
* target address can be located in either kernel space or user space.
*
* The breakpoint's address, length, and type are highly
* architecture-specific. The values are encoded in the @info field; you
* specify them when registering the breakpoint. To examine the encoded
* values use hw_breakpoint_get_{kaddress,uaddress,len,type}(), declared
* below.
*
* The address is specified as a regular kernel pointer (for kernel-space
* breakponts) or as an %__user pointer (for user-space breakpoints).
* With register_user_hw_breakpoint(), the address must refer to a
* location in user space. The breakpoint will be active only while the
* requested task is running. Conversely with
* register_kernel_hw_breakpoint(), the address must refer to a location
* in kernel space, and the breakpoint will be active on all CPUs
* regardless of the current task.
*
* The length is the breakpoint's extent in bytes, which is subject to
* certain limitations. include/asm/hw_breakpoint.h contains macros
* defining the available lengths for a specific architecture. Note that
* the address's alignment must match the length. The breakpoint will
* catch accesses to any byte in the range from address to address +
* (length - 1).
*
* The breakpoint's type indicates the sort of access that will cause it
* to trigger. Possible values may include:
*
* %HW_BREAKPOINT_RW (triggered on read or write access),
* %HW_BREAKPOINT_WRITE (triggered on write access), and
* %HW_BREAKPOINT_READ (triggered on read access).
*
* Appropriate macros are defined in include/asm/hw_breakpoint.h; not all
* possibilities are available on all architectures. Execute breakpoints
* must have length equal to the special value %HW_BREAKPOINT_LEN_EXECUTE.
*
* When a breakpoint gets hit, the @triggered callback is
* invoked in_interrupt with a pointer to the %hw_breakpoint structure and the
* processor registers.
* Data breakpoints occur after the memory access has taken place.
* Breakpoints are disabled during execution @triggered, to avoid
* recursive traps and allow unhindered access to breakpointed memory.
*
* This sample code sets a breakpoint on pid_max and registers a callback
* function for writes to that variable. Note that it is not portable
* as written, because not all architectures support HW_BREAKPOINT_LEN_4.
*
* ----------------------------------------------------------------------
*
* #include <asm/hw_breakpoint.h>
*
* struct hw_breakpoint my_bp;
*
* static void my_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
* {
* printk(KERN_DEBUG "Inside triggered routine of breakpoint exception\n");
* dump_stack();
* .......<more debugging output>........
* }
*
* static struct hw_breakpoint my_bp;
*
* static int init_module(void)
* {
* ..........<do anything>............
* my_bp.info.type = HW_BREAKPOINT_WRITE;
* my_bp.info.len = HW_BREAKPOINT_LEN_4;
*
* my_bp.installed = (void *)my_bp_installed;
*
* rc = register_kernel_hw_breakpoint(&my_bp);
* ..........<do anything>............
* }
*
* static void cleanup_module(void)
* {
* ..........<do anything>............
* unregister_kernel_hw_breakpoint(&my_bp);
* ..........<do anything>............
* }
*
* ----------------------------------------------------------------------
*/
struct hw_breakpoint {
void (*triggered)(struct hw_breakpoint *, struct pt_regs *);
struct arch_hw_breakpoint info;
};
/*
* len and type values are defined in include/asm/hw_breakpoint.h.
* Available values vary according to the architecture. On i386 the
* possibilities are:
*
* HW_BREAKPOINT_LEN_1
* HW_BREAKPOINT_LEN_2
* HW_BREAKPOINT_LEN_4
* HW_BREAKPOINT_RW
* HW_BREAKPOINT_READ
*
* On other architectures HW_BREAKPOINT_LEN_8 may be available, and the
* 1-, 2-, and 4-byte lengths may be unavailable. There also may be
* HW_BREAKPOINT_WRITE. You can use #ifdef to check at compile time.
*/
extern int register_user_hw_breakpoint(struct task_struct *tsk,
struct hw_breakpoint *bp);
extern int modify_user_hw_breakpoint(struct task_struct *tsk,
struct hw_breakpoint *bp);
extern void unregister_user_hw_breakpoint(struct task_struct *tsk,
struct hw_breakpoint *bp);
/*
* Kernel breakpoints are not associated with any particular thread.
*/
extern int register_kernel_hw_breakpoint(struct hw_breakpoint *bp);
extern void unregister_kernel_hw_breakpoint(struct hw_breakpoint *bp);
extern unsigned int hbp_kernel_pos;
#endif /* __KERNEL__ */
#endif /* _ASM_GENERIC_HW_BREAKPOINT_H */
|