return true;
}
+// Attach to a specific existing process.
+bool
+mutator::attach_process(pid_t pid)
+{
+ if (target_mutatee)
+ {
+ staperror() << "Already attached to a target process!" << endl;
+ return false;
+ }
+
+ BPatch_process* app = patch.processAttach(NULL, pid);
+ if (!app)
+ {
+ staperror() << "Couldn't attach to the target process" << endl;
+ return false;
+ }
+
+ boost::shared_ptr<mutatee> m(new mutatee(app));
+ mutatees.push_back(m);
+ target_mutatee = m;
+ p_target_created = false;
+
+ if (!m->load_stap_dso(module_name))
+ return false;
+
+ if (!targets.empty())
+ m->instrument_dynprobes(targets);
+
+ return true;
+}
+
// Initialize the module session
bool
mutator::run_module_init()
usage (int rc)
{
clog << "Usage: " << program_invocation_short_name
- << " MODULE -c CMD" << endl;
+ << " MODULE [-c CMD | -x PID]" << endl;
exit (rc);
}
int
main(int argc, char * const argv[])
{
+ pid_t pid = 0;
const char* command = NULL;
const char* module = NULL;
// First, option parsing.
int opt;
- while ((opt = getopt (argc, argv, "c:vwV")) != -1)
+ while ((opt = getopt (argc, argv, "c:x:vwV")) != -1)
{
switch (opt)
{
command = optarg;
break;
+ case 'x':
+ pid = atoi(optarg);
+ break;
+
case 'v':
++stapdyn_log_level;
break;
if (optind == argc - 1)
module = argv[optind];
- if (!module)
+ if (!module || (command && pid))
usage (1);
// Make sure that environment variables and selinux are set ok.
if (command && !session->create_process(command))
return 1;
+ if (pid && !session->attach_process(pid))
+ return 1;
+
return session->run() ? EXIT_SUCCESS : EXIT_FAILURE;
}