Branch data Line data Source code
1 : : // Synthetic derived probe group that enables merging probes from
2 : : // difference derived probe groups for dyninst.
3 : : //
4 : : // Copyright (C) 2013 Red Hat Inc.
5 : : //
6 : : // This file is part of systemtap, and is free software. You can
7 : : // redistribute it and/or modify it under the terms of the GNU General
8 : : // Public License (GPL); either version 2, or (at your option) any
9 : : // later version.
10 : :
11 : :
12 : : #include "session.h"
13 : : #include "tapsets.h"
14 : : #include "tapset-dynprobe.h"
15 : : #include "translate.h"
16 : :
17 : : #include <cstring>
18 : : #include <string>
19 : :
20 : : using namespace std;
21 : : using namespace __gnu_cxx;
22 : :
23 : : // ------------------------------------------------------------------------
24 : : // dynprobe derived 'probes': These don't really exist. The purpose of
25 : : // the dynprobe_derived_probe_group is allow multiple
26 : : // *_derived_probe_group classes to output only one set of
27 : : // 'stapdu_target'/'stapdu_probe' arrays. This class also includes
28 : : // "dyninst/uprobes.c" only once and in the correct place.
29 : : // ------------------------------------------------------------------------
30 : :
31 [ # # ]: 0 : struct dynprobe_derived_probe: public derived_probe
32 : : {
33 : : // Dummy constructor for gcc 3.4 compatibility
34 : : dynprobe_derived_probe (): derived_probe (0, 0) { assert(0); }
35 : : };
36 : :
37 : : struct dynprobe_info
38 : : {
39 : : bool has_path;
40 : : const Dwarf_Addr offset;
41 : : const Dwarf_Addr semaphore_addr;
42 : : const string flags_string;
43 : : const string probe_init;
44 : :
45 : 0 : dynprobe_info(bool hp, const Dwarf_Addr o, const Dwarf_Addr sa,
46 : : const string fs, const string pi):
47 : : has_path(hp), offset(o), semaphore_addr(sa), flags_string(fs),
48 [ # # ]: 0 : probe_init(pi) { }
49 : : };
50 : :
51 [ # # ][ # # ]: 0 : struct dynprobe_derived_probe_group: public generic_dpg<dynprobe_derived_probe>
[ # # ][ # # ]
[ # # ]
52 : : {
53 : : private:
54 : : map<string, vector<dynprobe_info*> > info_by_path;
55 : : typedef map<string, vector<dynprobe_info*> >::iterator i_b_path_iterator;
56 : : map<Dwarf_Addr, vector<dynprobe_info*> > info_by_pid;
57 : : typedef map<Dwarf_Addr, vector<dynprobe_info*> >::iterator i_b_pid_iterator;
58 : :
59 : : void emit_info(systemtap_session& s, unsigned tgt_idx, dynprobe_info *info);
60 : :
61 : : public:
62 : : void emit_module_decls (systemtap_session& s);
63 : 0 : void emit_module_init (systemtap_session& ) { }
64 : 0 : void emit_module_post_init (systemtap_session& ) { }
65 : 0 : void emit_module_exit (systemtap_session& ) { }
66 : :
67 : : void add(const string& path, const Dwarf_Addr offset,
68 : : const Dwarf_Addr semaphore_addr, const string& flags_string,
69 : : const string& probe_init);
70 : : };
71 : :
72 : :
73 : : void
74 : 0 : dynprobe_derived_probe_group::add(const string& path, const Dwarf_Addr offset,
75 : : const Dwarf_Addr semaphore_addr,
76 : : const string& flags_string,
77 : : const string& probe_init)
78 : : {
79 [ # # ]: 0 : struct dynprobe_info *info = new dynprobe_info(!path.empty(), offset,
80 : : semaphore_addr,
81 [ # # ][ # # ]: 0 : flags_string, probe_init);
[ # # ][ # # ]
[ # # ][ # # ]
82 [ # # ][ # # ]: 0 : if (!path.empty())
83 [ # # ][ # # ]: 0 : info_by_path[path].push_back(info);
84 : : else
85 [ # # ][ # # ]: 0 : info_by_pid[offset].push_back(info);
86 : 0 : }
87 : :
88 : : void
89 : 0 : dynprobe_derived_probe_group::emit_info(systemtap_session& s,
90 : : unsigned tgt_idx, dynprobe_info *info)
91 : : {
92 : 0 : s.op->newline() << "{";
93 : 0 : s.op->line() << " .target=" << tgt_idx << ",";
94 : :
95 : : // We have to force path vs. pid probes into
96 : : // stapdu_target/stapdu_probe. So, here's how we'll do it.
97 : : //
98 : : // For path probes, stapdu_target will hold the path, and the
99 : : // stapdu_probe with the correct index will point to it.
100 : : //
101 : : // For pid probes, stapdu_target will have an empty path, and the
102 : : // 'offset' field of stapdu_probe will really be the pid.
103 [ # # ]: 0 : if (info->has_path)
104 [ # # ][ # # ]: 0 : s.op->line() << " .offset=" << lex_cast_hex(info->offset) << "ULL,";
105 : : else
106 : 0 : s.op->line() << " .offset=" << info->offset << "ULL/*pid*/,";
107 [ # # ]: 0 : if (info->semaphore_addr)
108 [ # # ]: 0 : s.op->line() << " .semaphore=" << lex_cast_hex(info->semaphore_addr)
109 [ # # ]: 0 : << "ULL,";
110 : 0 : s.op->line() << " .flags=" << info->flags_string << ",";
111 : 0 : s.op->line() << " .probe=" << info->probe_init << ",";
112 : 0 : s.op->line() << " },";
113 : 0 : }
114 : :
115 : : void
116 : 0 : dynprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
117 : : {
118 [ # # ]: 0 : if (! s.runtime_usermode_p())
119 : 0 : return;
120 : :
121 : 0 : s.op->newline() << "#include \"dyninst/uprobes.h\"";
122 : 0 : s.op->newline() << "static const struct stapdu_target stapdu_targets[] = {";
123 : 0 : s.op->indent(1);
124 [ # # ][ # # ]: 0 : for (i_b_path_iterator it = info_by_path.begin();
125 [ # # ]: 0 : it != info_by_path.end(); it++)
126 : : {
127 [ # # ][ # # ]: 0 : s.op->newline() << "{";
128 [ # # ][ # # ]: 0 : s.op->line() << " .path=" << lex_cast_qstring(it->first) << ",";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
129 [ # # ][ # # ]: 0 : s.op->line() << " },";
130 : : }
131 [ # # ]: 0 : if (! info_by_pid.empty())
132 : : {
133 : 0 : s.op->newline() << "{";
134 : 0 : s.op->line() << " .path=NULL,";
135 : 0 : s.op->line() << " },";
136 : : }
137 : 0 : s.op->newline(-1) << "};";
138 : 0 : s.op->assert_0_indent();
139 : :
140 : 0 : s.op->newline() << "static struct stapdu_probe stapdu_probes[] = {";
141 : 0 : s.op->indent(1);
142 : 0 : unsigned tgt_idx = 0;
143 [ # # ][ # # ]: 0 : for (i_b_path_iterator it = info_by_path.begin();
144 [ # # ]: 0 : it != info_by_path.end(); it++, tgt_idx++)
145 : : {
146 [ # # ][ # # ]: 0 : for (unsigned i = 0; i < it->second.size(); i++)
147 : : {
148 [ # # ]: 0 : dynprobe_info *info = it->second[i];
149 [ # # ]: 0 : emit_info(s, tgt_idx, info);
150 : : }
151 : : }
152 [ # # ]: 0 : if (! info_by_pid.empty())
153 : : {
154 [ # # ][ # # ]: 0 : for (i_b_pid_iterator it = info_by_pid.begin();
155 [ # # ]: 0 : it != info_by_pid.end(); it++)
156 : : {
157 [ # # ][ # # ]: 0 : for (unsigned i = 0; i < it->second.size(); i++)
158 : : {
159 [ # # ]: 0 : dynprobe_info *info = it->second[i];
160 [ # # ]: 0 : emit_info(s, tgt_idx, info);
161 : : }
162 : : }
163 : : }
164 : 0 : s.op->newline(-1) << "};";
165 : 0 : s.op->assert_0_indent();
166 : :
167 : 0 : s.op->newline() << "#include \"dyninst/uprobes.c\"";
168 : : }
169 : :
170 : :
171 : : // Declare that dynprobes are needed in this session
172 : 0 : void enable_dynprobes(systemtap_session& s)
173 : : {
174 [ # # ]: 0 : if (! s.dynprobe_derived_probes)
175 [ # # ]: 0 : s.dynprobe_derived_probes = new dynprobe_derived_probe_group();
176 : 0 : }
177 : :
178 : : void
179 : 0 : dynprobe_add_uprobe(systemtap_session& s, const string& path,
180 : : const Dwarf_Addr offset, const Dwarf_Addr semaphore_addr,
181 : : const string flags_string, const string probe_init)
182 : : {
183 : 0 : enable_dynprobes(s);
184 : : s.dynprobe_derived_probes->add(path, offset, semaphore_addr, flags_string,
185 : 0 : probe_init);
186 : 0 : }
187 : :
188 : : void
189 : 0 : dynprobe_add_utrace_path(systemtap_session& s, const std::string& path,
190 : : const std::string flags_string,
191 : : const std::string probe_init)
192 : : {
193 : 0 : enable_dynprobes(s);
194 : 0 : s.dynprobe_derived_probes->add(path, 0, 0, flags_string, probe_init);
195 : 0 : }
196 : :
197 : : void
198 : 0 : dynprobe_add_utrace_pid(systemtap_session& s, const Dwarf_Addr pid,
199 : : const std::string flags_string,
200 : : const std::string probe_init)
201 : : {
202 : 0 : enable_dynprobes(s);
203 : : // Notice we're passing the pid as the offset. Stapdyn is expecting
204 : : // this when the path is empty.
205 [ # # ][ # # ]: 0 : s.dynprobe_derived_probes->add("", pid, 0, flags_string, probe_init);
[ # # ]
206 [ + - ][ + - ]: 7242 : }
207 : :
208 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|