// session functions
-// Copyright (C) 2010-2016 Red Hat Inc.
+// Copyright (C) 2010-2019 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
base_hash(0),
pattern_root(new match_node),
dfa_counter (0),
- dfa_maxstate (0),
+ dfa_maxmap (0),
dfa_maxtag (0),
need_tagged_dfa (false),
be_derived_probes(0),
suppressed_errors(0),
warningerr_count(0),
target_namespaces_pid(0),
+ suppress_costly_diagnostics(0),
last_token (0)
{
struct utsname buf;
tmpdir_opt_set = false;
monitor = false;
monitor_interval = 1;
+ read_stdin = false;
save_module = false;
save_uprobes = false;
modname_given = false;
update_release_sysroot = false;
suppress_time_limits = false;
target_namespaces_pid = 0;
+ suppress_costly_diagnostics = 0;
color_mode = color_auto;
color_errors = isatty(STDERR_FILENO) // conditions for coloring when
&& strcmp(getenv("TERM") ?: "notdumb", "dumb"); // on auto
interactive_mode = false;
+ run_example = false;
+ no_global_var_display = false;
pass_1a_complete = false;
timeout = 0;
+ use_bpf_raw_tracepoint = false;
// PR12443: put compiled-in / -I paths in front, to be preferred during
// tapset duplicate-file elimination
pattern_root(new match_node),
user_files (other.user_files),
dfa_counter(0),
- dfa_maxstate (0),
+ dfa_maxmap(0),
dfa_maxtag (0),
need_tagged_dfa(other.need_tagged_dfa),
be_derived_probes(0),
suppressed_errors(0),
warningerr_count(0),
target_namespaces_pid(0),
+ suppress_costly_diagnostics(0),
last_token (0)
{
release = kernel_release = kern;
color_errors = other.color_errors;
color_mode = other.color_mode;
interactive_mode = other.interactive_mode;
+ run_example = other.run_example;
+ no_global_var_display = other.no_global_var_display;
pass_1a_complete = other.pass_1a_complete;
timeout = other.timeout;
script_file = other.script_file;
cmdline_script = other.cmdline_script;
additional_scripts = other.additional_scripts;
+ stdin_script.str() = other.stdin_script.str();
c_macros = other.c_macros;
args = other.args;
kbuildflags = other.kbuildflags;
server_args = other.server_args;
mok_fingerprints = other.mok_fingerprints;
+ // HTTP client/server
+ http_servers = other.http_servers;
+
unwindsym_modules = other.unwindsym_modules;
auto_privilege_level_msg = other.auto_privilege_level_msg;
auto_server_msgs = other.auto_server_msgs;
const string
systemtap_session::module_filename() const
{
- if (runtime_usermode_p())
- return module_name + ".so";
- return module_name + ".ko";
+ const char *suffix;
+ switch (runtime_mode)
+ {
+ case kernel_runtime:
+ suffix = ".ko";
+ break;
+ case dyninst_runtime:
+ suffix = ".so";
+ break;
+ case bpf_runtime:
+ suffix = ".bo";
+ break;
+ default:
+ abort();
+ }
+ return module_name + suffix;
}
#if HAVE_NSS
{
string elfutils_version1;
#ifdef _ELFUTILS_VERSION
- elfutils_version1 = "0." + lex_cast(_ELFUTILS_VERSION);
+ elfutils_version1 = "0." + lex_cast(_ELFUTILS_VERSION); /* BUILD */
#endif
- string elfutils_version2 = dwfl_version(NULL);
+ string elfutils_version2 = dwfl_version(NULL); /* RUN */
if (elfutils_version1 != elfutils_version2)
- elfutils_version2 += string("/") + elfutils_version1;
+ elfutils_version2 += string("/") + elfutils_version1; /* RUN/BUILD */
return string (VERSION) + "/" + elfutils_version2 + ", " + STAP_EXTENDED_VERSION;
}
void
systemtap_session::version ()
{
- // PRERELEASE
cout << _F("Systemtap translator/driver (version %s)\n"
- "Copyright (C) 2005-2016 Red Hat, Inc. and others\n"
+ "Copyright (C) 2005-2019 Red Hat, Inc. and others\n" // PRERELEASE
"This is free software; see the source for copying conditions.\n",
version_string().c_str());
- cout << _F("tested kernel versions: %s ... %s\n", "2.6.18", "4.10-rc0");
+ cout << _F("tested kernel versions: %s ... %s\n", "2.6.18", "5.4-rc6"); // PRERELEASE
cout << _("enabled features:")
#ifdef HAVE_AVAHI
#ifdef HAVE_DYNINST
<< " DYNINST"
#endif
+#ifdef HAVE_BPF_DECLS
+ << " BPF"
+#endif
#ifdef HAVE_JAVA
<< " JAVA"
#endif
" --dyninst\n"
" shorthand for --runtime=dyninst\n"
#endif /* HAVE_DYNINST */
+#ifdef HAVE_BPF_DECLS
+ " --bpf\n"
+ " shorthand for --runtime=bpf\n"
+#endif /* HAVE_BPF_DECLS */
" --prologue-searching[=WHEN]\n"
" prologue-searching for function probes\n"
" --privilege=PRIVILEGE_LEVEL\n"
" ssl,signer,all-users,revoke,no-prompt\n"
" --use-server-on-error[=yes/no]\n"
" retry compilation using a compile server upon compilation error\n"
+#endif
+#ifdef HAVE_HTTP_SUPPORT
+ " --use-http-server=SERVER-SPEC\n"
+ " specify systemtap http compile server\n"
#endif
" --remote=HOSTNAME\n"
" run pass 5 on the specified ssh host.\n"
" disable -DSTP_OVERLOAD, -DMAXACTION, and -DMAXTRYACTION limits\n"
" --save-uprobes\n"
" save uprobes.ko to current directory if it is built from source\n"
- " --target-namesapce=PID\n"
+ " --target-namespace=PID\n"
" sets the target namespaces pid to PID\n"
#if HAVE_MONITOR_LIBS
" --monitor=INTERVAL\n"
- " enables monitor interfaces\n"
+ " enables runtime interactive monitoring\n"
#endif
, compatible.c_str()) << endl
;
client_options_disallowed_for_unprivileged = "";
std::set<std::string> additional_unwindsym_modules;
struct rlimit our_rlimit;
+ bool sysroot_option_seen = false;
+ string kernel_release_value;
+
while (true)
{
char * num_endptr;
case 'r':
assert(optarg);
if (client_options) // NB: no paths!
- assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.-]+$");
+ // Note that '-' must come last in a regex bracket expression.
+ assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.+-]+$");
server_args.push_back (string ("-") + (char)grc + optarg);
- setup_kernel_release(optarg);
+ kernel_release_value = optarg;
break;
case 'a':
break;
case 'S':
- assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$");
assert(optarg);
+ assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$");
server_args.push_back (string ("-") + (char)grc + optarg);
size_option = string (optarg);
break;
// privilege level. The server also expects and depends on this behaviour when
// examining the client-side options passed to it.
privilege_t newPrivilege;
+ assert(optarg);
if (strcmp (optarg, "stapdev") == 0)
newPrivilege = pr_stapdev;
else if (strcmp (optarg, "stapsys") == 0)
server_trust_spec = "ssl";
break;
+
+#ifdef HAVE_HTTP_SUPPORT
+ case LONG_OPT_USE_HTTP_SERVER:
+ if (client_options) {
+ cerr << _F("ERROR: %s is invalid with %s", "--use-http-server", "--client-options") << endl;
+ return 1;
+ }
+ http_servers.push_back (optarg);
+ break;
+#endif
+
case LONG_OPT_HELP:
usage (0);
break;
+ case LONG_OPT_RUN_EXAMPLE:
+ run_example = true;
+ break;
+
// The caching options should not be available to server clients
case LONG_OPT_DISABLE_CACHE:
if (client_options) {
throw exit_exception(EXIT_SUCCESS);
case LONG_OPT_COMPATIBLE:
+ assert(optarg);
server_args.push_back ("--compatible=" + string(optarg));
if (strverscmp(optarg, VERSION) > 0) {
cerr << _F("ERROR: systemtap version %s cannot be compatible with future version %s", VERSION, optarg)
cerr << _F("ERROR: %s is invalid with %s", "--modinfo", "--client-options") << endl;
return 1;
}
+ assert(optarg);
assert_regexp_match("--modinfo parameter", optarg, "^[a-z_][a-z0-9_]*=.+$");
modinfos.push_back (string(optarg));
break;
case LONG_OPT_RLIMIT_AS:
+ assert(optarg);
if(getrlimit(RLIMIT_AS, & our_rlimit))
cerr << _F("Unable to obtain resource limits for rlimit-as : %s", strerror (errno)) << endl;
if (strlen(optarg) == 0) {
break;
case LONG_OPT_RLIMIT_CPU:
+ assert(optarg);
if(getrlimit(RLIMIT_CPU, & our_rlimit))
cerr << _F("Unable to obtain resource limits for rlimit-cpu : %s", strerror (errno)) << endl;
if (strlen(optarg) == 0) {
break;
case LONG_OPT_RLIMIT_NPROC:
+ assert(optarg);
if(getrlimit(RLIMIT_NPROC, & our_rlimit))
cerr << _F("Unable to obtain resource limits for rlimit-nproc : %s", strerror (errno)) << endl;
if (strlen(optarg) == 0) {
break;
case LONG_OPT_RLIMIT_STACK:
+ assert(optarg);
if(getrlimit(RLIMIT_STACK, & our_rlimit))
cerr << _F("Unable to obtain resource limits for rlimit-stack : %s", strerror (errno)) << endl;
if (strlen(optarg) == 0) {
break;
case LONG_OPT_RLIMIT_FSIZE:
+ assert(optarg);
if(getrlimit(RLIMIT_FSIZE, & our_rlimit))
cerr << _F("Unable to obtain resource limits for rlimit-fsize : %s", strerror (errno)) << endl;
if (strlen(optarg) == 0) {
if (client_options) {
cerr << _F("ERROR: %s invalid with %s", "--sysroot", "--client-options") << endl;
return 1;
- } else if (!sysroot.empty()) {
+ } else if (sysroot_option_seen) {
cerr << "ERROR: multiple --sysroot options not supported" << endl;
return 1;
} else {
- char *spath = canonicalize_file_name (optarg);
+ char *spath;
+ assert(optarg);
+ spath = canonicalize_file_name (optarg);
if (spath == NULL) {
cerr << _F("ERROR: %s is an invalid directory for --sysroot", optarg) << endl;
return 1;
sysroot = string(spath);
free (spath);
- if (sysroot[sysroot.size() - 1] != '/')
- sysroot.append("/");
- break;
+ // We do path creation like this:
+ // sysroot + "/lib/modules"
+ // So, we don't want the sysroot path to end with a '/',
+ // otherwise we'll end up with '/foo//lib/modules'.
+ if (!sysroot.empty() && *(sysroot.end() - 1) == '/') {
+ sysroot.erase(sysroot.end() - 1);
+ }
}
+ sysroot_option_seen = true;
+ break;
case LONG_OPT_SYSENV:
if (client_options) {
string sysenv_str = optarg;
string value;
size_t pos;
- if (sysroot.empty()) {
+ if (! sysroot_option_seen) {
cerr << "ERROR: --sysenv must follow --sysroot" << endl;
return 1;
}
return 1;
break;
+ case LONG_OPT_RUNTIME_BPF:
+ if (!parse_cmdline_runtime ("bpf"))
+ return 1;
+ break;
+
case LONG_OPT_BENCHMARK_SDT:
// XXX This option is secret, not supported, subject to change at our whim
benchmark_sdt_threads = thread::hardware_concurrency();
}
break;
+ case LONG_OPT_NO_GLOBAL_VAR_DISPLAY:
+ no_global_var_display = true;
+ break;
+
case '?':
// Invalid/unrecognized option given or argument required, but
// not given. In both cases getopt_long() will have printed the
}
}
+ if (! kernel_release_value.empty())
+ {
+ setup_kernel_release(kernel_release_value);
+ }
+ else if (! sysroot.empty())
+ {
+ kernel_build_tree = sysroot + "/lib/modules/" + kernel_release + "/build";
+ }
+
return 0;
}
{
if (opt_runtime == string("kernel"))
runtime_mode = kernel_runtime;
+ else if (opt_runtime == string("bpf"))
+ {
+#ifndef HAVE_BPF_DECLS
+ cerr << _("ERROR: --runtime=bpf unavailable; this build lacks BPF feature") << endl;
+ version();
+ return false;
+#else
+ runtime_mode = bpf_runtime;
+
+ // TODO: From early BPF development. Remove after making sure the
+ // cache doesn't break anything. Currently removal is blocked
+ // by PR22330 (module name encoded in trace_printk() calls,
+ // using up a lot of stack space for the cacheable script
+ // names).
+ use_cache = use_script_cache = false;
+#endif
+ }
else if (opt_runtime == string("dyninst"))
{
#ifndef HAVE_DYNINST
clog << _F("Checking \"%s\" failed with error: %s",
kernel_config_file.c_str(), strerror(errno)) << endl;
find_devel_rpms(*this, kernel_build_tree.c_str());
+ // Enable warnings, so that the rpm-installation help is sent
+ // out. The above message is going to go to stderr anyway
+ // in the case of stap -L without a necessary -devel available.
+ // Might as well make the text more helpful.
+ this->suppress_warnings = false;
missing_rpm_list_print(*this, "-devel");
return rc;
}
clog << _F("Kernel symbol table %s unavailable, (%s)",
system_map_path.c_str(), strerror(errno)) << endl;
- system_map_path = "/boot/System.map-" + kernel_release;
+ system_map_path = sysroot + "/boot/System.map-" + kernel_release;
system_map.clear();
system_map.open(system_map_path.c_str(), ifstream::in);
if (! system_map.is_open())
string address, type, name;
system_map >> address >> type >> name;
- if (verbose > 3)
+ if (verbose > 5)
clog << "'" << address << "' '" << type << "' '" << name
<< "'" << endl;
}
void
-systemtap_session::setup_kernel_release (const char* kstr)
+systemtap_session::setup_kernel_release (const string& kstr)
{
// Sometimes we may get dupes here... e.g. a server may have a full
// -r /path/to/kernel followed by a client's -r kernel.
else
{
update_release_sysroot = true;
- kernel_release = string (kstr);
+ kernel_release = kstr;
if (!kernel_release.empty())
kernel_build_tree = "/lib/modules/" + kernel_release + "/build";
}
}
+// The name of the primary stap file, if any -- usually user_files[0]->name:
+string
+systemtap_session::script_name()
+{
+ if (user_files.empty())
+ return "<unknown>";
+ return user_files[0]->name;
+}
+
+
+// The basename of the primary stap file, if any:
+string
+systemtap_session::script_basename()
+{
+ if (user_files.empty())
+ return "<unknown>";
+ return user_files[0]->name.substr(user_files[0]->name.rfind('/')+1); // basename
+}
+
// Print this given token, but abbreviate it if the last one had the
// same file name.
*
* On certain kernels (RHEL7), we also have to check
* /sys/kernel/security/securelevel.
+ *
+ * On certain kernels (Fedora28+), efi-lockdown may be in effect, but
+ * we lack a way of telling. RHBZ1638874. So check an environment
+ * variable "SYSTEMTAP_SIGN" instead for now.
*/
bool
systemtap_session::modules_must_be_signed()
ifstream securelevel("/sys/kernel/security/securelevel");
char status = 'N';
+ if (getenv("SYSTEMTAP_SIGN"))
+ return true;
+
statm >> status;
if (status == 'Y')
return true;
securelevel >> status;
if (status == '1')
return true;
+
return false;
}
bool
systemtap_session::is_primary_probe (derived_probe *dp)
{
+
+ // If the probe is synthetically generated, then it's not primary.
+
+ if (dp->synthetic)
+ return false;
+
// We check if this probe is from the primary user file by going back to its
// original probe and checking if that probe was found in the primary user
// file.