]> sourceware.org Git - systemtap.git/blame - tapset-itrace.cxx
Fixed systemtap-server.exp
[systemtap.git] / tapset-itrace.cxx
CommitLineData
93646f4d 1// tapset for timers
1af100fc 2// Copyright (C) 2005-2013 Red Hat Inc.
93646f4d 3// Copyright (C) 2005-2007 Intel Corporation.
93646f4d
JS
4//
5// This file is part of systemtap, and is free software. You can
6// redistribute it and/or modify it under the terms of the GNU General
7// Public License (GPL); either version 2, or (at your option) any
8// later version.
9
10
11#include "session.h"
12#include "tapsets.h"
13#include "task_finder.h"
14#include "translate.h"
15#include "util.h"
16
17#include <cstring>
18#include <string>
19
20
21using namespace std;
22using namespace __gnu_cxx;
23
24
4627ed58
JS
25static const string TOK_PROCESS("process");
26static const string TOK_INSN("insn");
27static const string TOK_BLOCK("block");
93646f4d
JS
28
29
30// ------------------------------------------------------------------------
31// itrace user-space probes
32// ------------------------------------------------------------------------
33
34
35struct itrace_derived_probe: public derived_probe
36{
37 bool has_path;
38 string path;
39 int64_t pid;
40 int single_step;
41
42 itrace_derived_probe (systemtap_session &s, probe* p, probe_point* l,
43 bool hp, string &pn, int64_t pd, int ss
44 );
45 void join_group (systemtap_session& s);
46};
47
48
49struct itrace_derived_probe_group: public generic_dpg<itrace_derived_probe>
50{
51private:
52 map<string, vector<itrace_derived_probe*> > probes_by_path;
53 typedef map<string, vector<itrace_derived_probe*> >::iterator p_b_path_iterator;
54 map<int64_t, vector<itrace_derived_probe*> > probes_by_pid;
55 typedef map<int64_t, vector<itrace_derived_probe*> >::iterator p_b_pid_iterator;
56 unsigned num_probes;
57
58 void emit_probe_decl (systemtap_session& s, itrace_derived_probe *p);
59
60public:
61 itrace_derived_probe_group(): num_probes(0) { }
62
63 void enroll (itrace_derived_probe* probe);
64 void emit_module_decls (systemtap_session& s);
65 void emit_module_init (systemtap_session& s);
66 void emit_module_exit (systemtap_session& s);
67};
68
69
70itrace_derived_probe::itrace_derived_probe (systemtap_session &s,
71 probe* p, probe_point* l,
72 bool hp, string &pn, int64_t pd,
73 int ss
74 ):
75 derived_probe(p, l), has_path(hp), path(pn), pid(pd), single_step(ss)
76{
e34d5d13 77 if (s.kernel_config["CONFIG_UTRACE"] != string("y"))
dc09353a 78 throw SEMANTIC_ERROR (_("process probes not available without kernel CONFIG_UTRACE"));
93646f4d
JS
79}
80
81
82void
83itrace_derived_probe::join_group (systemtap_session& s)
84{
85 if (! s.itrace_derived_probes)
86 s.itrace_derived_probes = new itrace_derived_probe_group ();
87
88 s.itrace_derived_probes->enroll (this);
ca6d3b0f 89 this->group = s.itrace_derived_probes;
93646f4d
JS
90
91 enable_task_finder(s);
92}
93
94struct itrace_builder: public derived_probe_builder
95{
96 itrace_builder() {}
97 virtual void build(systemtap_session & sess,
98 probe * base,
99 probe_point * location,
100 std::map<std::string, literal *> const & parameters,
101 vector<derived_probe *> & finished_results)
102 {
05fb3e0c 103 string path, path_tgt;
93646f4d
JS
104 int64_t pid = 0;
105 int single_step;
106
107 bool has_path = get_param (parameters, TOK_PROCESS, path);
108 bool has_pid = get_param (parameters, TOK_PROCESS, pid);
109 // XXX: PR 6445 needs !has_path && !has_pid support
110 assert (has_path || has_pid);
111
112 single_step = ! has_null_param (parameters, TOK_BLOCK);
113
114 // If we have a path, we need to validate it.
115 if (has_path)
671ceda8 116 {
05fb3e0c 117 path = find_executable (path, sess.sysroot, sess.sysenv);
671ceda8 118 sess.unwindsym_modules.insert (path);
05fb3e0c 119 path_tgt = path_remove_sysroot(sess, path);
671ceda8 120 }
5c6f9e92
AJ
121 else // (has_pid)
122 {
a03a3744
JS
123 string pid_err_msg;
124 if (!is_valid_pid(pid, pid_err_msg))
125 throw SEMANTIC_ERROR(pid_err_msg);
5c6f9e92 126 }
93646f4d
JS
127
128 finished_results.push_back(new itrace_derived_probe(sess, base, location,
05fb3e0c 129 has_path, path_tgt, pid,
93646f4d
JS
130 single_step
131 ));
132 }
133};
134
135
136void
137itrace_derived_probe_group::enroll (itrace_derived_probe* p)
138{
139 if (p->has_path)
140 probes_by_path[p->path].push_back(p);
141 else
142 probes_by_pid[p->pid].push_back(p);
143 num_probes++;
144
145 // XXX: multiple exec probes (for instance) for the same path (or
146 // pid) should all share a itrace report function, and have their
147 // handlers executed sequentially.
148}
149
150
151void
152itrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
153 itrace_derived_probe *p)
154{
155 s.op->newline() << "{";
156 s.op->line() << " .tgt={";
1af100fc 157 s.op->line() << " .purpose=\"itrace\",";
93646f4d
JS
158
159 if (p->has_path)
160 {
b6921d59 161 s.op->line() << " .procname=\"" << p->path << "\",";
93646f4d
JS
162 s.op->line() << " .pid=0,";
163 }
164 else
165 {
b6921d59 166 s.op->line() << " .procname=NULL,";
93646f4d
JS
167 s.op->line() << " .pid=" << p->pid << ",";
168 }
169
170 s.op->line() << " .callback=&_stp_itrace_probe_cb,";
171 s.op->line() << " },";
faea5e16 172 s.op->line() << " .probe=" << common_probe_init (p) << ",";
93646f4d 173 s.op->line() << " .single_step=" << p->single_step << ",";
93646f4d
JS
174 s.op->line() << " },";
175}
176
177
178void
179itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
180{
181 if (probes_by_path.empty() && probes_by_pid.empty())
182 return;
183
184 s.op->newline();
185 s.op->newline() << "/* ---- itrace probes ---- */";
186
187 s.op->newline() << "struct stap_itrace_probe {";
188 s.op->indent(1);
189 s.op->newline() << "struct stap_task_finder_target tgt;";
7c3e97f4 190 s.op->newline() << "const struct stap_probe * const probe;";
93646f4d
JS
191 s.op->newline() << "int single_step;";
192 s.op->newline(-1) << "};";
193 s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data);";
2ba1736a 194 s.op->newline() << "#include \"linux/itrace.c\"";
93646f4d
JS
195
196 // output routine to call itrace probe
197 s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data) {";
198 s.op->indent(1);
199
71db462b 200 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe",
cda141c2 201 "stp_probe_type_itrace");
d9aed31e 202 s.op->newline() << "c->uregs = regs;";
e04b5d74 203 s.op->newline() << "c->user_mode_p = 1;";
93646f4d
JS
204
205 // call probe function
26e63673 206 s.op->newline() << "(*p->probe->ph) (c);";
ef1337ee 207 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
93646f4d
JS
208
209 s.op->newline() << "return;";
210 s.op->newline(-1) << "}";
211
212 // Output task finder callback routine that gets called for all
213 // itrace probe types.
214 s.op->newline() << "static int _stp_itrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {";
215 s.op->indent(1);
216 s.op->newline() << "int rc = 0;";
217 s.op->newline() << "struct stap_itrace_probe *p = container_of(tgt, struct stap_itrace_probe, tgt);";
218
219 s.op->newline() << "if (register_p) ";
220 s.op->indent(1);
221
c8a44dea 222 s.op->newline() << "rc = usr_itrace_init(p->single_step, tsk, p);";
93646f4d 223 s.op->newline(-1) << "else";
4f600a5f 224 s.op->newline(1) << "remove_usr_itrace_info(find_itrace_info(tsk));";
93646f4d
JS
225 s.op->newline(-1) << "return rc;";
226 s.op->newline(-1) << "}";
227
93646f4d
JS
228 s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {";
229 s.op->indent(1);
230
231 // Set up 'process(PATH)' probes
232 if (! probes_by_path.empty())
233 {
234 for (p_b_path_iterator it = probes_by_path.begin();
235 it != probes_by_path.end(); it++)
236 {
237 for (unsigned i = 0; i < it->second.size(); i++)
238 {
239 itrace_derived_probe *p = it->second[i];
240 emit_probe_decl(s, p);
241 }
242 }
243 }
244
245 // Set up 'process(PID)' probes
246 if (! probes_by_pid.empty())
247 {
248 for (p_b_pid_iterator it = probes_by_pid.begin();
249 it != probes_by_pid.end(); it++)
250 {
251 for (unsigned i = 0; i < it->second.size(); i++)
252 {
253 itrace_derived_probe *p = it->second[i];
254 emit_probe_decl(s, p);
255 }
256 }
257 }
258 s.op->newline(-1) << "};";
259}
260
261
262void
263itrace_derived_probe_group::emit_module_init (systemtap_session& s)
264{
265 if (probes_by_path.empty() && probes_by_pid.empty())
266 return;
267
93646f4d
JS
268 s.op->newline();
269 s.op->newline() << "/* ---- itrace probes ---- */";
270
271 s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {";
272 s.op->indent(1);
273 s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];";
274
275 // 'arch_has_single_step' needs to be defined for either single step mode
276 // or branch mode.
277 s.op->newline() << "if (!arch_has_single_step()) {";
278 s.op->indent(1);
279 s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");";
280 s.op->newline() << "rc = -EPERM;";
281 s.op->newline() << "break;";
282 s.op->newline(-1) << "}";
283 s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {";
284 s.op->indent(1);
285 s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");";
286 s.op->newline() << "rc = -EPERM;";
287 s.op->newline() << "break;";
288 s.op->newline(-1) << "}";
289
290 s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
291 s.op->newline(-1) << "}";
292}
293
294
295void
296itrace_derived_probe_group::emit_module_exit (systemtap_session& s)
297{
298 if (probes_by_path.empty() && probes_by_pid.empty()) return;
299 s.op->newline();
300 s.op->newline() << "/* ---- itrace probes ---- */";
301 s.op->newline() << "cleanup_usr_itrace();";
302}
303
304void
305register_tapset_itrace(systemtap_session& s)
306{
307 match_node* root = s.pattern_root;
308 derived_probe_builder *builder = new itrace_builder();
309
d2c9ec9b 310 root->bind_str(TOK_PROCESS)->bind(TOK_INSN)
d2c9ec9b
DB
311 ->bind(builder);
312 root->bind_num(TOK_PROCESS)->bind(TOK_INSN)
d2c9ec9b
DB
313 ->bind(builder);
314 root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
d2c9ec9b
DB
315 ->bind(builder);
316 root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
d2c9ec9b 317 ->bind(builder);
93646f4d
JS
318}
319
320
321
322/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.166926 seconds and 5 git commands to generate.