]> sourceware.org Git - systemtap.git/blame - tapsets.cxx
2005-08-22 Martin Hunt <hunt@redhat.com>
[systemtap.git] / tapsets.cxx
CommitLineData
56e12059
FCE
1// tapset resolution
2// Copyright (C) 2005 Red Hat Inc.
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
8
9#include "config.h"
10#include "staptree.h"
11#include "elaborate.h"
b55bc428 12#include "tapsets.h"
56e12059 13#include "translate.h"
bd2b1e68
GH
14
15#include <deque>
56e12059 16#include <iostream>
bd2b1e68 17#include <map>
ec4373ff 18#include <set>
56e12059 19#include <sstream>
bd2b1e68 20#include <stdexcept>
b55bc428 21#include <vector>
e36387d7 22#include <cstdarg>
bd2b1e68
GH
23
24extern "C" {
25#include <elfutils/libdwfl.h>
7a053d3b 26#include <elfutils/libdw.h>
77de5e9e
GH
27#include <dwarf.h>
28#include <elf.h>
29#include <obstack.h>
30#include "loc2c.h"
4b1ad75e
RM
31
32#define __STDC_FORMAT_MACROS
33#include <inttypes.h>
bd2b1e68 34}
77de5e9e 35
bd2b1e68 36#include <fnmatch.h>
56e12059
FCE
37
38using namespace std;
39
b55bc428
FCE
40// ------------------------------------------------------------------------
41// begin/end probes are run right during registration / deregistration
56e12059
FCE
42// ------------------------------------------------------------------------
43
b55bc428
FCE
44struct be_derived_probe: public derived_probe
45{
46 bool begin;
47 be_derived_probe (probe* p, bool b): derived_probe (p), begin (b) {}
48 be_derived_probe (probe* p, probe_point* l, bool b):
49 derived_probe (p, l), begin (b) {}
56e12059 50
b55bc428
FCE
51 void emit_registrations (translator_output* o, unsigned i);
52 void emit_deregistrations (translator_output* o, unsigned i);
53 void emit_probe_entries (translator_output* o, unsigned i);
54};
55
98afd80e
FCE
56
57struct be_builder: public derived_probe_builder
b55bc428
FCE
58{
59 bool begin;
60 be_builder(bool b) : begin(b) {}
5227f1ea 61 virtual void build(systemtap_session & sess,
7a053d3b 62 probe * base,
20c6c071
GH
63 probe_point * location,
64 std::map<std::string, literal *> const & parameters,
65 vector<probe *> & results_to_expand_further,
66 vector<derived_probe *> & finished_results)
b55bc428 67 {
20c6c071 68 finished_results.push_back(new be_derived_probe(base, location, begin));
b55bc428 69 }
b55bc428 70};
56e12059
FCE
71
72
7a053d3b 73void
56e12059
FCE
74be_derived_probe::emit_registrations (translator_output* o, unsigned j)
75{
76 if (begin)
77 for (unsigned i=0; i<locations.size(); i++)
bfb3d2d2 78 o->newline() << "enter_" << j << "_" << i << " ();";
56e12059
FCE
79}
80
81
7a053d3b 82void
56e12059
FCE
83be_derived_probe::emit_deregistrations (translator_output* o, unsigned j)
84{
bfb3d2d2 85 if (!begin)
56e12059 86 for (unsigned i=0; i<locations.size(); i++)
bfb3d2d2 87 o->newline() << "enter_" << j << "_" << i << " ();";
56e12059
FCE
88}
89
90
91void
92be_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
93{
94 for (unsigned i=0; i<locations.size(); i++)
95 {
96 probe_point *l = locations[i];
97 o->newline() << "/* location " << i << ": " << *l << " */";
f4b28491
FCE
98 o->newline() << "static void enter_" << j << "_" << i << " (void);";
99 o->newline() << "void enter_" << j << "_" << i << " () {";
bfb3d2d2 100
7a053d3b 101 // While begin/end probes are executed single-threaded, we
bfb3d2d2
FCE
102 // still code defensively and use a per-cpu context.
103 o->newline(1) << "struct context* c = & contexts [smp_processor_id()];";
104
105 // A precondition for running a probe handler is that we're in STARTING
106 // or STOPPING state (not ERROR), and that no one else is already using
107 // this context.
108 o->newline() << "if (atomic_read (&session_state) != ";
109 if (begin) o->line() << "STAP_SESSION_STARTING)";
110 else o->line() << "STAP_SESSION_STOPPING)";
111 o->newline(1) << "return;";
112 o->newline(-1) << "if (c->busy) {";
113 o->newline(1) << "printk (KERN_ERR \"probe reentrancy\");";
114 o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
115 o->newline() << "return;";
116 o->newline(-1) << "}";
117 o->newline();
7a053d3b 118
56e12059 119 o->newline() << "c->busy ++;";
bfb3d2d2 120 o->newline() << "mb ();"; // for smp
5e309481 121 o->newline() << "c->last_error = 0;";
56e12059 122 o->newline() << "c->nesting = 0;";
3d49c615 123 o->newline() << "c->regs = 0;";
5e309481 124 o->newline() << "c->actioncount = 0;";
bfb3d2d2 125
56e12059
FCE
126 // NB: locals are initialized by probe function itself
127 o->newline() << "probe_" << j << " (c);";
bfb3d2d2 128
5e309481
FCE
129 o->newline() << "if (c->last_error) {";
130 o->newline(1) << "if (c->last_error[0]) _stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
131 o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
bfb3d2d2
FCE
132 o->newline(-1) << "}";
133
56e12059 134 o->newline() << "c->busy --;";
bfb3d2d2 135 o->newline() << "mb ();";
56e12059
FCE
136 o->newline(-1) << "}" << endl;
137 }
138}
139
140
141// ------------------------------------------------------------------------
bd2b1e68 142// Dwarf derived probes.
b55bc428 143// ------------------------------------------------------------------------
bd2b1e68 144
c239d28c
GH
145static string TOK_PROCESS("process");
146static string TOK_KERNEL("kernel");
147static string TOK_MODULE("module");
148
149static string TOK_FUNCTION("function");
150static string TOK_RETURN("return");
151static string TOK_CALLEES("callees");
152
153static string TOK_STATEMENT("statement");
154static string TOK_LABEL("label");
155static string TOK_RELATIVE("relative");
156
59ff2773
FCE
157
158// XXX: should standardize to these functions throughout translator
159
7a053d3b 160template <typename OUT, typename IN> inline OUT
77de5e9e
GH
161lex_cast(IN const & in)
162{
163 stringstream ss;
164 OUT out;
165 if (!(ss << in && ss >> out))
166 throw runtime_error("bad lexical cast");
167 return out;
168}
169
59ff2773
FCE
170template <typename OUT, typename IN> inline OUT
171lex_cast_hex(IN const & in)
172{
173 stringstream ss;
174 OUT out;
175 if (!(ss << hex << showbase << in && ss >> out))
176 throw runtime_error("bad lexical cast");
177 return out;
178}
179
180
181
bd2b1e68
GH
182// Helper for dealing with selected portions of libdwfl in a more readable
183// fashion, and with specific cleanup / checking / logging options.
184
91eefb1c
GH
185static const char *
186dwarf_diename_integrate (Dwarf_Die *die)
187{
188 Dwarf_Attribute attr_mem;
189 return dwarf_formstring (dwarf_attr_integrate (die, DW_AT_name, &attr_mem));
190}
191
bd2b1e68
GH
192struct
193dwflpp
194{
5227f1ea 195 systemtap_session & sess;
bd2b1e68
GH
196 Dwfl * dwfl;
197
198 // These are "current" values we focus on.
199 Dwfl_Module * module;
200 Dwarf * module_dwarf;
201 Dwarf_Addr module_bias;
50e0d793
GH
202
203 // These describe the current module's PC address range
204 Dwarf_Addr module_start;
205 Dwarf_Addr module_end;
206
bd2b1e68
GH
207 Dwarf_Die * cu;
208 Dwarf_Func * function;
209
210 string module_name;
211 string cu_name;
212 string function_name;
213
50e0d793 214
7a053d3b 215 string const default_name(char const * in,
bd2b1e68
GH
216 char const * type)
217 {
7a053d3b 218 if (in)
bd2b1e68 219 return in;
24cb178f 220 if (false && sess.verbose)
bd2b1e68 221 clog << "WARNING: no name found for " << type << endl;
a229fcd7 222 return string("");
bd2b1e68
GH
223 }
224
50e0d793 225
5227f1ea
GH
226 void get_module_dwarf()
227 {
228 if (!module_dwarf)
229 module_dwarf = dwfl_module_getdwarf(module, &module_bias);
a229fcd7 230 if (module_dwarf == NULL && sess.verbose)
d9b516ca 231 clog << "WARNING: dwfl_module_getdwarf() : "
a229fcd7 232 << dwfl_errmsg (dwfl_errno ()) << endl;
5227f1ea
GH
233 }
234
50e0d793 235
bd2b1e68
GH
236 void focus_on_module(Dwfl_Module * m)
237 {
238 assert(m);
239 module = m;
7a053d3b 240 module_name = default_name(dwfl_module_info(module, NULL,
50e0d793 241 &module_start, &module_end,
bd2b1e68
GH
242 NULL, NULL,
243 NULL, NULL),
244 "module");
50e0d793
GH
245
246 // Reset existing pointers and names
247
248 module_dwarf = NULL;
249
a229fcd7 250 cu_name.clear();
50e0d793
GH
251 cu = NULL;
252
a229fcd7 253 function_name.clear();
50e0d793 254 function = NULL;
bd2b1e68
GH
255 }
256
50e0d793 257
bd2b1e68
GH
258 void focus_on_cu(Dwarf_Die * c)
259 {
260 assert(c);
50e0d793
GH
261 assert(module);
262
bd2b1e68 263 cu = c;
50e0d793
GH
264 cu_name = default_name(dwarf_diename(c), "CU");
265
266 // Reset existing pointers and names
a229fcd7 267 function_name.clear();
50e0d793 268 function = NULL;
bd2b1e68
GH
269 }
270
50e0d793 271
bd2b1e68
GH
272 void focus_on_function(Dwarf_Func * f)
273 {
274 assert(f);
50e0d793
GH
275 assert(module);
276 assert(cu);
277
bd2b1e68 278 function = f;
7a053d3b 279 function_name = default_name(dwarf_func_name(function),
bd2b1e68 280 "function");
bd2b1e68
GH
281 }
282
50e0d793 283
bd2b1e68
GH
284 void focus_on_module_containing_global_address(Dwarf_Addr a)
285 {
286 assert(dwfl);
50e0d793 287 cu = NULL;
24cb178f 288 if (false && sess.verbose)
bd2b1e68
GH
289 clog << "focusing on module containing global addr " << a << endl;
290 focus_on_module(dwfl_addrmodule(dwfl, a));
291 }
292
50e0d793
GH
293
294 void focus_on_cu_containing_global_address(Dwarf_Addr a)
bd2b1e68 295 {
bd2b1e68 296 Dwarf_Addr bias;
50e0d793 297 assert(dwfl);
5227f1ea 298 get_module_dwarf();
aab2b35f 299 if (false && sess.verbose)
50e0d793 300 clog << "focusing on cu containing global addr " << a << endl;
bd2b1e68
GH
301 focus_on_cu(dwfl_module_addrdie(module, a, &bias));
302 assert(bias == module_bias);
303 }
304
50e0d793
GH
305
306 void focus_on_cu_containing_module_address(Dwarf_Addr a)
bd2b1e68 307 {
50e0d793 308 focus_on_cu_containing_global_address(module_address_to_global(a));
bd2b1e68
GH
309 }
310
50e0d793 311
bd2b1e68
GH
312 Dwarf_Addr module_address_to_global(Dwarf_Addr a)
313 {
50e0d793 314 assert(dwfl);
bd2b1e68 315 assert(module);
5227f1ea 316 get_module_dwarf();
c239d28c
GH
317 if (module_name == TOK_KERNEL)
318 return a;
319
db520b00
FCE
320 if (false && sess.verbose)
321 clog << "module addr " << hex << a
322 << " + module start " << module_start
323 << " -> global addr " << (a + module_start) << dec << endl;
50e0d793 324 return a + module_start;
bd2b1e68
GH
325 }
326
50e0d793 327
bd2b1e68
GH
328 Dwarf_Addr global_address_to_module(Dwarf_Addr a)
329 {
330 assert(module);
5227f1ea 331 get_module_dwarf();
db520b00
FCE
332 if (false && sess.verbose)
333 clog << "global addr " << a
334 << " - module start " << hex << module_start
335 << " -> module addr " << (a - module_start) << dec << endl;
bd2b1e68
GH
336 return a - module_bias;
337 }
338
339
340 bool module_name_matches(string pattern)
341 {
342 assert(module);
343 bool t = (fnmatch(pattern.c_str(), module_name.c_str(), 0) == 0);
24cb178f 344 if (t && sess.verbose)
bd2b1e68 345 clog << "pattern '" << pattern << "' "
24cb178f 346 << "matches "
bd2b1e68
GH
347 << "module '" << module_name << "'" << endl;
348 return t;
349 }
350
50e0d793 351
bd2b1e68
GH
352 bool function_name_matches(string pattern)
353 {
354 assert(function);
355 bool t = (fnmatch(pattern.c_str(), function_name.c_str(), 0) == 0);
24cb178f 356 if (t && sess.verbose)
bd2b1e68 357 clog << "pattern '" << pattern << "' "
24cb178f 358 << "matches "
bd2b1e68
GH
359 << "function '" << function_name << "'" << endl;
360 return t;
361 }
362
50e0d793 363
bd2b1e68
GH
364 bool cu_name_matches(string pattern)
365 {
366 assert(cu);
367 bool t = (fnmatch(pattern.c_str(), cu_name.c_str(), 0) == 0);
24cb178f 368 if (t && sess.verbose)
bd2b1e68 369 clog << "pattern '" << pattern << "' "
24cb178f 370 << "matches "
bd2b1e68
GH
371 << "CU '" << cu_name << "'" << endl;
372 return t;
373 }
374
50e0d793 375
d8067b24 376 void dwflpp_assert(string desc, int rc) // NB: "rc == 0" means OK in this case
bd2b1e68 377 {
d8067b24
FCE
378 string msg = "dwfl failure (" + desc + "): ";
379 if (rc < 0) msg += dwfl_errmsg (rc);
380 else if (rc > 0) msg += strerror (rc);
bd2b1e68 381 if (rc != 0)
d8067b24 382 throw semantic_error (msg);
bd2b1e68
GH
383 }
384
50e0d793 385
5227f1ea 386 dwflpp(systemtap_session & sess)
bd2b1e68 387 :
5227f1ea 388 sess(sess),
bd2b1e68
GH
389 dwfl(NULL),
390 module(NULL),
391 module_dwarf(NULL),
392 module_bias(0),
50e0d793
GH
393 module_start(0),
394 module_end(0),
bd2b1e68
GH
395 cu(NULL),
396 function(NULL)
397 {}
7a053d3b 398
50e0d793 399
bd2b1e68
GH
400 void setup(bool kernel)
401 {
b5d77020
FCE
402 // XXX: this is where the session -R parameter could come in
403 static char* debuginfo_path = "-:.debug:/usr/lib/debug";
404
bd2b1e68
GH
405 static const Dwfl_Callbacks proc_callbacks =
406 {
407 dwfl_linux_proc_find_elf,
408 dwfl_standard_find_debuginfo,
409 NULL,
b5d77020 410 & debuginfo_path
bd2b1e68 411 };
7a053d3b 412
bd2b1e68
GH
413 static const Dwfl_Callbacks kernel_callbacks =
414 {
415 dwfl_linux_kernel_find_elf,
416 dwfl_standard_find_debuginfo,
417 dwfl_linux_kernel_module_section_address,
b5d77020 418 & debuginfo_path
bd2b1e68
GH
419 };
420
421 if (kernel)
422 {
423 dwfl = dwfl_begin(&kernel_callbacks);
424 if (!dwfl)
425 throw semantic_error("cannot open dwfl");
426 dwfl_report_begin(dwfl);
d8067b24
FCE
427 // XXX: if we have only kernel.* probe points, we shouldn't waste time
428 // looking for module debug-info (and vice versa).
429 dwflpp_assert("find kernel debug-info", dwfl_linux_kernel_report_kernel(dwfl));
430 dwflpp_assert("find modules debug-info", dwfl_linux_kernel_report_modules(dwfl));
bd2b1e68
GH
431 }
432 else
433 {
434 dwfl = dwfl_begin(&proc_callbacks);
435 dwfl_report_begin(dwfl);
436 if (!dwfl)
437 throw semantic_error("cannot open dwfl");
438 // XXX: Find pids or processes, do userspace stuff.
439 }
440
377b8831 441 dwflpp_assert("report_end", dwfl_report_end(dwfl, NULL, NULL));
bd2b1e68
GH
442 }
443
444 void iterate_over_modules(int (* callback)(Dwfl_Module *, void **,
445 const char *, Dwarf_Addr,
77de5e9e 446 void *),
bd2b1e68
GH
447 void * data)
448 {
bd2b1e68
GH
449 ptrdiff_t off = 0;
450 do
451 {
77de5e9e 452 off = dwfl_getmodules (dwfl, callback, data, off);
bd2b1e68
GH
453 }
454 while (off > 0);
377b8831 455 dwflpp_assert("getdwarf", off);
bd2b1e68
GH
456 }
457
7a053d3b 458 void iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg),
bd2b1e68
GH
459 void * data)
460 {
5227f1ea
GH
461 get_module_dwarf();
462
bd2b1e68
GH
463 if (!module_dwarf)
464 {
465 cerr << "WARNING: no dwarf info found for module " << module_name << endl;
466 return;
467 }
468
bd2b1e68
GH
469 Dwarf *dw = module_dwarf;
470 Dwarf_Off off = 0;
471 size_t cuhl;
472 Dwarf_Off noff;
473 while (dwarf_nextcu(dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
7a053d3b 474 {
bd2b1e68
GH
475 Dwarf_Die die_mem;
476 Dwarf_Die *die;
477 die = dwarf_offdie(dw, off + cuhl, &die_mem);
478 if (callback(die, data) != DWARF_CB_OK)
479 break;
480 off = noff;
481 }
482 }
483
484 void iterate_over_functions(int (* callback)(Dwarf_Func * func, void * arg),
485 void * data)
486 {
487 assert(module);
488 assert(cu);
bd2b1e68
GH
489 dwarf_getfuncs(cu, callback, data, 0);
490 }
491
492 bool function_entrypc(Dwarf_Addr * addr)
493 {
494 return (dwarf_func_entrypc(function, addr) == 0);
495 }
496
497 bool function_includes_global_addr(Dwarf_Addr addr)
498 {
499 assert(module_dwarf);
500 assert(cu);
501 assert(function);
502 Dwarf_Addr lo, hi;
503 if (dwarf_func_lowpc(function, &lo) != 0)
504 {
db520b00 505 if (false && sess.verbose)
bd2b1e68
GH
506 clog << "WARNING: cannot find low PC value for function " << function_name << endl;
507 return false;
508 }
7a053d3b 509
bd2b1e68
GH
510 if (dwarf_func_highpc(function, &hi) != 0)
511 {
db520b00 512 if (false && sess.verbose)
bd2b1e68
GH
513 clog << "WARNING: cannot find high PC value for function " << function_name << endl;
514 return false;
515 }
7a053d3b 516
bd2b1e68 517 bool t = lo <= addr && addr <= hi;
db520b00
FCE
518 if (t && sess.verbose)
519 clog << "function " << function_name << " = [" << hex << lo << "," << hi << "] "
520 << "contains global addr " << addr << dec << endl;
bd2b1e68
GH
521 return t;
522 }
523
bd2b1e68
GH
524
525 Dwarf_Addr global_addr_of_line_in_cu(int line)
526 {
527 Dwarf_Lines * lines;
bd2b1e68 528 Dwarf_Addr addr;
c239d28c
GH
529 size_t nlines;
530 int best_line = -1;
bd2b1e68
GH
531
532 assert(module);
533 assert(cu);
377b8831 534 dwflpp_assert("getsrclines", dwarf_getsrclines(cu, &lines, &nlines));
50e0d793
GH
535
536 for (size_t i = 0; i < nlines; ++i)
537 {
538 int curr_line;
539 Dwarf_Line * line_rec = dwarf_onesrcline(lines, i);
d9b516ca 540 dwflpp_assert("lineno", dwarf_lineno (line_rec, &curr_line));
c239d28c
GH
541
542 if (curr_line >= line && (best_line == -1 || curr_line < best_line))
50e0d793 543 {
c239d28c 544 best_line = curr_line;
50e0d793 545 dwflpp_assert("lineaddr", dwarf_lineaddr(line_rec, &addr));
50e0d793
GH
546 }
547 }
d9b516ca 548
c239d28c 549 if (best_line != -1)
d9b516ca 550 {
c239d28c
GH
551 if (sess.verbose)
552 clog << "line " << best_line
553 << " (given query line " << line << ")"
554 << " of CU " << cu_name
db520b00
FCE
555 << " has module address " << hex << addr
556 << " in " << module_name << dec << endl;
c239d28c
GH
557 return module_address_to_global(addr);
558 }
50e0d793 559
5227f1ea 560 if (sess.verbose)
d9b516ca 561 clog << "WARNING: could not find line " << line
50e0d793
GH
562 << " in CU " << cu_name << endl;
563 return 0;
564 }
565
566
567 bool function_prologue_end(Dwarf_Addr * addr)
568 {
50e0d793
GH
569 Dwarf_Lines * lines;
570 size_t nlines;
571
572 assert(addr);
573 dwflpp_assert("getsrclines", dwarf_getsrclines(cu, &lines, &nlines));
574
575
576 // If GCC output the right information we would do this:
577 /*
578
579 for (size_t i = 0; i < nlines; ++i)
580 {
581 bool flag;
582 Dwarf_Line * line_rec = dwarf_onesrcline(lines, i);
d9b516ca 583
50e0d793
GH
584 dwflpp_assert("lineprologueend", dwarf_lineprologueend (line_rec, &flag));
585
586 if (sess.verbose)
d9b516ca
RM
587 clog << "checked line record " << i
588 << ", is " << (flag ? "" : " not")
50e0d793
GH
589 << " prologue end" << endl;
590
591 if (flag)
592 {
593 dwflpp_assert("lineaddr", dwarf_lineaddr(line_rec, addr));
594 return true;
595 }
596 }
597 return false;
598 */
599
600 // Since GCC does not output the right information, we do this:
d9b516ca 601
50e0d793
GH
602 Dwarf_Addr entrypc;
603 if (!function_entrypc(&entrypc))
604 return false;
605
606 bool choose_next_line = false;
607
608 for (size_t i = 0; i < nlines; ++i)
609 {
610 Dwarf_Addr line_addr;
611 Dwarf_Line * line_rec = dwarf_onesrcline(lines, i);
612 dwflpp_assert("lineaddr", dwarf_lineaddr(line_rec, &line_addr));
613 if (choose_next_line)
614 {
615 *addr = line_addr;
616 if (sess.verbose)
617 clog << "function " << function_name
c0de7a8d
FCE
618 << " entrypc: " << hex << entrypc
619 << " prologue-end: " << line_addr << dec
50e0d793
GH
620 << endl;
621 return true;
622 }
623 else if (line_addr == entrypc)
624 choose_next_line = true;
625 }
626 return false;
bd2b1e68
GH
627 }
628
e36387d7
RM
629 static void loc2c_error (void *arg, const char *fmt, ...)
630 {
631 char *msg = NULL;
632 va_list ap;
633 va_start (ap, fmt);
634 vasprintf (&msg, fmt, ap);
635 va_end (ap);
636 throw semantic_error (msg);
637 }
bd2b1e68 638
4b1ad75e
RM
639 static void loc2c_emit_address (void *arg, struct obstack *pool,
640 Dwarf_Addr address)
641 {
642 dwflpp *dwfl = (dwflpp *) arg;
643 obstack_printf (pool, "%#" PRIx64 "UL /* hard-coded %s address */",
644 address, dwfl_module_info (dwfl->module, NULL, NULL, NULL,
645 NULL, NULL, NULL, NULL));
646 }
647
77de5e9e 648 string literal_stmt_for_local(Dwarf_Addr pc,
91eefb1c 649 string const & local,
d9b516ca 650 vector<pair<target_symbol::component_type,
91eefb1c 651 std::string> > const & components)
77de5e9e
GH
652 {
653 assert (cu);
654
655 Dwarf_Die *scopes;
656 Dwarf_Die vardie;
657
7a053d3b 658 int nscopes = dwarf_getscopes (cu, pc, &scopes);
77de5e9e
GH
659 if (nscopes == 0)
660 {
7a053d3b 661 throw semantic_error ("unable to find any scopes containing "
59ff2773 662 + lex_cast_hex<string>(pc)
77de5e9e
GH
663 + " while searching for local '" + local + "'");
664 }
7a053d3b 665
77de5e9e 666 int declaring_scope = dwarf_getscopevar (scopes, nscopes,
7a053d3b
RM
667 local.c_str(),
668 0, NULL, 0, 0,
669 &vardie);
77de5e9e
GH
670 if (declaring_scope < 0)
671 {
672 throw semantic_error ("unable to find local '" + local + "'"
59ff2773 673 + " near pc " + lex_cast_hex<string>(pc));
77de5e9e 674 }
7a053d3b 675
77de5e9e
GH
676 Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
677 for (int inner = 0; inner < nscopes; ++inner)
678 {
679 switch (dwarf_tag (&scopes[inner]))
680 {
681 default:
682 continue;
683 case DW_TAG_subprogram:
684 case DW_TAG_entry_point:
685 case DW_TAG_inlined_subroutine: /* XXX */
686 if (inner >= declaring_scope)
687 fb_attr = dwarf_attr_integrate (&scopes[inner],
688 DW_AT_frame_base,
689 &fb_attr_mem);
690 break;
691 }
692 }
693
694 if (sess.verbose)
7a053d3b 695 clog << "finding location for local '" << local
db520b00
FCE
696 << "' near address " << hex << pc
697 << ", module bias " << module_bias << dec
77de5e9e 698 << endl;
7a053d3b
RM
699
700 Dwarf_Attribute attr_mem;
77de5e9e
GH
701 if (dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL)
702 throw semantic_error("failed to retrieve location "
703 "attribute for local '" + local + "'");
7a053d3b 704
77de5e9e
GH
705#define obstack_chunk_alloc malloc
706#define obstack_chunk_free free
7a053d3b 707
77de5e9e 708 struct obstack pool;
7a053d3b 709 obstack_init (&pool);
77de5e9e 710 struct location *tail = NULL;
e36387d7 711 struct location *head = c_translate_location (&pool, &loc2c_error, this,
4b1ad75e 712 &loc2c_emit_address,
e36387d7 713 1, module_bias,
77de5e9e
GH
714 &attr_mem, pc,
715 &tail, fb_attr);
716
d9b516ca 717 if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL)
77de5e9e
GH
718 throw semantic_error("failed to retrieve type "
719 "attribute for local '" + local + "'");
720
d9b516ca
RM
721 Dwarf_Die die_mem, *die = &vardie;
722 unsigned i = 0;
723 while (i < components.size())
724 {
725 die = dwarf_formref_die (&attr_mem, &die_mem);
726 const int typetag = dwarf_tag (die);
727 switch (typetag)
728 {
729 case DW_TAG_typedef:
730 /* Just iterate on the referent type. */
731 break;
91eefb1c 732
d9b516ca
RM
733 case DW_TAG_pointer_type:
734 if (components[i].first == target_symbol::comp_literal_array_index)
735 goto subscript;
91eefb1c 736
d9b516ca
RM
737 c_translate_pointer (&pool, 1, module_bias, die, &tail);
738 break;
91eefb1c 739
d9b516ca
RM
740 case DW_TAG_array_type:
741 if (components[i].first == target_symbol::comp_literal_array_index)
742 {
743 subscript:
744 c_translate_array (&pool, 1, module_bias, die, &tail,
745 NULL, lex_cast<Dwarf_Word>(components[i].second));
746 ++i;
747 }
748 else
749 throw semantic_error("bad field '"
750 + components[i].second
751 + "' for array type");
752 break;
91eefb1c 753
d9b516ca
RM
754 case DW_TAG_structure_type:
755 case DW_TAG_union_type:
756 switch (dwarf_child (die, &die_mem))
757 {
758 case 1: /* No children. */
759 throw semantic_error ("empty struct "
760 + string (dwarf_diename_integrate (die) ?: "<anonymous>"));
761 break;
762 case -1: /* Error. */
763 default: /* Shouldn't happen */
764 throw semantic_error (string (typetag == DW_TAG_union_type ? "union" : "struct")
765 + string (dwarf_diename_integrate (die) ?: "<anonymous>")
766 + string (dwarf_errmsg (-1)));
767 break;
768
769 case 0:
770 break;
771 }
772
773 while (dwarf_tag (die) != DW_TAG_member
774 || ({ const char *member = dwarf_diename_integrate (die);
775 member == NULL || string(member) != components[i].second; }))
776 if (dwarf_siblingof (die, &die_mem) != 0)
777 throw semantic_error ("field name " + components[i].second + " not found");
778
779 if (dwarf_attr_integrate (die, DW_AT_data_member_location,
780 &attr_mem) == NULL)
781 {
782 /* Union members don't usually have a location,
783 but just use the containing union's location. */
784 if (typetag != DW_TAG_union_type)
785 throw semantic_error ("no location for field "
786 + components[i].second
787 + " :" + string(dwarf_errmsg (-1)));
788 }
789 else
4b1ad75e 790 c_translate_location (&pool, NULL, NULL, NULL, 1,
e36387d7 791 module_bias, &attr_mem, pc,
d9b516ca
RM
792 &tail, NULL);
793 ++i;
794 break;
795
796 case DW_TAG_base_type:
797 throw semantic_error ("field "
798 + components[i].second
799 + " vs base type "
800 + string(dwarf_diename_integrate (die) ?: "<anonymous type>"));
801 break;
802 case -1:
803 throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)));
804 break;
805
806 default:
807 throw semantic_error (string(dwarf_diename_integrate (die) ?: "<anonymous type>")
808 + ": unexpected type tag "
809 + lex_cast<string>(dwarf_tag (die)));
810 break;
811 }
812
813 /* Now iterate on the type in DIE's attribute. */
814 if (dwarf_attr_integrate (die, DW_AT_type, &attr_mem) == NULL)
815 throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
816 }
91eefb1c 817
d9b516ca
RM
818 /* Fetch the type DIE corresponding to the final location to be accessed.
819 It must be a base type or a typedef for one. */
820
821 Dwarf_Die typedie_mem;
822 Dwarf_Die *typedie;
823 int typetag;
824 while (1)
825 {
826 typedie = dwarf_formref_die (&attr_mem, &typedie_mem);
827 if (typedie == NULL)
828 throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
829 typetag = dwarf_tag (typedie);
830 if (typetag != DW_TAG_typedef)
91eefb1c 831 break;
d9b516ca
RM
832 if (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem) == NULL)
833 throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
834 }
91eefb1c 835
d9b516ca
RM
836 if (typetag != DW_TAG_base_type)
837 throw semantic_error ("target location not a base type");
91eefb1c 838
d9b516ca 839 c_translate_fetch (&pool, 1, module_bias, die, typedie, &tail,
77de5e9e 840 "THIS->__retvalue");
7a053d3b 841
77de5e9e
GH
842 size_t bufsz = 1024;
843 char *buf = static_cast<char*>(malloc(bufsz));
844 assert(buf);
7a053d3b 845
77de5e9e
GH
846 FILE *memstream = open_memstream (&buf, &bufsz);
847 assert(memstream);
7a053d3b 848
77de5e9e 849 bool deref = c_emit_location (memstream, head, 1);
a781f401 850 fprintf(memstream, " goto out;\n");
7a053d3b 851
a781f401
FCE
852 // dummy use of deref_fault label, to disable warning if deref() not used
853 fprintf(memstream, "if (0) goto deref_fault;\n");
854
855 // XXX: deref flag not reliable; emit fault label unconditionally
856 if (deref) ;
857 fprintf(memstream,
858 "deref_fault:\n"
5e309481 859 " c->last_error = \"pointer dereference fault\";\n"
a781f401 860 " goto out;\n");
7a053d3b 861
77de5e9e
GH
862 fclose (memstream);
863 string result(buf);
864 free (buf);
865 return result;
866 }
7a053d3b
RM
867
868
77de5e9e 869
bd2b1e68
GH
870 ~dwflpp()
871 {
872 if (dwfl)
873 dwfl_end(dwfl);
874 }
875};
876
20c6c071 877
7a053d3b 878enum
bd2b1e68 879function_spec_type
7a053d3b 880 {
bd2b1e68
GH
881 function_alone,
882 function_and_file,
7a053d3b 883 function_file_and_line
bd2b1e68
GH
884 };
885
ec4373ff 886
bd2b1e68 887struct dwarf_builder;
77de5e9e
GH
888struct dwarf_query;
889
bd2b1e68 890struct dwarf_derived_probe : public derived_probe
b55bc428 891{
77de5e9e 892 dwarf_derived_probe (dwarf_query & q,
20c6c071 893 Dwarf_Addr addr);
d9b516ca 894
20c6c071 895 string module_name;
a229fcd7
GH
896 string function_name;
897 bool has_statement;
20c6c071 898 Dwarf_Addr addr;
a229fcd7 899 Dwarf_Addr module_bias;
fd6602a0 900 bool has_return;
7a053d3b 901
bd2b1e68 902 // Pattern registration helpers.
7a053d3b 903 static void register_relative_variants(match_node * root,
bd2b1e68 904 dwarf_builder * dw);
7a053d3b 905 static void register_statement_variants(match_node * root,
bd2b1e68 906 dwarf_builder * dw);
fd6602a0
FCE
907 static void register_function_variants(match_node * root,
908 dwarf_builder * dw);
7a053d3b 909 static void register_function_and_statement_variants(match_node * root,
bd2b1e68 910 dwarf_builder * dw);
20c6c071 911 static void register_patterns(match_node * root);
7a053d3b 912
20c6c071
GH
913 virtual void emit_registrations (translator_output * o, unsigned i);
914 virtual void emit_deregistrations (translator_output * o, unsigned i);
915 virtual void emit_probe_entries (translator_output * o, unsigned i);
20c6c071
GH
916};
917
918// Helper struct to thread through the dwfl callbacks.
7a053d3b 919struct
20c6c071
GH
920dwarf_query
921{
5227f1ea
GH
922 dwarf_query(systemtap_session & sess,
923 probe * base_probe,
20c6c071
GH
924 probe_point * base_loc,
925 dwflpp & dw,
926 map<string, literal *> const & params,
927 vector<derived_probe *> & results);
bd2b1e68 928
5227f1ea
GH
929 systemtap_session & sess;
930
bd2b1e68 931 // Parameter extractors.
7a053d3b 932 static bool has_null_param(map<string, literal *> const & params,
bd2b1e68 933 string const & k);
7a053d3b 934 static bool get_string_param(map<string, literal *> const & params,
bd2b1e68 935 string const & k, string & v);
7a053d3b 936 static bool get_number_param(map<string, literal *> const & params,
bd2b1e68 937 string const & k, long & v);
c239d28c
GH
938 static bool get_number_param(map<string, literal *> const & params,
939 string const & k, Dwarf_Addr & v);
b55bc428 940
77de5e9e
GH
941 string pt_regs_member_for_regnum(uint8_t dwarf_regnum);
942
20c6c071 943 vector<derived_probe *> & results;
20c6c071
GH
944
945 bool has_kernel;
946 bool has_process;
947 bool has_module;
7a053d3b
RM
948 string process_val;
949 string module_val;
950 string function_val;
20c6c071
GH
951
952 bool has_function_str;
953 bool has_statement_str;
954 bool has_function_num;
955 bool has_statement_num;
7a053d3b
RM
956 string statement_str_val;
957 string function_str_val;
c239d28c
GH
958 Dwarf_Addr statement_num_val;
959 Dwarf_Addr function_num_val;
20c6c071
GH
960
961 bool has_callees;
7a053d3b 962 long callee_val;
20c6c071
GH
963
964 bool has_return;
965
966 bool has_label;
967 string label_val;
968
969 bool has_relative;
970 long relative_val;
971
972 function_spec_type parse_function_spec(string & spec);
973 function_spec_type spec_type;
974 string function;
975 string file;
976 int line;
977
978 probe * base_probe;
979 probe_point * base_loc;
980 dwflpp & dw;
b55bc428
FCE
981};
982
98afd80e
FCE
983
984struct dwarf_builder: public derived_probe_builder
b55bc428 985{
bd2b1e68 986 dwarf_builder() {}
5227f1ea 987 virtual void build(systemtap_session & sess,
7a053d3b 988 probe * base,
20c6c071
GH
989 probe_point * location,
990 std::map<std::string, literal *> const & parameters,
991 vector<probe *> & results_to_expand_further,
992 vector<derived_probe *> & finished_results);
b55bc428
FCE
993};
994
7a053d3b
RM
995bool
996dwarf_query::has_null_param(map<string, literal *> const & params,
20c6c071 997 string const & k)
bd2b1e68
GH
998{
999 map<string, literal *>::const_iterator i = params.find(k);
1000 if (i != params.end() && i->second == NULL)
1001 return true;
1002 return false;
1003}
1004
7a053d3b
RM
1005bool
1006dwarf_query::get_string_param(map<string, literal *> const & params,
20c6c071 1007 string const & k, string & v)
bd2b1e68 1008{
98afd80e 1009 return derived_probe_builder::get_param (params, k, v);
bd2b1e68
GH
1010}
1011
7a053d3b
RM
1012bool
1013dwarf_query::get_number_param(map<string, literal *> const & params,
20c6c071 1014 string const & k, long & v)
bd2b1e68 1015{
98afd80e
FCE
1016 int64_t value;
1017 bool present = derived_probe_builder::get_param (params, k, value);
1018 v = (long) value;
1019 return present;
bd2b1e68
GH
1020}
1021
c239d28c
GH
1022bool
1023dwarf_query::get_number_param(map<string, literal *> const & params,
1024 string const & k, Dwarf_Addr & v)
1025{
98afd80e
FCE
1026 int64_t value;
1027 bool present = derived_probe_builder::get_param (params, k, value);
1028 v = (Dwarf_Addr) value;
1029 return present;
c239d28c
GH
1030}
1031
77de5e9e 1032
5227f1ea
GH
1033dwarf_query::dwarf_query(systemtap_session & sess,
1034 probe * base_probe,
20c6c071
GH
1035 probe_point * base_loc,
1036 dwflpp & dw,
1037 map<string, literal *> const & params,
1038 vector<derived_probe *> & results)
5227f1ea
GH
1039 : sess(sess),
1040 results(results),
7a053d3b 1041 base_probe(base_probe),
20c6c071
GH
1042 base_loc(base_loc),
1043 dw(dw)
bd2b1e68 1044{
20c6c071 1045
bd2b1e68
GH
1046 // Reduce the query to more reasonable semantic values (booleans,
1047 // extracted strings, numbers, etc).
1048
1049 has_kernel = has_null_param(params, TOK_KERNEL);
1050 has_module = get_string_param(params, TOK_MODULE, module_val);
1051 has_process = get_string_param(params, TOK_PROCESS, process_val);
1052
1053 has_function_str = get_string_param(params, TOK_FUNCTION, function_str_val);
1054 has_function_num = get_number_param(params, TOK_FUNCTION, function_num_val);
1055
1056 has_statement_str = get_string_param(params, TOK_STATEMENT, statement_str_val);
1057 has_statement_num = get_number_param(params, TOK_STATEMENT, statement_num_val);
1058
1059 callee_val = 1;
7a053d3b 1060 has_callees = (has_null_param(params, TOK_CALLEES) ||
bd2b1e68
GH
1061 get_number_param(params, TOK_CALLEES, callee_val));
1062
1063 has_return = has_null_param(params, TOK_RETURN);
1064
1065 has_label = get_string_param(params, TOK_LABEL, label_val);
1066 has_relative = get_number_param(params, TOK_RELATIVE, relative_val);
7a053d3b 1067
bd2b1e68
GH
1068 if (has_function_str)
1069 spec_type = parse_function_spec(function_str_val);
1070 else if (has_statement_str)
1071 spec_type = parse_function_spec(statement_str_val);
7a053d3b 1072}
bd2b1e68
GH
1073
1074
bd2b1e68 1075function_spec_type
20c6c071 1076dwarf_query::parse_function_spec(string & spec)
bd2b1e68
GH
1077{
1078 string::const_iterator i = spec.begin(), e = spec.end();
7a053d3b 1079
bd2b1e68
GH
1080 function.clear();
1081 file.clear();
1082 line = 0;
1083
1084 while (i != e && *i != '@')
1085 {
1086 if (*i == ':')
1087 goto bad;
1088 function += *i++;
1089 }
1090
1091 if (i == e)
1092 {
5227f1ea 1093 if (sess.verbose)
7a053d3b
RM
1094 clog << "parsed '" << spec
1095 << "' -> func '" << function
bd2b1e68
GH
1096 << "'" << endl;
1097 return function_alone;
1098 }
1099
1100 if (i++ == e)
1101 goto bad;
1102
1103 while (i != e && *i != ':')
1104 file += *i++;
7a053d3b 1105
bd2b1e68
GH
1106 if (i == e)
1107 {
5227f1ea 1108 if (sess.verbose)
7a053d3b
RM
1109 clog << "parsed '" << spec
1110 << "' -> func '"<< function
1111 << "', file '" << file
bd2b1e68
GH
1112 << "'" << endl;
1113 return function_and_file;
1114 }
1115
1116 if (i++ == e)
1117 goto bad;
1118
1119 try
1120 {
1121 line = lex_cast<int>(string(i, e));
5227f1ea 1122 if (sess.verbose)
7a053d3b
RM
1123 clog << "parsed '" << spec
1124 << "' -> func '"<< function
1125 << "', file '" << file
bd2b1e68
GH
1126 << "', line " << line << endl;
1127 return function_file_and_line;
1128 }
1129 catch (runtime_error & exn)
1130 {
1131 goto bad;
1132 }
1133
1134 bad:
7a053d3b 1135 throw semantic_error("malformed specification '" + spec + "'",
20c6c071 1136 base_probe->tok);
bd2b1e68
GH
1137}
1138
1139
1140static void
20c6c071 1141query_statement(Dwarf_Addr stmt_addr, dwarf_query * q)
bd2b1e68 1142{
39bcd429
FCE
1143 try
1144 {
1145 // XXX: implement
1146 if (q->has_relative)
1147 throw semantic_error("incomplete: do not know how to interpret .relative",
1148 q->base_probe->tok);
d9b516ca 1149
39bcd429
FCE
1150 q->results.push_back(new dwarf_derived_probe(*q, stmt_addr));
1151 }
1152 catch (const semantic_error& e)
1153 {
1154 q->sess.print_error (e);
1155 }
bd2b1e68
GH
1156}
1157
1158static int
1159query_function(Dwarf_Func * func, void * arg)
1160{
20c6c071 1161 dwarf_query * q = static_cast<dwarf_query *>(arg);
bd2b1e68 1162
39bcd429 1163 try
7a053d3b 1164 {
39bcd429
FCE
1165 // XXX: implement
1166 if (q->has_callees)
1167 throw semantic_error("incomplete: do not know how to interpret .callees",
1168 q->base_probe->tok);
d9b516ca 1169
39bcd429
FCE
1170 if (q->has_label)
1171 throw semantic_error("incomplete: do not know how to interpret .label",
1172 q->base_probe->tok);
d9b516ca 1173
39bcd429 1174 q->dw.focus_on_function(func);
d9b516ca 1175
39bcd429 1176 Dwarf_Addr entry_addr;
d9b516ca 1177
39bcd429 1178 if (q->has_statement_str || q->has_function_str)
d9b516ca 1179 {
39bcd429
FCE
1180 if (q->dw.function_name_matches(q->function))
1181 {
b5d77020
FCE
1182 if (q->sess.verbose)
1183 clog << "focused on function '" << q->dw.function_name
1184 << "', in CU '" << q->dw.cu_name
1185 << "', module '" << q->dw.module_name << "'" << endl;
1186
39bcd429
FCE
1187 // XXX: This code is duplicated below, but it's important
1188 // for performance reasons to test things in this order.
b5d77020 1189
db520b00 1190 if (q->has_statement_str)
39bcd429 1191 {
db520b00
FCE
1192 // XXX: look up address corresponding to statement string,
1193 // which could be any old line within a function definition.
1194 cerr << "WARNING: cannot handle statement "
1195 << q->statement_str_val << " address" << endl;
39bcd429
FCE
1196 return DWARF_CB_OK;
1197 }
db520b00
FCE
1198 if (q->has_return)
1199 {
1200 bool ok = q->dw.function_entrypc (& entry_addr);
1201 if (! ok)
1202 {
1203 if (q->sess.verbose)
1204 cerr << "WARNING: cannot find entry-pc for function "
1205 << q->dw.function_name << endl;
1206 return DWARF_CB_OK;
1207 }
1208 if (q->sess.verbose)
d9b516ca 1209 clog << "function " << q->dw.function_name
db520b00
FCE
1210 << " entrypc: " << hex << entry_addr << dec << endl;
1211 }
1212 else
1213 {
1214 bool ok = q->dw.function_prologue_end(& entry_addr);
1215 if (! ok)
1216 {
1217 // XXX: but this is actually OK for inlined function instances
1218 if (q->sess.verbose)
1219 cerr << "WARNING: cannot find prologue-end PC for function "
1220 << q->dw.function_name << endl;
1221 return DWARF_CB_OK;
1222 }
1223 }
d9b516ca 1224
39bcd429
FCE
1225 // If this function's name matches a function or statement
1226 // pattern, we use its entry pc, but we do not abort iteration
1227 // since there might be other functions matching the pattern.
1228 query_statement(entry_addr, q);
1229 }
1230 }
1231 else
1232 {
1233 if (q->has_function_num || q->has_statement_num)
1234 {
1235 Dwarf_Addr query_addr = (q->has_function_num
1236 ? q->function_num_val
1237 : q->statement_num_val);
d9b516ca 1238
39bcd429 1239 // Adjust module-relative address to global
d9b516ca 1240
39bcd429
FCE
1241 if (q->has_module)
1242 query_addr = q->dw.module_address_to_global(query_addr);
d9b516ca 1243
39bcd429
FCE
1244 if (q->dw.function_includes_global_addr(query_addr))
1245 {
db520b00
FCE
1246 if (q->has_statement_num) // has_statement
1247 entry_addr = 0; // unused, see below
1248 else if (q->has_return) // has_function
39bcd429 1249 {
db520b00
FCE
1250 bool ok = q->dw.function_entrypc (& entry_addr);
1251 if (! ok)
1252 {
1253 if (q->sess.verbose)
1254 cerr << "WARNING: cannot find entry-pc for function "
1255 << q->dw.function_name << endl;
1256 return DWARF_CB_OK;
1257 }
1258 if (q->sess.verbose)
d9b516ca 1259 clog << "function " << q->dw.function_name
db520b00
FCE
1260 << " entrypc: " << hex << entry_addr << dec << endl;
1261 }
1262 else // has_function
1263 {
1264 bool ok = q->dw.function_prologue_end(& entry_addr);
1265 if (! ok)
1266 {
1267 // XXX: but this is actually OK for inlined function instances
1268 if (q->sess.verbose)
1269 cerr << "WARNING: cannot find prologue-end PC for function "
1270 << q->dw.function_name << endl;
1271 return DWARF_CB_OK;
1272 }
39bcd429 1273 }
d9b516ca 1274
39bcd429
FCE
1275 query_statement(q->has_function_num ? entry_addr : query_addr, q);
1276 return DWARF_CB_ABORT;
1277 }
1278 }
1279 }
d9b516ca 1280
39bcd429 1281 return DWARF_CB_OK;
bd2b1e68 1282 }
39bcd429 1283 catch (const semantic_error& e)
bd2b1e68 1284 {
39bcd429
FCE
1285 q->sess.print_error (e);
1286 return DWARF_CB_ABORT;
bd2b1e68 1287 }
bd2b1e68
GH
1288}
1289
1290static int
1291query_cu (Dwarf_Die * cudie, void * arg)
1292{
20c6c071 1293 dwarf_query * q = static_cast<dwarf_query *>(arg);
7a053d3b 1294
39bcd429 1295 try
bd2b1e68 1296 {
39bcd429 1297 q->dw.focus_on_cu(cudie);
d9b516ca 1298
39bcd429
FCE
1299 // If we have enough information in the pattern to skip a CU
1300 // and the CU does not match that information, return early.
1301 if ((q->has_statement_str || q->has_function_str)
1302 && (q->spec_type == function_file_and_line ||
1303 q->spec_type == function_and_file)
1304 && (!q->dw.cu_name_matches(q->file)))
1305 return DWARF_CB_OK;
b5d77020
FCE
1306
1307 if (false && q->sess.verbose)
1308 clog << "focused on CU '" << q->dw.cu_name
1309 << "', in module '" << q->dw.module_name << "'" << endl;
d9b516ca 1310
39bcd429
FCE
1311 if (q->has_statement_str
1312 && (q->spec_type == function_file_and_line)
1313 && q->dw.cu_name_matches(q->file))
1314 {
1315 // If we have a complete file:line statement
1316 // functor (not function functor) landing on
1317 // this CU, we can look up a specific address
1318 // for the statement, and skip scanning
1319 // the remaining functions within the CU.
1320 query_statement(q->dw.global_addr_of_line_in_cu(q->line), q);
1321 }
c239d28c
GH
1322 else if (q->has_function_str
1323 && (q->spec_type == function_file_and_line)
1324 && q->dw.cu_name_matches(q->file))
1325 {
1326 // If we have a complete file:line *function* functor
1327 // landing on this CU, we need to select only the functions
1328 // which land on the line in question. We *could* check each
1329 // function individually but the line->addr lookup is
1330 // expensive, so we do it once here, then temporarily switch
1331 // to a .function(addr) query for the remaining function
1332 // iteration, switching back when we complete.
1333 q->function_num_val = q->dw.global_addr_of_line_in_cu(q->line);
1334 swap(q->has_function_str, q->has_function_num);
1335 q->dw.iterate_over_functions(&query_function, q);
1336 swap(q->has_function_str, q->has_function_num);
1337 }
39bcd429
FCE
1338 else
1339 {
c239d28c
GH
1340 // Otherwise we need to scan all the functions in this CU,
1341 // matching by function name or address, as requested.
39bcd429
FCE
1342 q->dw.iterate_over_functions(&query_function, q);
1343 }
1344 return DWARF_CB_OK;
bd2b1e68 1345 }
39bcd429 1346 catch (const semantic_error& e)
bd2b1e68 1347 {
39bcd429
FCE
1348 q->sess.print_error (e);
1349 return DWARF_CB_ABORT;
bd2b1e68 1350 }
bd2b1e68
GH
1351}
1352
1353static int
1354query_module (Dwfl_Module *mod __attribute__ ((unused)),
1355 void **userdata __attribute__ ((unused)),
1356 const char *name, Dwarf_Addr base,
bd2b1e68
GH
1357 void *arg __attribute__ ((unused)))
1358{
20c6c071 1359 dwarf_query * q = static_cast<dwarf_query *>(arg);
bd2b1e68 1360
39bcd429 1361 try
bd2b1e68 1362 {
39bcd429 1363 q->dw.focus_on_module(mod);
d9b516ca 1364
39bcd429
FCE
1365 // If we have enough information in the pattern to skip a module and
1366 // the module does not match that information, return early.
d9b516ca 1367
39bcd429
FCE
1368 if (q->has_kernel && !q->dw.module_name_matches(TOK_KERNEL))
1369 return DWARF_CB_OK;
d9b516ca 1370
39bcd429
FCE
1371 if (q->has_module && !q->dw.module_name_matches(q->module_val))
1372 return DWARF_CB_OK;
b5d77020
FCE
1373
1374 if (q->sess.verbose)
d9b516ca
RM
1375 clog << "focused on module '" << q->dw.module_name
1376 << "' = [" << hex << q->dw.module_start
1377 << "-" << q->dw.module_end
c0de7a8d 1378 << ", bias " << q->dw.module_bias << "]" << dec << endl;
b5d77020 1379
39bcd429
FCE
1380 if (q->has_function_num || q->has_statement_num)
1381 {
1382 // If we have module("foo").function(0xbeef) or
1383 // module("foo").statement(0xbeef), the address is relative
1384 // to the start of the module, so we seek the function
1385 // number plus the module's bias.
1386 Dwarf_Addr addr;
1387 if (q->has_function_num)
1388 addr = q->function_num_val;
1389 else
1390 addr = q->statement_num_val;
d9b516ca 1391
39bcd429
FCE
1392 if (q->has_kernel)
1393 q->dw.focus_on_cu_containing_global_address(addr);
1394 else
1395 q->dw.focus_on_cu_containing_module_address(addr);
d9b516ca 1396
39bcd429
FCE
1397 q->dw.iterate_over_functions(&query_function, q);
1398 }
50e0d793 1399 else
39bcd429
FCE
1400 {
1401 // Otherwise if we have a function("foo") or statement("foo")
1402 // specifier, we have to scan over all the CUs looking for
1403 // the function in question
1404 assert(q->has_function_str || q->has_statement_str);
1405 q->dw.iterate_over_cus(&query_cu, q);
1406 }
d9b516ca 1407
39bcd429
FCE
1408 // If we just processed the module "kernel", and the user asked for
1409 // the kernel pattern, there's no need to iterate over any further
1410 // modules
d9b516ca 1411
39bcd429
FCE
1412 if (q->has_kernel && q->dw.module_name_matches(TOK_KERNEL))
1413 return DWARF_CB_ABORT;
d9b516ca 1414
39bcd429 1415 return DWARF_CB_OK;
7a053d3b 1416 }
39bcd429 1417 catch (const semantic_error& e)
bd2b1e68 1418 {
39bcd429
FCE
1419 q->sess.print_error (e);
1420 return DWARF_CB_ABORT;
bd2b1e68 1421 }
bd2b1e68
GH
1422}
1423
77de5e9e
GH
1424struct
1425var_expanding_copy_visitor
1426 : public deep_copy_visitor
1427{
77de5e9e
GH
1428 static unsigned tick;
1429
1430 dwarf_query & q;
77de5e9e
GH
1431 Dwarf_Addr addr;
1432
7a053d3b 1433 var_expanding_copy_visitor(dwarf_query & q, Dwarf_Addr a)
d7f3e0c5 1434 : q(q), addr(a)
77de5e9e 1435 {}
d7f3e0c5 1436 void visit_target_symbol (target_symbol* e);
77de5e9e
GH
1437};
1438
1439
1440unsigned var_expanding_copy_visitor::tick = 0;
1441
1442
1443void
d7f3e0c5 1444var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
77de5e9e 1445{
d7f3e0c5 1446 assert(e->base_name.size() > 0 && e->base_name[0] == '$');
d9b516ca 1447
d7f3e0c5 1448 if (is_active_lvalue(e))
77de5e9e 1449 {
d7f3e0c5
GH
1450 throw semantic_error("read-only special variable "
1451 + e->base_name + " used as lvalue", e->tok);
77de5e9e 1452 }
d9b516ca 1453
d7f3e0c5
GH
1454 string fname = "get_" + e->base_name.substr(1) + "_" + lex_cast<string>(tick++);
1455
1456 // synthesize a function
1457 functiondecl *fdecl = new functiondecl;
1458 embeddedcode *ec = new embeddedcode;
5e309481 1459 ec->tok = e->tok;
d9b516ca 1460 ec->code = q.dw.literal_stmt_for_local(addr,
91eefb1c
GH
1461 e->base_name.substr(1),
1462 e->components);
d7f3e0c5
GH
1463 fdecl->name = fname;
1464 fdecl->body = ec;
1465 fdecl->type = pe_long;
1466 q.sess.functions.push_back(fdecl);
d9b516ca 1467
d7f3e0c5
GH
1468 // synthesize a call
1469 functioncall* n = new functioncall;
1470 n->tok = e->tok;
1471 n->function = fname;
1472 n->referent = NULL;
d9b516ca 1473 provide <functioncall*> (this, n);
77de5e9e
GH
1474}
1475
1476
7a053d3b 1477dwarf_derived_probe::dwarf_derived_probe (dwarf_query & q,
20c6c071 1478 Dwarf_Addr addr)
a229fcd7
GH
1479 : derived_probe (NULL),
1480 module_name(q.dw.module_name),
1481 function_name(q.dw.function_name),
1482 has_statement(q.has_statement_str || q.has_statement_num),
fd6602a0 1483 addr(addr),
a229fcd7 1484 module_bias(q.dw.module_bias),
fd6602a0 1485 has_return (q.has_return)
bd2b1e68 1486{
a229fcd7
GH
1487 // first synthesize an "expanded" location
1488 vector<probe_point::component*> comps;
1489 comps.push_back
1490 (module_name == TOK_KERNEL
1491 ? new probe_point::component(TOK_KERNEL)
db520b00 1492 : new probe_point::component(TOK_MODULE, new literal_string(module_name)));
b5d77020 1493
db520b00
FCE
1494 string fn_or_stmt;
1495 if (q.has_function_str || q.has_function_num)
1496 fn_or_stmt = "function";
1497 else
1498 fn_or_stmt = "statement";
a229fcd7 1499
db520b00
FCE
1500 if (q.has_function_str || q.has_statement_str)
1501 {
1502 string retro_name;;
1503 if (! function_name.empty())
1504 retro_name = function_name + "@" + q.dw.cu_name; // XXX: add line number
1505 else if (q.has_function_str)
1506 retro_name = q.function_str_val;
1507 else // has_statement_str
1508 retro_name = q.statement_str_val;
1509 // XXX: actually the statement_str case is not yet adequately
1510 // handled in the search code
1511
1512 comps.push_back
1513 (new probe_point::component
1514 (fn_or_stmt, new literal_string (retro_name)));
1515 }
1516 else if (q.has_function_num || q.has_statement_num)
1517 {
1518 Dwarf_Addr retro_addr;
1519 if (q.has_function_num)
1520 retro_addr = q.function_num_val;
1521 else
1522 retro_addr = q.statement_num_val;
1523
1524 comps.push_back (new probe_point::component
1525 (fn_or_stmt,
1526 new literal_number(retro_addr))); // XXX: should be hex if possible
a229fcd7
GH
1527 }
1528
db520b00 1529 if (has_return)
a229fcd7 1530 comps.push_back
db520b00 1531 (new probe_point::component(TOK_RETURN));
d9b516ca 1532
a229fcd7
GH
1533 assert(q.base_probe->locations.size() > 0);
1534 locations.push_back(new probe_point(comps, q.base_probe->locations[0]->tok));
1535
1536 // Now make a local-variable-expanded copy of the probe body
77de5e9e
GH
1537 var_expanding_copy_visitor v (q, addr);
1538 require <block*> (&v, &(this->body), q.base_probe->body);
1539 this->tok = q.base_probe->tok;
bd2b1e68
GH
1540}
1541
7a053d3b 1542void
20c6c071 1543dwarf_derived_probe::register_relative_variants(match_node * root,
bd2b1e68
GH
1544 dwarf_builder * dw)
1545{
1546 // Here we match 2 forms:
1547 //
1548 // .
1549 // .relative(NN)
1550
20c6c071
GH
1551 root->bind(dw);
1552 root->bind_num(TOK_RELATIVE)->bind(dw);
bd2b1e68
GH
1553}
1554
7a053d3b 1555void
20c6c071 1556dwarf_derived_probe::register_statement_variants(match_node * root,
bd2b1e68
GH
1557 dwarf_builder * dw)
1558{
1559 // Here we match 3 forms:
1560 //
1561 // .
1562 // .return
1563 // .label("foo")
7a053d3b 1564
bd2b1e68 1565 register_relative_variants(root, dw);
20c6c071 1566 register_relative_variants(root->bind_str(TOK_LABEL), dw);
bd2b1e68
GH
1567}
1568
7a053d3b 1569void
fd6602a0 1570dwarf_derived_probe::register_function_variants(match_node * root,
bd2b1e68
GH
1571 dwarf_builder * dw)
1572{
a229fcd7 1573 // Here we match 4 forms:
bd2b1e68
GH
1574 //
1575 // .
fd6602a0 1576 // .return
bd2b1e68
GH
1577 // .callees
1578 // .callees(N)
1579 //
1580 // The last form permits N-level callee resolving without any
1581 // recursive .callees.callees.callees... pattern-matching on our part.
1582
fd6602a0
FCE
1583 root->bind(dw);
1584 root->bind(TOK_RETURN)->bind(dw);
1585 root->bind(TOK_CALLEES)->bind(dw);
1586 root->bind_num(TOK_CALLEES)->bind(dw);
bd2b1e68
GH
1587}
1588
7a053d3b 1589void
20c6c071 1590dwarf_derived_probe::register_function_and_statement_variants(match_node * root,
bd2b1e68
GH
1591 dwarf_builder * dw)
1592{
1593 // Here we match 4 forms:
1594 //
1595 // .function("foo")
1596 // .function(0xdeadbeef)
1597 // .statement("foo")
1598 // .statement(0xdeadbeef)
1599
fd6602a0
FCE
1600 register_function_variants(root->bind_str(TOK_FUNCTION), dw);
1601 register_function_variants(root->bind_num(TOK_FUNCTION), dw);
20c6c071
GH
1602 register_statement_variants(root->bind_str(TOK_STATEMENT), dw);
1603 register_statement_variants(root->bind_num(TOK_STATEMENT), dw);
bd2b1e68
GH
1604}
1605
1606void
20c6c071 1607dwarf_derived_probe::register_patterns(match_node * root)
bd2b1e68
GH
1608{
1609 dwarf_builder *dw = new dwarf_builder();
1610
1611 // Here we match 3 forms:
1612 //
1613 // .kernel
1614 // .module("foo")
1615 // .process("foo")
1616
20c6c071 1617 register_function_and_statement_variants(root->bind(TOK_KERNEL), dw);
fe3d01fa 1618 // XXX: may need to disable these for 2005-08 release
20c6c071
GH
1619 register_function_and_statement_variants(root->bind_str(TOK_MODULE), dw);
1620 register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw);
bd2b1e68
GH
1621}
1622
7a053d3b 1623static string
ec4373ff 1624probe_entry_function_name(unsigned probenum)
b55bc428 1625{
ec4373ff
GH
1626 return "dwarf_kprobe_" + lex_cast<string>(probenum) + "_enter";
1627}
1628
7a053d3b 1629static string
20c6c071 1630probe_entry_struct_kprobe_name(unsigned probenum)
ec4373ff 1631{
20c6c071 1632 return "dwarf_kprobe_" + lex_cast<string>(probenum);
ec4373ff
GH
1633}
1634
7a053d3b 1635void
20c6c071 1636dwarf_derived_probe::emit_registrations (translator_output* o, unsigned probenum)
ec4373ff 1637{
59ff2773 1638 if (! (module_name.empty() || module_name == "kernel"))
ec4373ff 1639 {
59ff2773
FCE
1640 // XXX: lock module_name in memory
1641 }
1642
1643 if (has_return)
1644 {
1645 o->newline() << probe_entry_struct_kprobe_name(probenum)
db520b00 1646 << ".kp.addr = (void *) 0x" << hex << addr << ";" << dec;
59ff2773
FCE
1647 o->newline() << "rc = register_kretprobe (&"
1648 << probe_entry_struct_kprobe_name(probenum)
1649 << ");";
ec4373ff 1650 }
20c6c071 1651 else
bd2b1e68 1652 {
59ff2773 1653 o->newline() << probe_entry_struct_kprobe_name(probenum)
db520b00 1654 << ".addr = (void *) 0x" << hex << addr << ";" << dec;
7a053d3b 1655 o->newline() << "rc = register_kprobe (&"
59ff2773
FCE
1656 << probe_entry_struct_kprobe_name(probenum)
1657 << ");";
bd2b1e68 1658 }
b55bc428
FCE
1659}
1660
7a053d3b 1661void
ec4373ff 1662dwarf_derived_probe::emit_deregistrations (translator_output* o, unsigned probenum)
b55bc428 1663{
fd6602a0
FCE
1664 if (has_return)
1665 o->newline() << "unregister_kretprobe (& "
1666 << probe_entry_struct_kprobe_name(probenum)
1667 << ");";
1668 else
1669 o->newline() << "unregister_kprobe (& "
1670 << probe_entry_struct_kprobe_name(probenum)
1671 << ");";
59ff2773
FCE
1672
1673 if (! (module_name.empty() || module_name == "kernel"))
1674 {
1675 // XXX: unlock module_name
1676 }
ec4373ff
GH
1677}
1678
7a053d3b 1679void
ec4373ff
GH
1680dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum)
1681{
ec4373ff 1682
7a053d3b 1683 // Construct a single entry function, and a struct kprobe pointing into
20c6c071 1684 // the entry function. The entry function will call the probe function.
20c6c071 1685 o->newline();
3d49c615 1686 o->newline() << "static int ";
9e6edd10
FCE
1687 o->newline() << probe_entry_function_name(probenum) << " (";
1688 if (has_return)
1689 o->line() << "struct kretprobe_instance *_ignored";
1690 else
1691 o->line() << "struct kprobe *_ignored";
1692 o->line() << ", struct pt_regs *regs) {";
3d49c615 1693 o->newline(1) << "struct context *c = & contexts [smp_processor_id()];";
bfb3d2d2
FCE
1694 o->newline();
1695
1696 // A precondition for running a probe handler is that we're in RUNNING
1697 // state (not ERROR), and that no one else is already using this context.
1698 o->newline() << "if (atomic_read (&session_state) != STAP_SESSION_RUNNING)";
3d49c615 1699 o->newline(1) << "return 0;";
bfb3d2d2
FCE
1700 o->newline(-1) << "if (c->busy) {";
1701 o->newline(1) << "printk (KERN_ERR \"probe reentrancy\");";
1702 o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
3d49c615 1703 o->newline() << "return 0;";
bfb3d2d2
FCE
1704 o->newline(-1) << "}";
1705 o->newline();
1706
ec4373ff 1707 o->newline() << "c->busy ++;";
bfb3d2d2 1708 o->newline() << "mb ();"; // for smp
5e309481 1709 o->newline() << "c->last_error = 0;";
ec4373ff 1710 o->newline() << "c->nesting = 0;";
3d49c615 1711 o->newline() << "c->regs = regs;";
5e309481
FCE
1712 o->newline() << "c->actioncount = 0;";
1713
ec4373ff
GH
1714 // NB: locals are initialized by probe function itself
1715 o->newline() << "probe_" << probenum << " (c);";
bfb3d2d2 1716
5e309481
FCE
1717 o->newline() << "if (c->last_error) {";
1718 o->newline(1) << "if (c->last_error[0]) _stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
1719 o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
bfb3d2d2
FCE
1720 o->newline(-1) << "}";
1721
ec4373ff 1722 o->newline() << "c->busy --;";
bfb3d2d2
FCE
1723 o->newline() << "mb ();";
1724
3d49c615 1725 o->newline() << "return 0;";
ec4373ff
GH
1726 o->newline(-1) << "}" << endl;
1727
20c6c071 1728 o->newline();
fd6602a0
FCE
1729 if (has_return)
1730 {
1731 o->newline() << "static struct kretprobe "
1732 << probe_entry_struct_kprobe_name(probenum)
1733 << "= {";
db520b00 1734 o->newline(1) << ".kp.addr = 0," ;
fd6602a0
FCE
1735 o->newline() << ".handler = &" << probe_entry_function_name(probenum);
1736 o->newline(-1) << "};";
1737 }
1738 else
1739 {
1740 o->newline() << "static struct kprobe "
1741 << probe_entry_struct_kprobe_name(probenum)
1742 << "= {";
db520b00 1743 o->newline(1) << ".addr = 0," ;
fd6602a0
FCE
1744 o->newline() << ".pre_handler = &" << probe_entry_function_name(probenum);
1745 o->newline(-1) << "};";
1746 }
20c6c071
GH
1747 o->newline();
1748}
ec4373ff 1749
20c6c071
GH
1750
1751void
5227f1ea 1752dwarf_builder::build(systemtap_session & sess,
7a053d3b 1753 probe * base,
20c6c071
GH
1754 probe_point * location,
1755 std::map<std::string, literal *> const & parameters,
1756 vector<probe *> & results_to_expand_further,
1757 vector<derived_probe *> & finished_results)
1758{
1759
5227f1ea
GH
1760 dwflpp dw(sess);
1761 dwarf_query q(sess, base, location, dw, parameters, finished_results);
20c6c071
GH
1762
1763 dw.setup(q.has_kernel || q.has_module);
1764
d9b516ca 1765 if (q.has_kernel
50e0d793 1766 && (q.has_function_num || q.has_statement_num))
20c6c071 1767 {
50e0d793
GH
1768 // If we have kernel.function(0xbeef), or
1769 // kernel.statement(0xbeef) the address is global (relative to
1770 // the kernel) and we can seek directly to the module and cudie
1771 // in question.
d9b516ca
RM
1772 Dwarf_Addr a = (q.has_function_num
1773 ? q.function_num_val
50e0d793
GH
1774 : q.statement_num_val);
1775 dw.focus_on_module_containing_global_address(a);
1776 dw.focus_on_cu_containing_global_address(a);
20c6c071
GH
1777 dw.iterate_over_functions(&query_function, &q);
1778 }
7a053d3b 1779 else
20c6c071
GH
1780 {
1781 // Otherwise we have module("foo"), kernel.statement("foo"), or
1782 // kernel.function("foo"); in these cases we need to scan all
1783 // the modules.
7a053d3b 1784 assert((q.has_kernel && q.has_function_str) ||
20c6c071
GH
1785 (q.has_kernel && q.has_statement_str) ||
1786 (q.has_module));
1787 dw.iterate_over_modules(&query_module, &q);
1788 }
b55bc428
FCE
1789}
1790
1791
98afd80e
FCE
1792
1793// ------------------------------------------------------------------------
1794// timer derived probes
1795// ------------------------------------------------------------------------
1796
1797
1798struct timer_derived_probe: public derived_probe
1799{
1800 int64_t interval, randomize;
1801
1802 timer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r);
1803
1804 virtual void emit_registrations (translator_output * o, unsigned i);
1805 virtual void emit_deregistrations (translator_output * o, unsigned i);
1806 virtual void emit_probe_entries (translator_output * o, unsigned i);
1807};
1808
1809
1810timer_derived_probe::timer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r):
1811 derived_probe (p, l), interval (i), randomize (r)
1812{
1813 if (interval <= 0 || interval > 1000000) // make i and r fit into plain ints
1814 throw semantic_error ("invalid interval for jiffies timer");
1815 // randomize = 0 means no randomization
1816 if (randomize < 0 || randomize > interval)
1817 throw semantic_error ("invalid randomize for jiffies timer");
1818
1819 if (locations.size() != 1)
1820 throw semantic_error ("expect single probe point");
1821 // so we don't have to loop over them in the other functions
1822}
1823
1824
1825void
1826timer_derived_probe::emit_registrations (translator_output* o, unsigned j)
1827{
1828 o->newline() << "init_timer (& timer_" << j << ");";
1829 o->newline() << "timer_" << j << ".expires = jiffies + " << interval << ";";
1830 o->newline() << "timer_" << j << ".function = & enter_" << j << ";";
1831 o->newline() << "add_timer (& timer_" << j << ");";
1832}
1833
1834
1835void
1836timer_derived_probe::emit_deregistrations (translator_output* o, unsigned j)
1837{
1838 o->newline() << "del_timer_sync (& timer_" << j << ");";
1839}
1840
1841
1842void
1843timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
1844{
1845 o->newline() << "static struct timer_list timer_" << j << ";";
1846
1847 o->newline() << "void enter_" << j << " (unsigned long val) {";
1848 o->newline(1) << "struct context* c = & contexts [smp_processor_id()];";
1849
1850 o->newline() << "(void) val;";
1851
1852 // A precondition for running a probe handler is that we're in
1853 // RUNNING state (not ERROR), and that no one else is already using
1854 // this context.
1855 o->newline() << "if (atomic_read (&session_state) != STAP_SESSION_RUNNING)";
1856 o->newline(1) << "return;";
1857
1858 o->newline(-1) << "if (c->busy) {";
1859 o->newline(1) << "printk (KERN_ERR \"probe reentrancy\");";
1860 o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
1861 o->newline() << "return;";
1862 o->newline(-1) << "}";
1863 o->newline();
1864
1865 o->newline() << "mod_timer (& timer_" << j << ", "
1866 << "jiffies + " << interval;
1867 if (randomize)
1868 o->line() << " + _stp_random_pm(" << randomize << ")";
1869 o->line() << ");";
1870
1871 o->newline() << "c->busy ++;";
1872 o->newline() << "mb ();"; // for smp
5e309481 1873 o->newline() << "c->last_error = 0;";
98afd80e 1874 o->newline() << "c->nesting = 0;";
98afd80e
FCE
1875 o->newline() << "if (! in_interrupt())";
1876 o->newline(1) << "c->regs = 0;";
1877 o->newline(-1) << "else";
1878 o->newline(1) << "c->regs = task_pt_regs (current);";
1879 o->indent(-1);
5e309481 1880 o->newline() << "c->actioncount = 0;";
98afd80e
FCE
1881
1882 // NB: locals are initialized by probe function itself
1883 o->newline() << "probe_" << j << " (c);";
1884
5e309481
FCE
1885 o->newline() << "if (c->last_error) {";
1886 o->newline(1) << "if (c->last_error[0]) _stp_error (\"%s near %s\", c->last_error, c->last_stmt);";
1887 o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);";
98afd80e
FCE
1888 o->newline(-1) << "}";
1889
1890 o->newline() << "c->busy --;";
1891 o->newline() << "mb ();";
1892 o->newline(-1) << "}" << endl;
1893}
1894
1895
1896struct timer_builder: public derived_probe_builder
1897{
1898 timer_builder() {}
1899 virtual void build(systemtap_session & sess,
1900 probe * base,
1901 probe_point * location,
1902 std::map<std::string, literal *> const & parameters,
1903 vector<probe *> &,
1904 vector<derived_probe *> & finished_results)
1905 {
1906 int64_t jn, rn;
1907 bool jn_p, rn_p;
1908
1909 jn_p = get_param (parameters, "jiffies", jn);
1910 rn_p = get_param (parameters, "randomize", rn);
1911
1912 finished_results.push_back(new timer_derived_probe(base, location,
1913 jn, rn_p ? rn : 0));
1914 }
1915};
1916
1917
1918
b55bc428 1919// ------------------------------------------------------------------------
bd2b1e68 1920// Standard tapset registry.
b55bc428
FCE
1921// ------------------------------------------------------------------------
1922
7a053d3b 1923void
f8220a7b 1924register_standard_tapsets(systemtap_session & s)
b55bc428 1925{
bd2b1e68 1926 // Rudimentary binders for begin and end targets
f8220a7b
GH
1927 s.pattern_root->bind("begin")->bind(new be_builder(true));
1928 s.pattern_root->bind("end")->bind(new be_builder(false));
98afd80e
FCE
1929 s.pattern_root->bind("timer")->bind_num("jiffies")->bind(new timer_builder());
1930 s.pattern_root->bind("timer")->bind_num("jiffies")->bind_num("randomize")->bind(new timer_builder());
b98a8d73 1931
14d0763f 1932 // kernel/module parts
f8220a7b 1933 dwarf_derived_probe::register_patterns(s.pattern_root);
b55bc428 1934}
This page took 0.270263 seconds and 5 git commands to generate.