diff options
author | Josh Stone <jistone@redhat.com> | 2010-03-10 19:17:40 -0800 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2010-03-10 19:24:14 -0800 |
commit | da9e11bd5cd3cbedbf794a0e8a83956bd178ba60 (patch) | |
tree | d727a14411eeda77c767fa30fe09ab4895b43798 | |
parent | e54c1d239a7dba1954dfc8359e62c94329b44a6a (diff) | |
download | systemtap-steved-da9e11bd5cd3cbedbf794a0e8a83956bd178ba60.tar.gz systemtap-steved-da9e11bd5cd3cbedbf794a0e8a83956bd178ba60.tar.xz systemtap-steved-da9e11bd5cd3cbedbf794a0e8a83956bd178ba60.zip |
PR11370: Add multi-header @casts
Sometimes you need multiple headers to fully describe a type, so we now
permit them to be listed together, e.g. "kernel<foo.h><bar.h>".
* buildrun.cxx (make_typequery): Split the input string into a vector.
(make_typequery_kmod, make_typequery_umod): Use the vector of headers.
* testsuite/semok/cast.stp: Add a multi-header case.
* stap.1.in, NEWS: Document it.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | buildrun.cxx | 48 | ||||
-rw-r--r-- | stap.1.in | 3 | ||||
-rwxr-xr-x | testsuite/semok/cast.stp | 3 |
4 files changed, 39 insertions, 19 deletions
@@ -1,5 +1,9 @@ * What's new +- Type-casting can now use multiple headers to resolve codependencies. + @cast(task, "task_struct", + "kernel<linux/sched.h><linux/fs_struct.h>")->fs->umask + - Tapset-related man pages have been renamed. 'man -k 3stap' should show the installed list, which due to prefixing should no longer collide over ordinary system functions. diff --git a/buildrun.cxx b/buildrun.cxx index d6fc52ee..084022bf 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -541,7 +541,7 @@ make_tracequery(systemtap_session& s, string& name, // Build a tiny kernel module to query type information static int -make_typequery_kmod(systemtap_session& s, const string& header, string& name) +make_typequery_kmod(systemtap_session& s, const vector<string>& headers, string& name) { static unsigned tick = 0; string basename("typequery_kmod_" + lex_cast(++tick)); @@ -569,7 +569,10 @@ make_typequery_kmod(systemtap_session& s, const string& header, string& name) // full kernel build tree, it's possible to get at types that aren't in the // normal include path, e.g.: // @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->... - omf << "CFLAGS_" << basename << ".o := -include " << header << endl; + omf << "CFLAGS_" << basename << ".o :="; + for (size_t i = 0; i < headers.size(); ++i) + omf << " -include " << lex_cast_qstring(headers[i]); + omf << endl; omf << "obj-m := " + basename + ".o" << endl; omf.close(); @@ -598,7 +601,7 @@ make_typequery_kmod(systemtap_session& s, const string& header, string& name) // Build a tiny user module to query type information static int -make_typequery_umod(systemtap_session& s, const string& header, string& name) +make_typequery_umod(systemtap_session& s, const vector<string>& headers, string& name) { static unsigned tick = 0; @@ -610,11 +613,13 @@ make_typequery_umod(systemtap_session& s, const string& header, string& name) // cwd in this case will be the cwd of stap itself though, which may be // trickier to deal with. It might be better to "cd `dirname $script`" // first... - string cmd = "gcc -shared -g -fno-eliminate-unused-debug-types -o " - + name + " -xc /dev/null -include " + header; + ostringstream cmd; + cmd << "gcc -shared -g -fno-eliminate-unused-debug-types -xc /dev/null -o " << name; + for (size_t i = 0; i < headers.size(); ++i) + cmd << " -include " << lex_cast_qstring(headers[i]); if (s.verbose < 4) - cmd += " >/dev/null 2>&1"; - return stap_system (s.verbose, cmd); + cmd << " >/dev/null 2>&1"; + return stap_system (s.verbose, cmd.str()); } @@ -623,23 +628,28 @@ make_typequery(systemtap_session& s, string& module) { int rc; string new_module; + vector<string> headers; + bool kernel = (module.compare(0, 6, "kernel") == 0); - if (module[module.size() - 1] != '>') - return -1; - - if (module[0] == '<') - { - string header = module.substr(1, module.size() - 2); - rc = make_typequery_umod(s, header, new_module); - } - else if (module.compare(0, 7, "kernel<") == 0) + for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1) { - string header = module.substr(7, module.size() - 8); - rc = make_typequery_kmod(s, header, new_module); + if (module[i] != '<') + return -1; + end = module.find('>', ++i); + if (end == string::npos) + return -1; + string header = module.substr(i, end - i); + assert_regexp_match("@cast header", header, "^[a-z0-9/_.+-]+$"); + headers.push_back(header); } - else + if (headers.empty()) return -1; + if (kernel) + rc = make_typequery_kmod(s, headers, new_module); + else + rc = make_typequery_umod(s, headers, new_module); + if (!rc) module = new_module; @@ -844,9 +844,12 @@ The translator can create its own module with type information from a header surrounded by angle brackets, in case normal debuginfo is not available. For kernel headers, prefix it with "kernel" to use the appropriate build system. All other headers are build with default GCC parameters into a user module. +Multiple headers may be specified in sequence to resolve a codependency. .SAMPLE @cast(tv, "timeval", "<sys/time.h>")->tv_sec @cast(task, "task_struct", "kernel<linux/sched.h>")->tgid +@cast(task, "task_struct", + "kernel<linux/sched.h><linux/fs_struct.h>")->fs->umask .ESAMPLE .PP When in guru mode, the translator will also allow scripts to assign new diff --git a/testsuite/semok/cast.stp b/testsuite/semok/cast.stp index 14401886..d3606a50 100755 --- a/testsuite/semok/cast.stp +++ b/testsuite/semok/cast.stp @@ -15,6 +15,9 @@ probe begin { println(@cast(0, "task_struct", "kernel<linux/sched.h>")->tgid) println(@cast(0, "timeval", "<sys/time.h>")->tv_sec) + // sometimes multiple headers are needed in tandem + println(@cast(0, "task_struct", "kernel<linux/sched.h><linux/fs_struct.h>")->fs->umask) + // make sure that bogus @casts can get optimized away @cast(0, "task_struct")->no_such_field @cast(0, "task_struct")->parent->no_such_field |