summaryrefslogtreecommitdiffstats
path: root/runtime/probes.c
blob: bb41091582c14db53d172406f23d6079a16dd3f4 (plain)
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
140
141
142
143
144
145
146
147
148
149
#ifndef _PROBES_C_ /* -*- linux-c -*- */
#define _PROBES_C

/** @file probes.c
 * @brief Functions to assist loading and unloading groups of probes.
 */

/** Lookup name.
 * This simply calls the kernel function kallsyms_lookup_name().
 * That function is not exported, so this workaround is required.
 * See the kernel source, kernel/kallsyms.c for more information.
 */
static unsigned long (*_stp_lookup_name)(char *name)=(void *)KALLSYMS_LOOKUP_NAME;

/** Unregister a group of jprobes.
 * @param probes Pointer to an array of struct jprobe.
 * @param num_probes Number of probes in the array.
 */

void _stp_unregister_jprobes (struct jprobe *probes, int num_probes)
{
	int i;
	for (i = 0; i < num_probes; i++)
		unregister_jprobe(&probes[i]);
	dbug("All jprobes removed\n");
}

/** Register a group of jprobes.
 * @param probes Pointer to an array of struct jprobe.
 * @param num_probes Number of probes in the array.
 * @return 0 on success.
 */

int _stp_register_jprobes (struct jprobe *probes, int num_probes)
{
	int i, ret ;
	unsigned long addr;

	for (i = 0; i < num_probes; i++) {
		addr =_stp_lookup_name((char *)probes[i].kp.addr);
		if (addr == 0) {
			_stp_warn("function %s not found!\n", (char *)probes[i].kp.addr);
			ret = -1; /* FIXME */
			goto out;
		}
		dbug("inserting jprobe at %s (%p)\n", probes[i].kp.addr, addr);
		probes[i].kp.addr = (kprobe_opcode_t *)addr;
		ret = register_jprobe(&probes[i]);
		if (ret)
			goto out;
	}
	return 0;
out:
	_stp_warn("probe module initialization failed.  Exiting...\n");
	_stp_unregister_jprobes(probes, i);
	return ret;
}

/** Unregister a group of kprobes.
 * @param probes Pointer to an array of struct kprobe.
 * @param num_probes Number of probes in the array.
 */

void _stp_unregister_kprobes (struct kprobe *probes, int num_probes)
{
	int i;
	for (i = 0; i < num_probes; i++)
		unregister_kprobe(&probes[i]);
	dbug("All kprobes removed\n");
}


#ifdef USE_RET_PROBES
/** Unregister a group of return probes.
 * @param probes Pointer to an array of struct kretprobe.
 * @param num_probes Number of probes in the array.
 */
void _stp_unregister_kretprobes (struct kretprobe *probes, int num_probes)
{
	int i;
	for (i = 0; i < num_probes; i++)
		unregister_kretprobe(&probes[i]);
	dbug("All return probes removed\n");
}
#endif

/** Register a group of kprobes.
 * @param probes Pointer to an array of struct kprobe.
 * @param num_probes Number of probes in the array.
 * @return 0 on success.
 */
int _stp_register_kprobes (struct kprobe *probes, int num_probes)
{
	int i, ret ;
	unsigned long addr;

	for (i = 0; i < num_probes; i++) {
		addr =_stp_lookup_name((char *)probes[i].addr);
		if (addr == 0) {
			_stp_warn("function %s not found!\n", (char *)probes[i].addr);
			ret = -1;
			goto out;
		}
		dbug("inserting kprobe at %s (%p)\n", probes[i].addr, addr);
		probes[i].addr = (kprobe_opcode_t *)addr;
		ret = register_kprobe(&probes[i]);
		if (ret)
			goto out;
	}
	return 0;
out:
	_stp_warn("probe module initialization failed.  Exiting...\n");
	_stp_unregister_kprobes(probes, i);
	return ret;
}

#ifdef USE_RET_PROBES
/** Register a group of return probes.
 * @param probes Pointer to an array of struct kretprobe.
 * @param num_probes Number of probes in the array.
 * @return 0 on success.
 */
int _stp_register_kretprobes (struct kretprobe *probes, int num_probes)
{
	int i, ret ;
	unsigned long addr;

	for (i = 0; i < num_probes; i++) {
		addr =_stp_lookup_name((char *)probes[i].kp.addr);
		if (addr == 0) {
			_stp_warn("function %s not found!\n", 
				   (char *)probes[i].kp.addr);
			ret = -1; /* FIXME */
			goto out;
		}
		dbug("inserting kretprobe at %s (%p)\n", probes[i].kp.addr, addr);
		probes[i].kp.addr = (kprobe_opcode_t *)addr;
		ret = register_kretprobe(&probes[i]);
		if (ret)
			goto out;
	}
	return 0;
out:
	_stp_warn("probe module initialization failed.  Exiting...\n");
	_stp_unregister_kretprobes(probes, i);
	return ret;
}
#endif
#endif /* _PROBES_C */