]> sourceware.org Git - systemtap.git/blame - tapset-itrace.cxx
Correct systemtap.spec to match support currently available on aarch64
[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"))
efee9a98 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);
89
90 enable_task_finder(s);
91}
92
93struct itrace_builder: public derived_probe_builder
94{
95 itrace_builder() {}
96 virtual void build(systemtap_session & sess,
97 probe * base,
98 probe_point * location,
99 std::map<std::string, literal *> const & parameters,
100 vector<derived_probe *> & finished_results)
101 {
05fb3e0c 102 string path, path_tgt;
93646f4d
JS
103 int64_t pid = 0;
104 int single_step;
105
106 bool has_path = get_param (parameters, TOK_PROCESS, path);
107 bool has_pid = get_param (parameters, TOK_PROCESS, pid);
108 // XXX: PR 6445 needs !has_path && !has_pid support
109 assert (has_path || has_pid);
110
111 single_step = ! has_null_param (parameters, TOK_BLOCK);
112
113 // If we have a path, we need to validate it.
114 if (has_path)
671ceda8 115 {
05fb3e0c 116 path = find_executable (path, sess.sysroot, sess.sysenv);
671ceda8 117 sess.unwindsym_modules.insert (path);
05fb3e0c 118 path_tgt = path_remove_sysroot(sess, path);
671ceda8 119 }
93646f4d
JS
120
121 finished_results.push_back(new itrace_derived_probe(sess, base, location,
05fb3e0c 122 has_path, path_tgt, pid,
93646f4d
JS
123 single_step
124 ));
125 }
126};
127
128
129void
130itrace_derived_probe_group::enroll (itrace_derived_probe* p)
131{
132 if (p->has_path)
133 probes_by_path[p->path].push_back(p);
134 else
135 probes_by_pid[p->pid].push_back(p);
136 num_probes++;
137
138 // XXX: multiple exec probes (for instance) for the same path (or
139 // pid) should all share a itrace report function, and have their
140 // handlers executed sequentially.
141}
142
143
144void
145itrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
146 itrace_derived_probe *p)
147{
148 s.op->newline() << "{";
149 s.op->line() << " .tgt={";
1af100fc 150 s.op->line() << " .purpose=\"itrace\",";
93646f4d
JS
151
152 if (p->has_path)
153 {
b6921d59 154 s.op->line() << " .procname=\"" << p->path << "\",";
93646f4d
JS
155 s.op->line() << " .pid=0,";
156 }
157 else
158 {
b6921d59 159 s.op->line() << " .procname=NULL,";
93646f4d
JS
160 s.op->line() << " .pid=" << p->pid << ",";
161 }
162
163 s.op->line() << " .callback=&_stp_itrace_probe_cb,";
164 s.op->line() << " },";
faea5e16 165 s.op->line() << " .probe=" << common_probe_init (p) << ",";
93646f4d 166 s.op->line() << " .single_step=" << p->single_step << ",";
93646f4d
JS
167 s.op->line() << " },";
168}
169
170
171void
172itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
173{
174 if (probes_by_path.empty() && probes_by_pid.empty())
175 return;
176
177 s.op->newline();
178 s.op->newline() << "/* ---- itrace probes ---- */";
179
180 s.op->newline() << "struct stap_itrace_probe {";
181 s.op->indent(1);
182 s.op->newline() << "struct stap_task_finder_target tgt;";
7c3e97f4 183 s.op->newline() << "const struct stap_probe * const probe;";
93646f4d
JS
184 s.op->newline() << "int single_step;";
185 s.op->newline(-1) << "};";
186 s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data);";
2ba1736a 187 s.op->newline() << "#include \"linux/itrace.c\"";
93646f4d
JS
188
189 // output routine to call itrace probe
190 s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data) {";
191 s.op->indent(1);
192
71db462b 193 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe",
cda141c2 194 "stp_probe_type_itrace");
d9aed31e 195 s.op->newline() << "c->uregs = regs;";
e04b5d74 196 s.op->newline() << "c->user_mode_p = 1;";
93646f4d
JS
197
198 // call probe function
26e63673 199 s.op->newline() << "(*p->probe->ph) (c);";
f887a8c9 200 common_probe_entryfn_epilogue (s, true);
93646f4d
JS
201
202 s.op->newline() << "return;";
203 s.op->newline(-1) << "}";
204
205 // Output task finder callback routine that gets called for all
206 // itrace probe types.
207 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) {";
208 s.op->indent(1);
209 s.op->newline() << "int rc = 0;";
210 s.op->newline() << "struct stap_itrace_probe *p = container_of(tgt, struct stap_itrace_probe, tgt);";
211
212 s.op->newline() << "if (register_p) ";
213 s.op->indent(1);
214
c8a44dea 215 s.op->newline() << "rc = usr_itrace_init(p->single_step, tsk, p);";
93646f4d 216 s.op->newline(-1) << "else";
4f600a5f 217 s.op->newline(1) << "remove_usr_itrace_info(find_itrace_info(tsk));";
93646f4d
JS
218 s.op->newline(-1) << "return rc;";
219 s.op->newline(-1) << "}";
220
93646f4d
JS
221 s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {";
222 s.op->indent(1);
223
224 // Set up 'process(PATH)' probes
225 if (! probes_by_path.empty())
226 {
227 for (p_b_path_iterator it = probes_by_path.begin();
228 it != probes_by_path.end(); it++)
229 {
230 for (unsigned i = 0; i < it->second.size(); i++)
231 {
232 itrace_derived_probe *p = it->second[i];
233 emit_probe_decl(s, p);
234 }
235 }
236 }
237
238 // Set up 'process(PID)' probes
239 if (! probes_by_pid.empty())
240 {
241 for (p_b_pid_iterator it = probes_by_pid.begin();
242 it != probes_by_pid.end(); it++)
243 {
244 for (unsigned i = 0; i < it->second.size(); i++)
245 {
246 itrace_derived_probe *p = it->second[i];
247 emit_probe_decl(s, p);
248 }
249 }
250 }
251 s.op->newline(-1) << "};";
252}
253
254
255void
256itrace_derived_probe_group::emit_module_init (systemtap_session& s)
257{
258 if (probes_by_path.empty() && probes_by_pid.empty())
259 return;
260
93646f4d
JS
261 s.op->newline();
262 s.op->newline() << "/* ---- itrace probes ---- */";
263
264 s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {";
265 s.op->indent(1);
266 s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];";
267
268 // 'arch_has_single_step' needs to be defined for either single step mode
269 // or branch mode.
270 s.op->newline() << "if (!arch_has_single_step()) {";
271 s.op->indent(1);
272 s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");";
273 s.op->newline() << "rc = -EPERM;";
274 s.op->newline() << "break;";
275 s.op->newline(-1) << "}";
276 s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {";
277 s.op->indent(1);
278 s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");";
279 s.op->newline() << "rc = -EPERM;";
280 s.op->newline() << "break;";
281 s.op->newline(-1) << "}";
282
283 s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
284 s.op->newline(-1) << "}";
285}
286
287
288void
289itrace_derived_probe_group::emit_module_exit (systemtap_session& s)
290{
291 if (probes_by_path.empty() && probes_by_pid.empty()) return;
292 s.op->newline();
293 s.op->newline() << "/* ---- itrace probes ---- */";
294 s.op->newline() << "cleanup_usr_itrace();";
295}
296
297void
298register_tapset_itrace(systemtap_session& s)
299{
300 match_node* root = s.pattern_root;
301 derived_probe_builder *builder = new itrace_builder();
302
d2c9ec9b 303 root->bind_str(TOK_PROCESS)->bind(TOK_INSN)
d2c9ec9b
DB
304 ->bind(builder);
305 root->bind_num(TOK_PROCESS)->bind(TOK_INSN)
d2c9ec9b
DB
306 ->bind(builder);
307 root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
d2c9ec9b
DB
308 ->bind(builder);
309 root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
d2c9ec9b 310 ->bind(builder);
93646f4d
JS
311}
312
313
314
315/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.140264 seconds and 5 git commands to generate.