]> sourceware.org Git - systemtap.git/blame - hash.cxx
rhbz1732514: java runtime requires java-devel
[systemtap.git] / hash.cxx
CommitLineData
1b78aef5 1// Copyright (C) Andrew Tridgell 2002 (original file)
b58abde1 2// Copyright (C) 2006-2014 Red Hat Inc. (systemtap changes)
dff50e09 3//
1b78aef5
DS
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
dff50e09 8//
1b78aef5
DS
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
dff50e09 13//
1b78aef5 14// You should have received a copy of the GNU General Public License
e8daaf60 15// along with this program. If not, see <http://www.gnu.org/licenses/>.
1b78aef5
DS
16
17#include "config.h"
18#include "session.h"
19#include "hash.h"
20#include "util.h"
3b579393
FCE
21
22#include <cstdlib>
dd936721
JS
23#include <cstring>
24#include <fstream>
1b78aef5
DS
25#include <sstream>
26#include <iomanip>
27#include <cerrno>
28
29extern "C" {
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
dd936721 33#include "mdfour.h"
1b78aef5
DS
34}
35
36using namespace std;
37
dd936721 38
dec33462 39class stap_hash
dd936721
JS
40{
41private:
42 struct mdfour md4;
43 std::ostringstream parm_stream;
44
45public:
dec33462
FCE
46 stap_hash() { start(); }
47 stap_hash(const stap_hash &base) { md4 = base.md4; parm_stream << base.parm_stream.str(); }
dd936721
JS
48
49 void start();
50
333040ca
CM
51 void add(const std::string& description, const unsigned char *buffer, size_t size);
52 template<typename T> void add(const std::string& d, const T& x);
53 void add(const std::string& d, const char *s) { add((const std::string&)d, (const unsigned char *)s, strlen(s)); }
54 void add(const std:: string& d, const std::string& s) { add(d, (const unsigned char *)s.c_str(), s.length()); }
9beca2c0 55
333040ca 56 void add_path(const std::string& description, const std::string& path);
dd936721
JS
57
58 void result(std::string& r);
178b5ebc 59 std::string get_parms() { return parm_stream.str(); }
dd936721
JS
60};
61
62
1b78aef5 63void
dec33462 64stap_hash::start()
1b78aef5
DS
65{
66 mdfour_begin(&md4);
67}
68
69
70void
dec33462 71stap_hash::add(const std::string& description, const unsigned char *buffer, size_t size)
1b78aef5 72{
affcbf48 73 parm_stream << description << buffer << endl;
1b78aef5
DS
74 mdfour_update(&md4, buffer, size);
75}
76
77
9beca2c0 78template <typename T> void
dec33462 79stap_hash::add(const std::string& d, const T& x)
9beca2c0 80{
333040ca 81 parm_stream << d << x << endl;
9beca2c0
JS
82 mdfour_update(&md4, (const unsigned char *)&x, sizeof(x));
83}
84
85
2a8c27f6 86void
dec33462 87stap_hash::add_path(const std::string& description, const std::string& path)
2a8c27f6
JS
88{
89 struct stat st;
e7899657 90 memset (&st, 0, sizeof(st));
2a8c27f6 91
413c55ed 92 if (stat(path.c_str(), &st) != 0)
9a193b06
JS
93 st.st_size = st.st_mtime = -1;
94
333040ca
CM
95 add(description + "Path: ", path);
96 add(description + "Size: ", st.st_size);
97 add(description + "Timestamp: ", st.st_mtime);
2a8c27f6
JS
98}
99
100
1b78aef5 101void
dec33462 102stap_hash::result(string& r)
1b78aef5
DS
103{
104 ostringstream rstream;
105 unsigned char sum[16];
106
107 mdfour_update(&md4, NULL, 0);
108 mdfour_result(&md4, sum);
109
110 for (int i=0; i<16; i++)
111 {
112 rstream << hex << setfill('0') << setw(2) << (unsigned)sum[i];
113 }
114 rstream << "_" << setw(0) << dec << (unsigned)md4.totalN;
115 r = rstream.str();
116}
117
0d1ad607
WH
118void create_hash_log(const string &type_str, const string &parms, const string &result, const string &hash_log_path)
119{
120 ofstream log_file;
121 time_t rawtime;
122 time ( &rawtime );
123 string time_str(ctime (&rawtime));
124
125 log_file.open(hash_log_path.c_str());
126 log_file << "[" << time_str.substr(0,time_str.length()-1); // erase terminated '\n'
178b5ebc
JS
127 log_file << "] " << type_str << ":" << endl;
128 log_file << parms << endl;
659d42ce 129 log_file << _("result:") << result << endl;
0d1ad607
WH
130 log_file.close();
131}
1b78aef5 132
dec33462 133static const stap_hash&
9b3c54b2 134get_base_hash (systemtap_session& s)
1b78aef5 135{
9b3c54b2
JS
136 if (s.base_hash)
137 return *s.base_hash;
138
dec33462
FCE
139 s.base_hash = new stap_hash();
140 stap_hash& h = *s.base_hash;
9b3c54b2 141
b58abde1
FCE
142 // Hash systemtap version
143 h.add("Systemtap version: ", s.version_string());
144
5c54d49e 145 // Hash kernel release and arch.
333040ca
CM
146 h.add("Kernel Release: ", s.kernel_release);
147 h.add_path("Kernel Build Tree ", s.kernel_build_tree);
148 h.add("Architecture: ", s.architecture);
5c54d49e 149
2a8c27f6
JS
150 // Hash a few kernel version/build-id files too
151 // (useful for kernel developers reusing a single source tree)
333040ca
CM
152 h.add_path("Kernel Build Tree .config ", s.kernel_build_tree + "/.config");
153 h.add_path("Kernel Build Tree .version ", s.kernel_build_tree + "/.version");
154 h.add_path("Kernel Build Tree compile.h ", s.kernel_build_tree + "/include/linux/compile.h");
155 h.add_path("Kernel Build Tree version.h ", s.kernel_build_tree + "/include/linux/version.h");
156 h.add_path("Kernel Build Tree utsrelease.h ", s.kernel_build_tree + "/include/linux/utsrelease.h");
2a8c27f6 157
d89da127
SM
158 // Also hash guru mode flag, since behaviour can diverge.
159 h.add("Guru mode ", s.guru_mode);
160
5c54d49e 161 // Hash runtime path (that gets added in as "-R path").
333040ca 162 h.add_path("Runtime ", s.runtime_path);
e057551e
JS
163 h.add_path("Runtime transport ", s.runtime_path + "/transport");
164 h.add_path("Runtime unwind ", s.runtime_path + "/unwind");
165 h.add_path("Runtime sub ", s.runtime_path +
ac3af990 166 (s.runtime_usermode_p() ? "/dyninst" : "/linux"));
5c54d49e
JS
167
168 // Hash compiler path, size, and mtime. We're just going to assume
169 // we'll be using gcc. XXX: getting kbuild to spit out out would be
413c55ed 170 // better, especially since this is fooled by ccache.
0a567f6d 171 h.add_path("Compiler ", find_executable("gcc"));
5c54d49e
JS
172
173 // Hash the systemtap size and mtime. We could use VERSION/DATE,
174 // but when developing systemtap that doesn't work well (since you
175 // can compile systemtap multiple times in 1 day). Since we don't
176 // know exactly where we're getting run from, we'll use
28946fe7
MW
177 // /proc/self/exe (and we resolve it ourselves to help valgrind).
178 h.add_path("Systemtap ", get_self_path());
9b3c54b2
JS
179
180 return h;
5c54d49e
JS
181}
182
183
184static bool
185create_hashdir (systemtap_session& s, const string& result, string& hashdir)
186{
187 int nlevels = 1;
188
189 // Use a N level subdir for the cache path to reduce the impact on
190 // filesystems which are slow for large directories. Let N be adjustable.
191 const char *s_n = getenv("SYSTEMTAP_NLEVELS");
192 if (s_n)
1b78aef5
DS
193 {
194 nlevels = atoi(s_n);
195 if (nlevels < 1) nlevels = 1;
196 if (nlevels > 8) nlevels = 8;
197 }
198
5c54d49e
JS
199 hashdir = s.cache_path;
200
201 for (int i = 0; i < nlevels; i++)
202 {
203 hashdir += string("/") + result[i*2] + result[i*2 + 1];
204 if (create_dir(hashdir.c_str()) != 0)
205 {
2713ea24 206 s.print_warning("failed to create cache directory (\"" + hashdir + "\") " + strerror(errno) + ", disabling cache support");
63d530ab 207 s.use_cache = s.use_script_cache = false;
5c54d49e
JS
208 return false;
209 }
210 }
211 return true;
212}
213
214
9b3c54b2
JS
215void
216find_script_hash (systemtap_session& s, const string& script)
5c54d49e 217{
dec33462 218 stap_hash h(get_base_hash(s));
5c54d49e 219
1b78aef5
DS
220 // Hash getuid. This really shouldn't be necessary (since who you
221 // are doesn't change the generated output), but the hash gets used
222 // as the module name. If two different users try to run the same
223 // script at the same time, we need something to differentiate the
224 // module name.
333040ca 225 h.add("UID: ", getuid());
1b78aef5 226
1b78aef5 227 // Hash user-specified arguments (that change the generated module).
7baf48e9
FCE
228 h.add("Bulk Mode (-b): ", s.bulk_mode);
229 h.add("Timing (-t): ", s.timing);
7baf48e9
FCE
230 h.add("Skip Badvars (--skip-badvars): ", s.skip_badvars);
231 h.add("Privilege (--privilege): ", s.privilege);
232 h.add("Compatible (--compatible): ", s.compatible);
7baf48e9 233 h.add("Error suppression (--suppress-handler-errors): ", s.suppress_handler_errors);
152fa051 234 h.add("Suppress Time Limits (--suppress-time-limits): ", s.suppress_time_limits);
30833b32
MC
235 h.add("Prologue Searching (--prologue-searching[=WHEN]): ", int(s.prologue_searching_mode));
236
08fce398
SM
237 for (unsigned i = 0; i < s.c_macros.size(); i++)
238 h.add("Macros: ", s.c_macros[i]);
1b78aef5 239
4569f6bb 240 // Add any custom kbuild flags (-B)
1392896d 241 for (unsigned i = 0; i < s.kbuildflags.size(); i++)
333040ca 242 h.add("Kbuildflags: ", s.kbuildflags[i]);
1392896d 243
633e5ca7
FCE
244 // Add any custom --modinfo strings
245 for (unsigned i = 0; i < s.modinfos.size(); i++)
246 h.add("MODULE_INFO: ", s.modinfos[i]);
247
a7f52597
FCE
248 // -d MODULE
249 for (set<string>::iterator it = s.unwindsym_modules.begin();
250 it != s.unwindsym_modules.end();
251 it++)
333040ca 252 h.add_path("Unwindsym Modules ", *it);
ecd129af
CM
253
254 // Add the build id of each module
255 for(vector<string>::iterator it = s.build_ids.begin();
256 it != s.build_ids.end();
257 it++)
333040ca 258 h.add("Build ID: ", *it);
a7f52597 259
1b78aef5 260 // Add in pass 2 script output.
affcbf48 261 h.add("Script:\n", script);
1b78aef5 262
5c54d49e
JS
263 // Get the directory path to store our cached script
264 string result, hashdir;
1b78aef5 265 h.result(result);
5c54d49e
JS
266 if (!create_hashdir(s, result, hashdir))
267 return;
1b78aef5
DS
268
269 // Update module name to be 'stap_{hash start}'. '{hash start}'
270 // must not be too long. This shouldn't happen, since the maximum
271 // size of a hash is 32 fixed chars + 1 (for the '_') + a max of 11.
272 s.module_name = "stap_" + result;
273 if (s.module_name.size() >= (MODULE_NAME_LEN - 1))
274 s.module_name.resize(MODULE_NAME_LEN - 1);
275
276 // 'ccache' would use a hash path of something like:
277 // s.hash_path = hashdir + "/" + result.substr(nlevels);
278 // which would look like:
279 // ~/.stap_cache/A/B/CDEFGHIJKLMNOPQRSTUVWXYZABCDEF_XXX
280 //
281 // We're using the following so that the module can be used straight
282 // from the cache if desired. This ends up looking like this:
283 // ~/.stap_cache/A/B/stap_ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF_XXX.ko
4441e344 284 s.hash_path = hashdir + "/" + s.module_filename();
1b78aef5
DS
285
286 // Update C source name with new module_name.
a4b9c3b3 287 s.translated_source = string(s.tmpdir) + "/" + s.module_name + "_src.c";
0d1ad607
WH
288 create_hash_log(string("script_hash"), h.get_parms(), result,
289 hashdir + "/" + s.module_name + "_hash.log");
1b78aef5 290}
73267b89 291
5c54d49e 292
9b3c54b2
JS
293void
294find_stapconf_hash (systemtap_session& s)
5c54d49e 295{
dec33462 296 stap_hash h(get_base_hash(s));
5c54d49e 297
4569f6bb
JS
298 // Add any custom kbuild flags
299 for (unsigned i = 0; i < s.kbuildflags.size(); i++)
333040ca 300 h.add("Kbuildflags: ", s.kbuildflags[i]);
5c54d49e
JS
301
302 // Get the directory path to store our cached stapconf parameters
303 string result, hashdir;
304 h.result(result);
305 if (!create_hashdir(s, result, hashdir))
306 return;
307
de0db58a
JS
308 s.stapconf_name = "stapconf_" + result + ".h";
309 s.stapconf_path = hashdir + "/" + s.stapconf_name;
0d1ad607
WH
310 create_hash_log(string("stapconf_hash"), h.get_parms(), result,
311 hashdir + "/stapconf_" + result + "_hash.log");
5c54d49e
JS
312}
313
314
a2639cb7 315string
c9ccb642 316find_tracequery_hash (systemtap_session& s, const string& header)
b278033a 317{
dec33462 318 stap_hash h(get_base_hash(s));
b278033a 319
c9ccb642
FCE
320 // Add the tracepoint header to the computed hash
321 h.add_path("Header ", header);
b278033a 322
4569f6bb
JS
323 // Add any custom kbuild flags
324 for (unsigned i = 0; i < s.kbuildflags.size(); i++)
333040ca 325 h.add("Kbuildflags: ", s.kbuildflags[i]);
4569f6bb 326
b278033a
JS
327 // Get the directory path to store our cached module
328 string result, hashdir;
329 h.result(result);
330 if (!create_hashdir(s, result, hashdir))
c9ccb642 331 return ""; // XXX: as opposed to throwing an exception?
b278033a 332
0d1ad607
WH
333 create_hash_log(string("tracequery_hash"), h.get_parms(), result,
334 hashdir + "/tracequery_" + result + "_hash.log");
2a0e62a8 335 return hashdir + "/tracequery_" + result + ".o";
b278033a
JS
336}
337
1f329b5e 338
a2639cb7
JS
339string
340find_typequery_hash (systemtap_session& s, const string& name)
1f329b5e 341{
dec33462 342 stap_hash h(get_base_hash(s));
1f329b5e
JS
343
344 // Add the typequery name to distinguish the hash
333040ca 345 h.add("Typequery Name: ", name);
1f329b5e 346
4569f6bb
JS
347 if (name[0] == 'k')
348 // Add any custom kbuild flags
349 for (unsigned i = 0; i < s.kbuildflags.size(); i++)
333040ca 350 h.add("Kbuildflags: ", s.kbuildflags[i]);
4569f6bb 351
1f329b5e
JS
352 // Get the directory path to store our cached module
353 string result, hashdir;
354 h.result(result);
355 if (!create_hashdir(s, result, hashdir))
a2639cb7 356 return "";
1f329b5e 357
0d1ad607
WH
358 create_hash_log(string("typequery_hash"), h.get_parms(), result,
359 hashdir + "/typequery_" + result + "_hash.log");
a2639cb7 360 return hashdir + "/typequery_" + result
1f329b5e
JS
361 + (name[0] == 'k' ? ".ko" : ".so");
362}
363
7d26ee02
JS
364
365string
366find_uprobes_hash (systemtap_session& s)
367{
dec33462 368 stap_hash h(get_base_hash(s));
7d26ee02
JS
369
370 // Hash runtime uprobes paths
e057551e
JS
371 h.add_path("Uprobes Runtime Path /uprobes ", s.runtime_path + "/linux/uprobes");
372 h.add_path("Uprobes Runtime Path /uprobes2 ", s.runtime_path + "/linux/uprobes2");
7d26ee02
JS
373
374 // Add any custom kbuild flags
375 for (unsigned i = 0; i < s.kbuildflags.size(); i++)
333040ca 376 h.add("Kbuildflags: ", s.kbuildflags[i]);
7d26ee02 377
f63e9688
JS
378 // Add any custom --modinfo strings
379 for (unsigned i = 0; i < s.modinfos.size(); i++)
380 h.add("MODULE_INFO: ", s.modinfos[i]);
381
7d26ee02
JS
382 // Get the directory path to store our cached module
383 string result, hashdir;
384 h.result(result);
385 if (!create_hashdir(s, result, hashdir))
386 return "";
387
388 create_hash_log(string("uprobes_hash"), h.get_parms(), result,
389 hashdir + "/uprobes_" + result + "_hash.log");
390 return hashdir + "/uprobes_" + result;
391}
392
73267b89 393/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.197173 seconds and 5 git commands to generate.