operf.cpp

Go to the documentation of this file.
00001 
00018 #include "config.h"
00019 
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <getopt.h>
00023 #include <dirent.h>
00024 #include <exception>
00025 #include <pwd.h>
00026 #include <errno.h>
00027 #include <sys/time.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <sys/stat.h>
00031 #include <sys/types.h>
00032 #include <fcntl.h>
00033 #include <sys/wait.h>
00034 #include <ftw.h>
00035 #include <getopt.h>
00036 #include <iostream>
00037 #include "operf_utils.h"
00038 #include "op_libiberty.h"
00039 #include "string_manip.h"
00040 #include "cverb.h"
00041 #include "operf_counter.h"
00042 #include "op_cpu_type.h"
00043 #include "op_cpufreq.h"
00044 #include "op_events.h"
00045 #include "op_string.h"
00046 #include "operf_kernel.h"
00047 #include "child_reader.h"
00048 #include "op_get_time.h"
00049 
00050 using namespace std;
00051 
00052 typedef enum END_CODE {
00053     ALL_OK = 0,
00054     APP_ABNORMAL_END =  1,
00055     PERF_RECORD_ERROR = 2,
00056     PERF_READ_ERROR   = 4,
00057     PERF_BOTH_ERROR   = 8
00058 } end_code_t;
00059 
00060 // Globals
00061 char * app_name = NULL;
00062 pid_t app_PID = -1;
00063 uint64_t kernel_start, kernel_end;
00064 operf_read operfRead;
00065 op_cpu cpu_type;
00066 double cpu_speed;
00067 char op_samples_current_dir[PATH_MAX];
00068 uint op_nr_counters;
00069 verbose vmisc("misc");
00070 uid_t my_uid;
00071 bool no_vmlinux;
00072 int kptr_restrict;
00073 char * start_time_human_readable;
00074 
00075 #define DEFAULT_OPERF_OUTFILE "operf.data"
00076 #define CALLGRAPH_MIN_COUNT_SCALE 15
00077 
00078 static char full_pathname[PATH_MAX];
00079 static char * app_name_SAVE = NULL;
00080 static char * app_args = NULL;
00081 static  pid_t jitconv_pid = -1;
00082 static bool app_started;
00083 static pid_t operf_record_pid;
00084 static pid_t operf_read_pid;
00085 static string samples_dir;
00086 static bool startApp;
00087 static string outputfile;
00088 static char start_time_str[32];
00089 static vector<operf_event_t> events;
00090 static bool jit_conversion_running;
00091 static void convert_sample_data(void);
00092 static int sample_data_pipe[2];
00093 static bool ctl_c = false;
00094 
00095 
00096 namespace operf_options {
00097 bool system_wide;
00098 bool append;
00099 int pid;
00100 bool callgraph;
00101 int mmap_pages_mult;
00102 string session_dir;
00103 string vmlinux;
00104 bool separate_cpu;
00105 bool separate_thread;
00106 bool post_conversion;
00107 vector<string> evts;
00108 }
00109 
00110 static const char * valid_verbose_vals[] = { "debug", "record", "convert", "misc", "sfile", "arcs", "all"};
00111 #define NUM_VERBOSE_OPTIONS (sizeof(valid_verbose_vals)/sizeof(char *))
00112 
00113 struct option long_options [] =
00114 {
00115  {"verbose", required_argument, NULL, 'V'},
00116  {"session-dir", required_argument, NULL, 'd'},
00117  {"vmlinux", required_argument, NULL, 'k'},
00118  {"callgraph", no_argument, NULL, 'g'},
00119  {"system-wide", no_argument, NULL, 's'},
00120  {"append", no_argument, NULL, 'a'},
00121  {"pid", required_argument, NULL, 'p'},
00122  {"events", required_argument, NULL, 'e'},
00123  {"separate-cpu", no_argument, NULL, 'c'},
00124  {"separate-thread", no_argument, NULL, 't'},
00125  {"lazy-conversion", no_argument, NULL, 'l'},
00126  {"help", no_argument, NULL, 'h'},
00127  {"version", no_argument, NULL, 'v'},
00128  {"usage", no_argument, NULL, 'u'},
00129  {NULL, 9, NULL, 0}
00130 };
00131 
00132 const char * short_options = "V:d:k:gsap:e:ctlhuv";
00133 
00134 vector<string> verbose_string;
00135 
00136 static void __print_usage_and_exit(const char * extra_msg)
00137 {
00138     if (extra_msg)
00139         cerr << extra_msg << endl;
00140     cerr << "usage: operf [ options ] [ --system-wide | --pid <pid> | [ command [ args ] ] ]" << endl;
00141     cerr << "See operf man page for details." << endl;
00142     exit(EXIT_FAILURE);
00143 }
00144 
00145 
00146 static void op_sig_stop(int val __attribute__((unused)))
00147 {
00148     // Received a signal to quit, so we need to stop the
00149     // app being profiled.
00150     size_t dummy __attribute__ ((__unused__));
00151     ctl_c = true;
00152     if (cverb << vdebug)
00153         dummy = write(1, "in op_sig_stop\n", 15);
00154     if (startApp)
00155         kill(app_PID, SIGKILL);
00156 }
00157 
00158 static void _handle_sigint(int val __attribute__((unused)))
00159 {
00160     size_t dummy __attribute__ ((__unused__));
00161     ctl_c = true;
00162     if (cverb << vdebug)
00163         dummy = write(1, "in _handle_sigint\n", 19);
00164     return;
00165 }
00166 
00167 
00168 void _set_signals_for_record(void)
00169 {
00170     struct sigaction act;
00171     sigset_t ss;
00172 
00173     sigfillset(&ss);
00174     sigprocmask(SIG_UNBLOCK, &ss, NULL);
00175 
00176     act.sa_handler = _handle_sigint;
00177     act.sa_flags = 0;
00178     sigemptyset(&act.sa_mask);
00179     sigaddset(&act.sa_mask, SIGINT);
00180     if (sigaction(SIGINT, &act, NULL)) {
00181         perror("operf: install of SIGINT handler failed: ");
00182         exit(EXIT_FAILURE);
00183     }
00184 }
00185 
00186 void set_signals(void)
00187 {
00188     struct sigaction act;
00189     sigset_t ss;
00190 
00191     sigfillset(&ss);
00192     sigprocmask(SIG_UNBLOCK, &ss, NULL);
00193 
00194     act.sa_handler = op_sig_stop;
00195     act.sa_flags = 0;
00196     sigemptyset(&act.sa_mask);
00197     sigaddset(&act.sa_mask, SIGINT);
00198 
00199     if (sigaction(SIGINT, &act, NULL)) {
00200         perror("operf: install of SIGINT handler failed: ");
00201         exit(EXIT_FAILURE);
00202     }
00203 }
00204 
00205 static int app_ready_pipe[2], start_app_pipe[2], operf_record_ready_pipe[2];
00206 
00207 void run_app(void)
00208 {
00209     char * app_fname = rindex(app_name, '/') + 1;
00210     if (!app_fname) {
00211         string msg = "Error trying to parse app name ";
00212         msg += app_name;
00213         __print_usage_and_exit(msg.c_str());
00214     }
00215 
00216     vector<string> exec_args_str;
00217     if (app_args) {
00218         size_t end_pos;
00219         string app_args_str = app_args;
00220         // Since the strings returned from substr would otherwise be ephemeral, we
00221         // need to store them into the exec_args_str vector so we can reference
00222         // them later when we call execvp.
00223         do {
00224             end_pos = app_args_str.find_first_of(' ', 0);
00225             if (end_pos != string::npos) {
00226                 exec_args_str.push_back(app_args_str.substr(0, end_pos));
00227                 app_args_str = app_args_str.substr(end_pos + 1);
00228             } else {
00229                 exec_args_str.push_back(app_args_str);
00230             }
00231         } while (end_pos != string::npos);
00232     }
00233 
00234     vector<const char *> exec_args;
00235     exec_args.push_back(app_fname);
00236     vector<string>::iterator it;
00237     cverb << vdebug << "Exec args are: " << app_fname << " ";
00238     // Now transfer the args from the intermediate exec_args_str container to the
00239     // exec_args container that can be passed to execvp.
00240     for (it = exec_args_str.begin(); it != exec_args_str.end(); it++) {
00241         exec_args.push_back((*it).c_str());
00242         cverb << vdebug << (*it).c_str() << " ";
00243     }
00244     exec_args.push_back((char *) NULL);
00245     cverb << vdebug << endl;
00246     // Fake an exec to warm-up the resolver
00247     execvp("", ((char * const *)&exec_args[0]));
00248     // signal to the parent that we're ready to exec
00249     int startup = 1;
00250     if (write(app_ready_pipe[1], &startup, sizeof(startup)) < 0) {
00251         perror("Internal error on app_ready_pipe");
00252         _exit(EXIT_FAILURE);
00253     }
00254 
00255     // wait for parent to tell us to start
00256     int startme = 0;
00257     if (read(start_app_pipe[0], &startme, sizeof(startme)) == -1) {
00258         perror("Internal error in run_app on start_app_pipe");
00259         _exit(EXIT_FAILURE);
00260     }
00261     if (startme != 1)
00262         _exit(EXIT_SUCCESS);
00263 
00264     cverb << vdebug << "parent says start app " << app_name << endl;
00265     app_started = true;
00266     execvp(app_name, ((char * const *)&exec_args[0]));
00267     cerr <<  "Failed to exec " << exec_args[0] << ": " << strerror(errno) << endl;
00268     /* We don't want any cleanup in the child */
00269     _exit(EXIT_FAILURE);
00270 
00271 }
00272 
00273 int start_profiling(void)
00274 {
00275     // The only process that should return from this function is the process
00276     // which invoked it.  Any forked process must do _exit() rather than return().
00277     struct timeval tv;
00278     unsigned long long start_time = 0ULL;
00279     gettimeofday(&tv, NULL);
00280     start_time = 0ULL;
00281     start_time = tv.tv_sec;
00282     sprintf(start_time_str, "%llu", start_time);
00283     start_time_human_readable = op_get_time();
00284     startApp = ((app_PID != operf_options::pid) && (operf_options::system_wide == false));
00285 
00286     if (startApp) {
00287         if (pipe(app_ready_pipe) < 0 || pipe(start_app_pipe) < 0) {
00288             perror("Internal error: operf-record could not create pipe");
00289             _exit(EXIT_FAILURE);
00290         }
00291         app_PID = fork();
00292         if (app_PID < 0) {
00293             perror("Internal error: fork failed");
00294             _exit(EXIT_FAILURE);
00295         } else if (app_PID == 0) { // child process for exec'ing app
00296             if (!operf_options::post_conversion) {
00297                 close(sample_data_pipe[0]);
00298                 close(sample_data_pipe[1]);
00299             }
00300             run_app();
00301         }
00302     }
00303 
00304     // parent
00305     if (pipe(operf_record_ready_pipe) < 0) {
00306         perror("Internal error: could not create pipe");
00307         return -1;
00308     }
00309     operf_record_pid = fork();
00310     if (operf_record_pid < 0) {
00311         return -1;
00312     } else if (operf_record_pid == 0) { // operf-record process
00313         int ready = 0;
00314         int exit_code = EXIT_SUCCESS;
00315         _set_signals_for_record();
00316         close(operf_record_ready_pipe[0]);
00317         if (!operf_options::post_conversion)
00318             close(sample_data_pipe[0]);
00319         /*
00320          * Since an informative message will be displayed to the user if
00321          * an error occurs, we don't want to blow chunks here; instead, we'll
00322          * exit gracefully.  Clear out the operf.data file as an indication
00323          * to the parent process that the profile data isn't valid.
00324          */
00325         try {
00326             OP_perf_utils::vmlinux_info_t vi;
00327             int outfd;
00328             int flags = O_WRONLY | O_CREAT | O_TRUNC;
00329             vi.image_name = operf_options::vmlinux;
00330             vi.start = kernel_start;
00331             vi.end = kernel_end;
00332             if (operf_options::post_conversion) {
00333                 outfd = open(outputfile.c_str(), flags, S_IRUSR|S_IWUSR);
00334                 if (outfd < 0) {
00335                     string errmsg = "Internal error: Could not create temporary output file. errno is ";
00336                     errmsg += strerror(errno);
00337                     throw runtime_error(errmsg);
00338                 }
00339             } else {
00340                 outfd = sample_data_pipe[1];
00341             }
00342             operf_record operfRecord(outfd, operf_options::system_wide, app_PID,
00343                                      (operf_options::pid == app_PID), events, vi,
00344                                      operf_options::callgraph,
00345                                      operf_options::separate_cpu, operf_options::post_conversion);
00346             if (operfRecord.get_valid() == false) {
00347                 /* If valid is false, it means that one of the "known" errors has
00348                  * occurred:
00349                  *   - profiled process has already ended
00350                  *   - passed PID was invalid
00351                  *   - device or resource busy
00352                  *   - failure to mmap kernel profile data
00353                  */
00354                 cerr << "operf record init failed" << endl;
00355                 cerr << "usage: operf [ options ] [ --system-wide | --pid <pid> | [ command [ args ] ] ]" << endl;
00356                 // Exit with SUCCESS to avoid the unnecessary "operf-record process ended
00357                 // abnormally" message
00358                 goto fail_out;
00359             }
00360 
00361             ready = 1;
00362             if (write(operf_record_ready_pipe[1], &ready, sizeof(ready)) < 0) {
00363                 perror("Internal error on operf_record_ready_pipe");
00364                 exit_code = EXIT_FAILURE;
00365                 goto fail_out;
00366             }
00367 
00368             // start recording
00369             operfRecord.recordPerfData();
00370             cverb << vmisc << "Total bytes recorded from perf events: " << dec
00371                     << operfRecord.get_total_bytes_recorded() << endl;
00372         } catch (runtime_error re) {
00373             /* If the user does ctl-c, the operf-record process may get interrupted
00374              * in a system call, causing problems with writes to the sample data pipe.
00375              * So we'll ignore such errors unless the user requests debug info.
00376              */
00377             if (!ctl_c || (cverb << vmisc)) {
00378                 cerr << "Caught runtime_error: " << re.what() << endl;
00379                 exit_code = EXIT_FAILURE;
00380             }
00381             goto fail_out;
00382         }
00383         // done
00384         _exit(exit_code);
00385 
00386 fail_out:
00387         if (!ready){
00388             /* ready==0 means we've not yet told parent we're ready,
00389              * but the parent is reading our pipe.  So we tell the
00390              * parent we're not ready so it can continue.
00391              */
00392             if (write(operf_record_ready_pipe[1], &ready, sizeof(ready)) < 0) {
00393                 perror("Internal error on operf_record_ready_pipe");
00394             }
00395         }
00396         _exit(exit_code);
00397     } else {  // parent
00398         int recorder_ready = 0;
00399         int startup;
00400         close(operf_record_ready_pipe[1]);
00401         if (startApp) {
00402             if (read(app_ready_pipe[0], &startup, sizeof(startup)) == -1) {
00403                 perror("Internal error on app_ready_pipe");
00404                 return -1;
00405             } else if (startup != 1) {
00406                 cerr << "app is not ready to start; exiting" << endl;
00407                 return -1;
00408             }
00409         }
00410 
00411         if (read(operf_record_ready_pipe[0], &recorder_ready, sizeof(recorder_ready)) == -1) {
00412             perror("Internal error on operf_record_ready_pipe");
00413             return -1;
00414         } else if (recorder_ready != 1) {
00415             cverb << vdebug << "operf record process failure; exiting" << endl;
00416             if (startApp) {
00417                 cverb << vdebug << "telling child to abort starting of app" << endl;
00418                 startup = 0;
00419                 if (write(start_app_pipe[1], &startup, sizeof(startup)) < 0) {
00420                     perror("Internal error on start_app_pipe");
00421                 }
00422             }
00423             return -1;
00424         }
00425 
00426         if (startApp) {
00427             // Tell app_PID to start the app
00428             cverb << vdebug << "telling child to start app" << endl;
00429             if (write(start_app_pipe[1], &startup, sizeof(startup)) < 0) {
00430                 perror("Internal error on start_app_pipe");
00431                 return -1;
00432             }
00433         }
00434 
00435     }
00436     if (!operf_options::system_wide)
00437         app_started = true;
00438 
00439     // parent returns
00440     return 0;
00441 }
00442 
00443 static end_code_t _kill_operf_read_pid(end_code_t rc)
00444 {
00445     // Now stop the operf-read process
00446     int waitpid_status;
00447     struct timeval tv;
00448     long long start_time_sec;
00449     long long usec_timer;
00450     bool keep_trying = true;
00451     waitpid_status = 0;
00452     gettimeofday(&tv, NULL);
00453     start_time_sec = tv.tv_sec;
00454     usec_timer = tv.tv_usec;
00455     /* We'll initially try the waitpid with WNOHANG once every 100,000 usecs.
00456      * If it hasn't ended within 5 seconds, we'll kill it and do one
00457      * final wait.
00458      */
00459     while (keep_trying) {
00460         int option = WNOHANG;
00461         int wait_rc;
00462         gettimeofday(&tv, NULL);
00463         if (tv.tv_sec > start_time_sec + 5) {
00464             keep_trying = false;
00465             option = 0;
00466             cerr << "now trying to kill convert pid..." << endl;
00467 
00468             if (kill(operf_read_pid, SIGUSR1) < 0) {
00469                 perror("Attempt to stop operf-read process failed");
00470                 rc = rc ? PERF_BOTH_ERROR : PERF_READ_ERROR;
00471                 break;
00472             }
00473         } else {
00474             /* If we exceed the 100000 usec interval or if the tv_usec
00475              * value has rolled over to restart at 0, then we reset
00476              * the usec_timer to current tv_usec and try waitpid.
00477              */
00478             if ((tv.tv_usec % 1000000) > (usec_timer + 100000)
00479                     || (tv.tv_usec < usec_timer))
00480                 usec_timer = tv.tv_usec;
00481             else
00482                 continue;
00483         }
00484         if ((wait_rc = waitpid(operf_read_pid, &waitpid_status, option)) < 0) {
00485             keep_trying = false;
00486             if (errno != ECHILD) {
00487                 perror("waitpid for operf-read process failed");
00488                 rc = rc ? PERF_BOTH_ERROR : PERF_READ_ERROR;
00489             }
00490         } else if (wait_rc) {
00491             if (WIFEXITED(waitpid_status)) {
00492                 keep_trying = false;
00493                 if (!WEXITSTATUS(waitpid_status)) {
00494                     cverb << vdebug << "operf-read process returned OK" << endl;
00495                 } else if (WIFEXITED(waitpid_status)) {
00496                     /* If user did ctl-c, operf-record may get spurious errors, like
00497                      * broken pipe, etc.  We ignore these unless the user asks for
00498                      * debug output.
00499                      */
00500                     if (!ctl_c || cverb << vdebug) {
00501                         cerr <<  "operf-read process ended abnormally.  Status = "
00502                              << WEXITSTATUS(waitpid_status) << endl;
00503                         rc = rc ? PERF_BOTH_ERROR : PERF_READ_ERROR;
00504                     }
00505                 }
00506             }  else if (WIFSIGNALED(waitpid_status)) {
00507                 keep_trying = false;
00508                 /* If user did ctl-c, operf-record may get spurious errors, like
00509                  * broken pipe, etc.  We ignore these unless the user asks for
00510                  * debug output.
00511                  */
00512                 if (!ctl_c || cverb << vdebug) {
00513                     cerr << "operf-read process killed by signal "
00514                          << WTERMSIG(waitpid_status) << endl;
00515                     rc = PERF_RECORD_ERROR;
00516                 }
00517             }
00518         }
00519     }
00520     return rc;
00521 }
00522 
00523 static end_code_t _kill_operf_record_pid(void)
00524 {
00525     int waitpid_status = 0;
00526     end_code_t rc = ALL_OK;
00527 
00528     // stop operf-record process
00529     if (kill(operf_record_pid, SIGUSR1) < 0) {
00530         perror("Attempt to stop operf-record process failed");
00531         rc = PERF_RECORD_ERROR;
00532     } else {
00533         if (waitpid(operf_record_pid, &waitpid_status, 0) < 0) {
00534             perror("waitpid for operf-record process failed");
00535             rc = PERF_RECORD_ERROR;
00536         } else {
00537             if (WIFEXITED(waitpid_status) && (!WEXITSTATUS(waitpid_status))) {
00538                 cverb << vdebug << "operf-record process returned OK" << endl;
00539             } else if (WIFEXITED(waitpid_status)) {
00540                 /* If user did ctl-c, operf-record may get spurious errors, like
00541                  * broken pipe, etc.  We ignore these unless the user asks for
00542                  * debug output.
00543                  */
00544                 if (!ctl_c || cverb << vdebug) {
00545                     cerr <<  "operf-record process ended abnormally: "
00546                             << WEXITSTATUS(waitpid_status) << endl;
00547                     rc = PERF_RECORD_ERROR;
00548                 }
00549             } else if (WIFSIGNALED(waitpid_status)) {
00550                 if (!ctl_c || cverb << vdebug) {
00551                     cerr << "operf-record process killed by signal "
00552                          << WTERMSIG(waitpid_status) << endl;
00553                     rc = PERF_RECORD_ERROR;
00554                 }
00555             }
00556         }
00557     }
00558     return rc;
00559 }
00560 
00561 static end_code_t _run(void)
00562 {
00563     int waitpid_status = 0;
00564     end_code_t rc = ALL_OK;
00565     bool kill_record = true;
00566 
00567     // Fork processes with signals blocked.
00568     sigset_t ss;
00569     sigfillset(&ss);
00570     sigprocmask(SIG_BLOCK, &ss, NULL);
00571 
00572     /* By default (unless the user specifies --lazy-conversion), the operf-record process
00573      * writes the sample data to a pipe, from which the operf-read process reads.
00574      */
00575     if (!operf_options::post_conversion && pipe(sample_data_pipe) < 0) {
00576         perror("Internal error: operf-record could not create pipe");
00577         _exit(EXIT_FAILURE);
00578     }
00579 
00580     if (start_profiling() < 0) {
00581         return PERF_RECORD_ERROR;
00582     }
00583     // parent continues here
00584     if (startApp)
00585         cverb << vdebug << "app " << app_PID << " is running" << endl;
00586 
00587     /* If we're not doing system wide profiling and no app is started, then
00588      * there's no profile data to convert. So if this condition is NOT true,
00589      * then we'll do the convert.
00590      * Note that if --lazy-connversion is passed, then operf_options::post_conversion
00591      * will be set, and we will defer conversion until after the operf-record
00592      * process is done.
00593      */
00594     if (!operf_options::post_conversion) {
00595         if (!(!app_started && !operf_options::system_wide)) {
00596             cverb << vdebug << "Forking read pid" << endl;
00597             operf_read_pid = fork();
00598             if (operf_read_pid < 0) {
00599                 perror("Internal error: fork failed");
00600                 _exit(EXIT_FAILURE);
00601             } else if (operf_read_pid == 0) { // child process
00602                 close(sample_data_pipe[1]);
00603                 convert_sample_data();
00604             }
00605             // parent
00606             close(sample_data_pipe[0]);
00607             close(sample_data_pipe[1]);
00608         }
00609     }
00610 
00611     set_signals();
00612     cerr << "operf: Profiler started" << endl;
00613     if (startApp) {
00614         /* The user passed in a command or program name to start, so we'll need to do waitpid on that
00615          * process.  However, while that user-requested process is running, it's possible we
00616          * may get an error in the operf-record process.  If that happens, we want to know it right
00617          * away so we can stop profiling and kill the user app.  Therefore, we must use WNOHANG
00618          * on the waitpid call and bounce back and forth between the user app and the operf-record
00619          * process, checking their status.  The profiled app may end normally, abnormally, or by way
00620          * of ctrl-C.  The operf-record process should not end here, except abnormally.  The normal
00621          * flow is:
00622          *    1. profiled app ends or is stopped vi ctrl-C
00623          *    2. keep_trying is set to false, so we drop out of while loop and proceed to end of function
00624          *    3. call _kill_operf_record_pid and _kill_operf_read_pid
00625          */
00626         struct timeval tv;
00627         long long usec_timer;
00628         bool keep_trying = true;
00629         const char * app_process = "profiled app";
00630         const char * record_process = "operf-record process";
00631         waitpid_status = 0;
00632         gettimeofday(&tv, NULL);
00633         usec_timer = tv.tv_usec;
00634         cverb << vdebug << "going into waitpid on profiled app " << app_PID << endl;
00635 
00636         // We'll try the waitpid with WNOHANG once every 100,000 usecs.
00637         while (keep_trying) {
00638             pid_t the_pid = app_PID;
00639             int wait_rc;
00640             const char * the_process = app_process;
00641             gettimeofday(&tv, NULL);
00642             /* If we exceed the 100000 usec interval or if the tv_usec
00643              * value has rolled over to restart at 0, then we reset
00644              * the usec_timer to current tv_usec and try waitpid.
00645              */
00646             if ((tv.tv_usec % 1000000) > (usec_timer + 100000)
00647                     || (tv.tv_usec < usec_timer))
00648                 usec_timer = tv.tv_usec;
00649             else
00650                 continue;
00651 
00652             bool trying_user_app = true;
00653 again:
00654             if ((wait_rc = waitpid(the_pid, &waitpid_status, WNOHANG)) < 0) {
00655                 keep_trying = false;
00656                 if (errno == EINTR) {
00657                     //  Ctrl-C will only kill the profiled app.  See the op_sig_stop signal handler.
00658                     cverb << vdebug << "Caught ctrl-C.  Killed " << the_process << "." << endl;
00659                 } else {
00660                     cerr << "waitpid for " << the_process << " failed: " << strerror(errno) << endl;
00661                     rc = trying_user_app ? APP_ABNORMAL_END : PERF_RECORD_ERROR;
00662                 }
00663             } else if (wait_rc) {
00664                 keep_trying = false;
00665                 if (WIFEXITED(waitpid_status) && (!WEXITSTATUS(waitpid_status))) {
00666                     cverb << vdebug << the_process << " ended normally." << endl;
00667                 } else if (WIFEXITED(waitpid_status)) {
00668                     cerr <<  the_process << " exited with the following status: "
00669                          << WEXITSTATUS(waitpid_status) << endl;
00670                     rc = trying_user_app ? APP_ABNORMAL_END : PERF_RECORD_ERROR;
00671                 }  else if (WIFSIGNALED(waitpid_status)) {
00672                     if (WTERMSIG(waitpid_status) != SIGKILL) {
00673                         cerr << the_process << " killed by signal "
00674                              << WTERMSIG(waitpid_status) << endl;
00675                         rc = trying_user_app ? APP_ABNORMAL_END : PERF_RECORD_ERROR;
00676                     }
00677                 } else {
00678                     keep_trying = true;
00679                 }
00680             }
00681             if (trying_user_app && (rc == ALL_OK)) {
00682                 trying_user_app = false;
00683                 the_pid = operf_record_pid;
00684                 the_process = record_process;
00685                 goto again;
00686             } else if (rc != ALL_OK) {
00687                 // If trying_user_app == true, implies profiled app ended; otherwise, operf-record process abended.
00688                 if (!trying_user_app)
00689                     kill_record = false;
00690             }
00691         }
00692     } else {
00693         // User passed in --pid or --system-wide
00694         cout << "operf: Press Ctl-c or 'kill -SIGINT " << getpid() << "' to stop profiling" << endl;
00695         cverb << vdebug << "going into waitpid on operf record process " << operf_record_pid << endl;
00696         if (waitpid(operf_record_pid, &waitpid_status, 0) < 0) {
00697             if (errno == EINTR) {
00698                 cverb << vdebug << "Caught ctrl-C. Killing operf-record process . . ." << endl;
00699             } else {
00700                 cerr << "waitpid errno is " << errno << endl;
00701                 perror("waitpid for operf-record process failed");
00702                 kill_record = false;
00703                 rc = PERF_RECORD_ERROR;
00704             }
00705         } else {
00706             if (WIFEXITED(waitpid_status) && (!WEXITSTATUS(waitpid_status))) {
00707                 cverb << vdebug << "waitpid for operf-record process returned OK" << endl;
00708             } else if (WIFEXITED(waitpid_status)) {
00709                 kill_record = false;
00710                 cerr <<  "operf-record process ended abnormally: "
00711                      << WEXITSTATUS(waitpid_status) << endl;
00712                 rc = PERF_RECORD_ERROR;
00713             } else if (WIFSIGNALED(waitpid_status)) {
00714                 kill_record = false;
00715                 cerr << "operf-record process killed by signal "
00716                      << WTERMSIG(waitpid_status) << endl;
00717                 rc = PERF_RECORD_ERROR;
00718             }
00719         }
00720     }
00721     if (kill_record) {
00722         if (operf_options::post_conversion)
00723             rc = _kill_operf_record_pid();
00724         else
00725             rc = _kill_operf_read_pid(_kill_operf_record_pid());
00726     } else {
00727         if (!operf_options::post_conversion)
00728             rc = _kill_operf_read_pid(rc);
00729     }
00730 
00731     return rc;
00732 }
00733 
00734 static void cleanup(void)
00735 {
00736     free(app_name_SAVE);
00737     free(app_args);
00738     events.clear();
00739     verbose_string.clear();
00740     if (operf_options::post_conversion) {
00741         string cmd = "rm -f " + outputfile;
00742         if (system(cmd.c_str()) != 0)
00743             cerr << "Unable to remove " << outputfile << endl;
00744     }
00745 }
00746 
00747 static void _jitconv_complete(int val __attribute__((unused)))
00748 {
00749     int child_status;
00750     pid_t the_pid = wait(&child_status);
00751     if (the_pid != jitconv_pid) {
00752         return;
00753     }
00754     jit_conversion_running = false;
00755     if (WIFEXITED(child_status) && (!WEXITSTATUS(child_status))) {
00756         cverb << vdebug << "JIT dump processing complete." << endl;
00757     } else {
00758          if (WIFSIGNALED(child_status))
00759              cerr << "child received signal " << WTERMSIG(child_status) << endl;
00760          else
00761              cerr << "JIT dump processing exited abnormally: "
00762              << WEXITSTATUS(child_status) << endl;
00763     }
00764 }
00765 
00766 static void _set_signals_for_convert(void)
00767 {
00768     struct sigaction act;
00769     sigset_t ss;
00770 
00771     sigfillset(&ss);
00772     sigprocmask(SIG_UNBLOCK, &ss, NULL);
00773 
00774     act.sa_handler = _jitconv_complete;
00775     act.sa_flags = 0;
00776     sigemptyset(&act.sa_mask);
00777     sigaddset(&act.sa_mask, SIGCHLD);
00778     if (sigaction(SIGCHLD, &act, NULL)) {
00779         perror("operf: install of SIGCHLD handler failed: ");
00780         exit(EXIT_FAILURE);
00781     }
00782 
00783     act.sa_handler = _handle_sigint;
00784     sigemptyset(&act.sa_mask);
00785     sigaddset(&act.sa_mask, SIGINT);
00786     if (sigaction(SIGINT, &act, NULL)) {
00787         perror("operf: install of SIGINT handler failed: ");
00788         exit(EXIT_FAILURE);
00789     }
00790 }
00791 
00792 static void _do_jitdump_convert()
00793 {
00794     int arg_num;
00795     unsigned long long end_time = 0ULL;
00796     struct timeval tv;
00797     char end_time_str[32];
00798     char opjitconv_path[PATH_MAX + 1];
00799     char * exec_args[8];
00800 
00801     jitconv_pid = fork();
00802     switch (jitconv_pid) {
00803     case -1:
00804         perror("Error forking JIT dump process!");
00805         break;
00806     case 0: {
00807         const char * jitconv_pgm = "opjitconv";
00808         const char * debug_option = "-d";
00809         const char * non_root_user = "--non-root";
00810         const char * delete_jitdumps = "--delete-jitdumps";
00811         gettimeofday(&tv, NULL);
00812         end_time = tv.tv_sec;
00813         sprintf(end_time_str, "%llu", end_time);
00814         sprintf(opjitconv_path, "%s/%s", OP_BINDIR, jitconv_pgm);
00815         arg_num = 0;
00816         exec_args[arg_num++] = (char *)jitconv_pgm;
00817         if (cverb << vdebug)
00818             exec_args[arg_num++] = (char *)debug_option;
00819         if (my_uid != 0)
00820             exec_args[arg_num++] = (char *)non_root_user;
00821         exec_args[arg_num++] = (char *)delete_jitdumps;
00822         exec_args[arg_num++] = (char *)operf_options::session_dir.c_str();
00823         exec_args[arg_num++] = start_time_str;
00824         exec_args[arg_num++] = end_time_str;
00825         exec_args[arg_num] = (char *) NULL;
00826         execvp(opjitconv_path, exec_args);
00827         fprintf(stderr, "Failed to exec %s: %s\n",
00828                 exec_args[0], strerror(errno));
00829         /* We don't want any cleanup in the child */
00830         _exit(EXIT_FAILURE);
00831         break;
00832     }
00833     default: // parent
00834         jit_conversion_running = true;
00835         break;
00836     }
00837 
00838 }
00839 
00840 static int __delete_old_previous_sample_data(const char *fpath,
00841                                 const struct stat *sb  __attribute__((unused)),
00842                                 int tflag  __attribute__((unused)),
00843                                 struct FTW *ftwbuf __attribute__((unused)))
00844 {
00845     if (remove(fpath)) {
00846         perror("sample data removal error");
00847         return FTW_STOP;
00848     } else {
00849         return FTW_CONTINUE;
00850     }
00851 }
00852 
00853 /* Read perf_events sample data written by the operf-record process
00854  * through the sample_data_pipe and convert this to oprofile format
00855  * sample files.
00856  */
00857 static void convert_sample_data(void)
00858 {
00859     int inputfd;
00860     string inputfname;
00861     int rc = EXIT_SUCCESS;
00862     int keep_waiting = 0;
00863     string current_sampledir = samples_dir + "/current/";
00864     string previous_sampledir = samples_dir + "/previous";
00865     current_sampledir.copy(op_samples_current_dir, current_sampledir.length(), 0);
00866 
00867     if (!app_started && !operf_options::system_wide)
00868         return;
00869 
00870     if (!operf_options::append) {
00871                 int flags = FTW_DEPTH | FTW_ACTIONRETVAL;
00872         errno = 0;
00873         if (nftw(previous_sampledir.c_str(), __delete_old_previous_sample_data, 32, flags) !=0 &&
00874                 errno != ENOENT) {
00875             cerr << "Unable to remove old sample data at " << previous_sampledir << "." << endl;
00876             if (errno)
00877                 cerr << strerror(errno) << endl;
00878             rc = EXIT_FAILURE;
00879             goto out;
00880         }
00881         if (rename(current_sampledir.c_str(), previous_sampledir.c_str()) < 0) {
00882             if (errno && (errno != ENOENT)) {
00883                 cerr << "Unable to move old profile data to " << previous_sampledir << endl;
00884                 cerr << strerror(errno) << endl;
00885                 rc = EXIT_FAILURE;
00886                 goto out;
00887             }
00888         }
00889     }
00890     rc = mkdir(current_sampledir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00891     if (rc && (errno != EEXIST)) {
00892         cerr << "Error trying to create " << current_sampledir << " dir." << endl;
00893         perror("mkdir failed with");
00894         rc = EXIT_FAILURE;
00895         goto out;
00896     }
00897 
00898     if (operf_options::post_conversion) {
00899         inputfd = -1;
00900         inputfname = outputfile;
00901     } else {
00902         inputfd = sample_data_pipe[0];
00903         inputfname = "";
00904     }
00905     operfRead.init(inputfd, inputfname, current_sampledir, cpu_type, events, operf_options::system_wide);
00906     if ((rc = operfRead.readPerfHeader()) < 0) {
00907         if (rc != OP_PERF_HANDLED_ERROR)
00908             cerr << "Error: Cannot create read header info for sample data " << endl;
00909         rc = EXIT_FAILURE;
00910         goto out;
00911     }
00912     cverb << vdebug << "Successfully read header info for sample data " << endl;
00913     if (operfRead.is_valid()) {
00914         try {
00915             int num = operfRead.convertPerfData();
00916             cverb << vdebug << "operf_read: Total bytes received from operf_record process: " << dec << num << endl;
00917         } catch (runtime_error e) {
00918             cerr << "Caught runtime error from operf_read::convertPerfData" << endl;
00919             cerr << e.what() << endl;
00920             rc = EXIT_FAILURE;
00921             goto out;
00922         }
00923     }
00924     _set_signals_for_convert();
00925     cverb << vdebug << "Calling _do_jitdump_convert" << endl;
00926     _do_jitdump_convert();
00927     while (jit_conversion_running && (keep_waiting < 2)) {
00928         sleep(1);
00929         keep_waiting++;
00930     }
00931     if (jit_conversion_running) {
00932         kill(jitconv_pid, SIGKILL);
00933     }
00934 out:
00935     if (!operf_options::post_conversion)
00936         _exit(rc);
00937 }
00938 
00939 
00940 static int find_app_file_in_dir(const struct dirent * d)
00941 {
00942     if (!strcmp(d->d_name, app_name))
00943         return 1;
00944     else
00945         return 0;
00946 }
00947 
00948 static int get_PATH_based_pathname(char * path_holder, size_t n)
00949 {
00950     int retval = -1;
00951 
00952     char * real_path = getenv("PATH");
00953     char * path = (char *) xstrdup(real_path);
00954     char * segment = strtok(path, ":");
00955     while (segment) {
00956         struct dirent ** namelist;
00957         int rc = scandir(segment, &namelist, find_app_file_in_dir, NULL);
00958         if (rc < 0) {
00959             cerr << app_name << " cannot be found in your PATH." << endl;
00960             break;
00961         } else if (rc == 1) {
00962             size_t applen = strlen(app_name);
00963             size_t dirlen = strlen(segment);
00964 
00965             if (applen + dirlen + 2 > n) {
00966                 cerr << "Path segment " << segment
00967                      << " prepended to the passed app name is too long"
00968                      << endl;
00969                 retval = -1;
00970                 break;
00971             }
00972             strncpy(path_holder, segment, dirlen);
00973             strcat(path_holder, "/");
00974             strncat(path_holder, app_name, applen);
00975             retval = 0;
00976             free(namelist[0]);
00977             free(namelist);
00978             break;
00979         }
00980         segment = strtok(NULL, ":");
00981     }
00982     free(path);
00983     return retval;
00984 }
00985 int validate_app_name(void)
00986 {
00987     int rc = 0;
00988     struct stat filestat;
00989     size_t len = strlen(app_name);
00990 
00991     if (len > (size_t) (OP_APPNAME_LEN - 1)) {
00992         cerr << "app name longer than max allowed (" << OP_APPNAME_LEN
00993              << " chars)\n";
00994         cerr << app_name << endl;
00995         rc = -1;
00996         goto out;
00997     }
00998 
00999     if (index(app_name, '/') == app_name) {
01000         // Full pathname of app was specified, starting with "/".
01001         strncpy(full_pathname, app_name, len);
01002     } else if ((app_name[0] == '.') && (app_name[1] == '/')) {
01003         // Passed app is in current directory; e.g., "./myApp"
01004         if (getcwd(full_pathname, PATH_MAX) == NULL) {
01005             rc = -1;
01006             cerr << "getcwd [1] failed when trying to find app name " << app_name << ". Aborting."
01007                  << endl;
01008             goto out;
01009         }
01010         strcat(full_pathname, "/");
01011         strcat(full_pathname, (app_name + 2));
01012     } else if (index(app_name, '/')) {
01013         // Passed app is in a subdirectory of cur dir; e.g., "test-stuff/myApp"
01014         if (getcwd(full_pathname, PATH_MAX) == NULL) {
01015             rc = -1;
01016             cerr << "getcwd [2] failed when trying to find app name " << app_name << ". Aborting."
01017                  << endl;
01018             goto out;
01019         }
01020         strcat(full_pathname, "/");
01021         strcat(full_pathname, app_name);
01022     } else {
01023         // Pass app name, at this point, MUST be found in PATH
01024         rc = get_PATH_based_pathname(full_pathname, PATH_MAX);
01025     }
01026 
01027     if (rc) {
01028         cerr << "Problem finding app name " << app_name << ". Aborting."
01029              << endl;
01030         goto out;
01031     }
01032     app_name_SAVE = app_name;
01033     app_name = full_pathname;
01034     if (stat(app_name, &filestat)) {
01035         char msg[OP_APPNAME_LEN + 50];
01036         snprintf(msg, OP_APPNAME_LEN + 50, "Non-existent app name \"%s\"",
01037                  app_name);
01038         perror(msg);
01039         rc = -1;
01040     }
01041 
01042     out: return rc;
01043 }
01044 
01045 static void _get_event_code(operf_event_t * event)
01046 {
01047     FILE * fp;
01048     char oprof_event_code[9];
01049     string command;
01050     u64 base_code, config;
01051     base_code = config = 0ULL;
01052 
01053     command = OP_BINDIR;
01054     command += "ophelp ";
01055     command += event->name;
01056 
01057     fp = popen(command.c_str(), "r");
01058     if (fp == NULL) {
01059         cerr << "Unable to execute ophelp to get info for event "
01060              << event->name << endl;
01061         exit(EXIT_FAILURE);
01062     }
01063     if (fgets(oprof_event_code, sizeof(oprof_event_code), fp) == NULL) {
01064         pclose(fp);
01065         cerr << "Unable to find info for event "
01066              << event->name << endl;
01067         exit(EXIT_FAILURE);
01068     }
01069 
01070     pclose(fp);
01071 
01072     base_code = strtoull(oprof_event_code, (char **) NULL, 10);
01073 
01074 
01075 #if defined(__i386__) || defined(__x86_64__)
01076     // Setup EventSelct[11:8] field for AMD
01077     const char * vendor_AMD = "AuthenticAMD";
01078     if (op_is_cpu_vendor((char *)vendor_AMD)) {
01079         config = base_code & 0xF00ULL;
01080         config = config << 32;
01081     }
01082 
01083     // Setup EventSelct[7:0] field
01084     config |= base_code & 0xFFULL;
01085 
01086     // Setup unitmask field
01087     if (event->um_name[0]) {
01088         char mask[12];
01089         char buf[20];
01090         if ((snprintf(buf, 20, "%lu", event->count)) == -1) {
01091             cerr << "Error parsing event count of " << event->count << endl;
01092             exit(EXIT_FAILURE);
01093         }
01094         command = OP_BINDIR;
01095         command += "ophelp ";
01096         command += "--extra-mask ";
01097         command += event->name;
01098         command += ":";
01099         command += buf;
01100         command += ":";
01101         command += event->um_name;
01102         fp = popen(command.c_str(), "r");
01103         if (fp == NULL) {
01104             cerr << "Unable to execute ophelp to get info for event "
01105                  << event->name << endl;
01106             exit(EXIT_FAILURE);
01107         }
01108         if (fgets(mask, sizeof(mask), fp) == NULL) {
01109             pclose(fp);
01110             cerr << "Unable to find unit mask info for " << event->um_name << " for event "
01111                  << event->name << endl;
01112             exit(EXIT_FAILURE);
01113         }
01114         pclose(fp);
01115         config |= strtoull(mask, (char **) NULL, 10);
01116     } else {
01117         config |= ((event->evt_um & 0xFFULL) << 8);
01118     }
01119 #else
01120     config = base_code;
01121 #endif
01122 
01123     event->op_evt_code = base_code;
01124     event->evt_code = config;
01125 }
01126 
01127 static void _process_events_list(void)
01128 {
01129     string cmd = OP_BINDIR;
01130     cmd += "/ophelp --check-events ";
01131     for (unsigned int i = 0; i <  operf_options::evts.size(); i++) {
01132         FILE * fp;
01133         string full_cmd = cmd;
01134         string event_spec = operf_options::evts[i];
01135         if (operf_options::callgraph) {
01136             full_cmd += " --callgraph=1 ";
01137         }
01138         full_cmd += event_spec;
01139         fp = popen(full_cmd.c_str(), "r");
01140         if (fp == NULL) {
01141             cerr << "Unable to execute ophelp to get info for event "
01142                  << event_spec << endl;
01143             exit(EXIT_FAILURE);
01144         }
01145         if (fgetc(fp) == EOF) {
01146             pclose(fp);
01147             cerr << "Error retrieving info for event "
01148                  << event_spec << endl;
01149             if (operf_options::callgraph)
01150                 cerr << "Note: When doing callgraph profiling, the sample count must be"
01151                      << endl << "15 times the minimum count value for the event."  << endl;
01152             exit(EXIT_FAILURE);
01153         }
01154         fclose(fp);
01155         char * event_str = op_xstrndup(event_spec.c_str(), event_spec.length());
01156         operf_event_t event;
01157         strncpy(event.name, strtok(event_str, ":"), OP_MAX_EVT_NAME_LEN);
01158         event.count = atoi(strtok(NULL, ":"));
01159         /* Name and count are required in the event spec in order for
01160          * 'ophelp --check-events' to pass.  But since unit mask and domain
01161          * control bits are optional, we need to ensure the result of strtok
01162          * is valid.
01163          */
01164         char * info;
01165 #define _OP_UM 1
01166 #define _OP_KERNEL 2
01167 #define _OP_USER 3
01168         int place =  _OP_UM;
01169         char * endptr = NULL;
01170         event.evt_um = 0ULL;
01171         event.no_kernel = 0;
01172         event.no_user = 0;
01173         memset(event.um_name, '\0', OP_MAX_UM_NAME_LEN);
01174         while ((info = strtok(NULL, ":"))) {
01175             switch (place) {
01176             case _OP_UM:
01177                 event.evt_um = strtoul(info, &endptr, 0);
01178                 // If any of the UM part is not a number, then we
01179                 // consider the entire part a string.
01180                 if (*endptr) {
01181                     event.evt_um = 0;
01182                     strncpy(event.um_name, info, OP_MAX_UM_NAME_LEN);
01183                 }
01184                 break;
01185             case _OP_KERNEL:
01186                 if (atoi(info) == 0)
01187                     event.no_kernel = 1;
01188                 break;
01189             case _OP_USER:
01190                 if (atoi(info) == 0)
01191                     event.no_user = 1;
01192                 break;
01193             }
01194             place++;
01195         }
01196         free(event_str);
01197         _get_event_code(&event);
01198         events.push_back(event);
01199     }
01200 #if (defined(__powerpc__) || defined(__powerpc64__))
01201     {
01202         /* This section of code is for architectures such as ppc[64] for which
01203          * the oprofile event code needs to be converted to the appropriate event
01204          * code to pass to the perf_event_open syscall.
01205          */
01206 
01207         using namespace OP_perf_utils;
01208         if (!op_convert_event_vals(&events)) {
01209             cerr << "Unable to convert all oprofile event values to perf_event values" << endl;
01210             exit(EXIT_FAILURE);
01211         }
01212     }
01213 #endif
01214 }
01215 
01216 static void get_default_event(void)
01217 {
01218     operf_event_t dft_evt;
01219     struct op_default_event_descr descr;
01220     vector<operf_event_t> tmp_events;
01221 
01222 
01223     op_default_event(cpu_type, &descr);
01224     if (descr.name[0] == '\0') {
01225         cerr << "Unable to find default event" << endl;
01226         exit(EXIT_FAILURE);
01227     }
01228 
01229     memset(&dft_evt, 0, sizeof(dft_evt));
01230     if (operf_options::callgraph) {
01231         struct op_event * _event;
01232         op_events(cpu_type);
01233         if ((_event = find_event_by_name(descr.name, 0, 0))) {
01234             dft_evt.count = _event->min_count * CALLGRAPH_MIN_COUNT_SCALE;
01235         } else {
01236             cerr << "Error getting event info for " << descr.name << endl;
01237             exit(EXIT_FAILURE);
01238         }
01239     } else {
01240         dft_evt.count = descr.count;
01241     }
01242     dft_evt.evt_um = descr.um;
01243     strncpy(dft_evt.name, descr.name, OP_MAX_EVT_NAME_LEN - 1);
01244     _get_event_code(&dft_evt);
01245     events.push_back(dft_evt);
01246 
01247 #if (defined(__powerpc__) || defined(__powerpc64__))
01248     {
01249         /* This section of code is for architectures such as ppc[64] for which
01250          * the oprofile event code needs to be converted to the appropriate event
01251          * code to pass to the perf_event_open syscall.
01252          */
01253 
01254         using namespace OP_perf_utils;
01255         if (!op_convert_event_vals(&events)) {
01256             cerr << "Unable to convert all oprofile event values to perf_event values" << endl;
01257             exit(EXIT_FAILURE);
01258         }
01259     }
01260 #endif
01261 }
01262 
01263 static void _process_session_dir(void)
01264 {
01265     if (operf_options::session_dir.empty()) {
01266         char * cwd = NULL;
01267         int rc;
01268         cwd = (char *) xmalloc(PATH_MAX);
01269         // set default session dir
01270         cwd = getcwd(cwd, PATH_MAX);
01271         operf_options::session_dir = cwd;
01272         operf_options::session_dir +="/oprofile_data";
01273         samples_dir = operf_options::session_dir + "/samples";
01274         free(cwd);
01275         rc = mkdir(operf_options::session_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
01276         if (rc && (errno != EEXIST)) {
01277             cerr << "Error trying to create " << operf_options::session_dir << " dir." << endl;
01278             perror("mkdir failed with");
01279             exit(EXIT_FAILURE);
01280         }
01281         rc = mkdir(samples_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
01282         if (rc && (errno != EEXIST)) {
01283             cerr << "Error trying to create " << samples_dir << " dir." << endl;
01284             perror("mkdir failed with");
01285             exit(EXIT_FAILURE);
01286         }
01287     } else {
01288         struct stat filestat;
01289         int rc;
01290         if (stat(operf_options::session_dir.c_str(), &filestat)) {
01291             perror("stat operation on passed session-dir failed");
01292             exit(EXIT_FAILURE);
01293         }
01294         if (!S_ISDIR(filestat.st_mode)) {
01295             cerr << "Passed session-dir " << operf_options::session_dir
01296                  << " is not a directory" << endl;
01297             exit(EXIT_FAILURE);
01298         }
01299         samples_dir = operf_options::session_dir + "/samples";
01300         rc = mkdir(samples_dir.c_str(), S_IRWXU);
01301         if (rc && (errno != EEXIST)) {
01302             cerr << "Error trying to create " << samples_dir << " dir." << endl;
01303             perror("mkdir failed with");
01304             exit(EXIT_FAILURE);
01305         }
01306     }
01307     cverb << vdebug << "Using samples dir " << samples_dir << endl;
01308 }
01309 
01310 bool _get_vmlinux_address_info(vector<string> args, string cmp_val, string &str)
01311 {
01312     bool found = false;
01313     child_reader reader("objdump", args);
01314     if (reader.error()) {
01315         cerr << "An error occurred while trying to get vmlinux address info:\n\n";
01316         cerr << reader.error_str() << endl;
01317         exit(EXIT_FAILURE);
01318     }
01319 
01320     while (reader.getline(str)) {
01321         if (str.find(cmp_val.c_str()) != string::npos) {
01322             found = true;
01323             break;
01324         }
01325     }
01326     // objdump always returns SUCCESS so we must rely on the stderr state
01327     // of objdump. If objdump error message is cryptic our own error
01328     // message will be probably also cryptic
01329     ostringstream std_err;
01330     ostringstream std_out;
01331     reader.get_data(std_out, std_err);
01332     if (std_err.str().length()) {
01333         cerr << "An error occurred while getting vmlinux address info:\n\n";
01334         cerr << std_err.str() << endl;
01335         // If we found the string we were looking for in objdump output,
01336         // treat this as non-fatal error.
01337         if (!found)
01338             exit(EXIT_FAILURE);
01339     }
01340 
01341     // force error code to be acquired
01342     reader.terminate_process();
01343 
01344     // required because if objdump stop by signal all above things suceeed
01345     // (signal error message are not output through stdout/stderr)
01346     if (reader.error()) {
01347         cerr << "An error occur during the execution of objdump to get vmlinux address info:\n\n";
01348         cerr << reader.error_str() << endl;
01349         if (!found)
01350             exit(EXIT_FAILURE);
01351     }
01352     return found;
01353 }
01354 
01355 string _process_vmlinux(string vmlinux_file)
01356 {
01357     vector<string> args;
01358     char start[17], end[17];
01359     string str, start_end;
01360     bool found;
01361     int ret;
01362 
01363     no_vmlinux = false;
01364     args.push_back("-h");
01365     args.push_back(vmlinux_file);
01366     if ((found = _get_vmlinux_address_info(args, " .text", str))) {
01367         cverb << vmisc << str << endl;
01368         ret = sscanf(str.c_str(), " %*s %*s %*s %s", start);
01369     }
01370     if (!found || ret != 1){
01371         cerr << "Unable to obtain vmlinux start address." << endl;
01372         cerr << "The specified vmlinux file (" << vmlinux_file << ") "
01373              << "does not seem to be valid." << endl;
01374         cerr << "Make sure you are using a non-compressed image file "
01375              << "(e.g. vmlinux not vmlinuz)" << endl;
01376         exit(EXIT_FAILURE);
01377     }
01378 
01379     args.clear();
01380     args.push_back("-t");
01381     args.push_back(vmlinux_file);
01382     if ((found = _get_vmlinux_address_info(args, " _etext", str))) {
01383         cverb << vmisc << str << endl;
01384         ret = sscanf(str.c_str(), "%s", end);
01385     }
01386     if (!found || ret != 1){
01387         cerr << "Unable to obtain vmlinux end address." << endl;
01388         cerr << "The specified vmlinux file (" << vmlinux_file << ") "
01389              << "does not seem to be valid." << endl;
01390         cerr << "Make sure you are using a non-compressed image file "
01391              << "(e.g. vmlinux not vmlinuz)" << endl;
01392         exit(EXIT_FAILURE);
01393     }
01394 
01395     errno = 0;
01396     kernel_start = strtoull(start, NULL, 16);
01397     if (errno) {
01398         cerr << "Unable to convert vmlinux start address " << start
01399              << " to a valid hex value. errno is " << strerror(errno) << endl;
01400         exit(EXIT_FAILURE);
01401     }
01402     errno = 0;
01403     kernel_end =  strtoull(end, NULL, 16);
01404     if (errno) {
01405         cerr << "Unable to convert vmlinux end address " << start
01406              << " to a valid hex value. errno is " << strerror(errno) << endl;
01407         exit(EXIT_FAILURE);
01408     }
01409 
01410     start_end = start;
01411     start_end.append(",");
01412     start_end.append(end);
01413     return start_end;
01414 }
01415 
01416 static void _print_valid_verbose_options(void)
01417 {
01418     cerr << "Valid verbosity options are: ";
01419     for (unsigned i = 0; i < (NUM_VERBOSE_OPTIONS - 1); i++)
01420         cerr << valid_verbose_vals[i] << ",";
01421     cerr << valid_verbose_vals[NUM_VERBOSE_OPTIONS - 1] << endl;
01422 }
01423 
01424 static bool _validate_verbose_args(char * verbosity)
01425 {
01426     bool valid_verbosity = true;
01427 
01428     char * verbose_cand = strtok(verbosity, ",");
01429     do {
01430         unsigned i;
01431         for (i = 0; i < (NUM_VERBOSE_OPTIONS); i++) {
01432             if (!strcmp(verbose_cand, valid_verbose_vals[i])) {
01433                 verbose_string.push_back(verbose_cand);
01434                 break;
01435             }
01436         }
01437         if (i == NUM_VERBOSE_OPTIONS) {
01438             valid_verbosity = false;
01439             cerr << "Verbosity argument " << verbose_cand << " is not valid." << endl;
01440             _print_valid_verbose_options();
01441         }
01442     } while ((verbose_cand = strtok(NULL, ",")) && valid_verbosity);
01443     return valid_verbosity;
01444 }
01445 
01446 static int _process_operf_and_app_args(int argc, char * const argv[])
01447 {
01448     bool keep_trying = true;
01449     int idx_of_non_options = 0;
01450     setenv("POSIXLY_CORRECT", "1", 0);
01451     while (keep_trying) {
01452         int option_idx = 0;
01453         int c = getopt_long(argc, argv, short_options, long_options, &option_idx);
01454         switch (c) {
01455         char * endptr;
01456         char * event;
01457 
01458         case -1:
01459             if (optind != argc) {
01460                 idx_of_non_options = optind;
01461             }
01462             keep_trying = false;
01463             break;
01464         case '?':
01465             cerr << "non-option detected at optind " << optind << endl;
01466             keep_trying = false;
01467             idx_of_non_options = -1;
01468             break;
01469         case 'V':
01470             if (!_validate_verbose_args(optarg))
01471                 __print_usage_and_exit("NULL");
01472             break;
01473         case 'd':
01474             operf_options::session_dir = optarg;
01475             break;
01476         case 'k':
01477             operf_options::vmlinux = optarg;
01478             break;
01479         case 'g':
01480             operf_options::callgraph = true;
01481             break;
01482         case 's':
01483             operf_options::system_wide = true;
01484             break;
01485         case 'a':
01486             operf_options::append = true;
01487             break;
01488         case 'p':
01489             operf_options::pid = strtol(optarg, &endptr, 10);
01490             if ((endptr >= optarg) && (endptr <= (optarg + strlen(optarg) - 1)))
01491                 __print_usage_and_exit("operf: Invalid numeric value for --pid option.");
01492             break;
01493         case 'e':
01494             event = strtok(optarg, ",");
01495             do {
01496                 operf_options::evts.push_back(event);
01497             } while ((event = strtok(NULL, ",")));
01498             break;
01499         case 'c':
01500             operf_options::separate_cpu = true;
01501             break;
01502         case 't':
01503             operf_options::separate_thread = true;
01504             break;
01505         case 'l':
01506             operf_options::post_conversion = true;
01507             break;
01508         case 'h':
01509             __print_usage_and_exit(NULL);
01510             break;
01511         case 'u':
01512             __print_usage_and_exit(NULL);
01513             break;
01514         case 'v':
01515             cout << argv[0] << ": " << PACKAGE << " " << VERSION << " compiled on " << __DATE__
01516                  << " " << __TIME__ << endl;
01517             exit(EXIT_SUCCESS);
01518             break;
01519         default:
01520             __print_usage_and_exit("unexpected end of arg parsing");
01521         }
01522     }
01523     return idx_of_non_options;
01524 }
01525 
01526 static void process_args(int argc, char * const argv[])
01527 {
01528     int non_options_idx  = _process_operf_and_app_args(argc, argv);
01529 
01530     if (non_options_idx < 0) {
01531         __print_usage_and_exit(NULL);
01532     } else if ((non_options_idx) > 0) {
01533         if (operf_options::pid || operf_options::system_wide)
01534             __print_usage_and_exit(NULL);
01535 
01536         app_name = (char *) xmalloc(strlen(argv[non_options_idx]) + 1);
01537         strcpy(app_name, argv[non_options_idx]);
01538         if (non_options_idx < (argc -1)) {
01539             size_t length_all_app_args = 0;
01540             non_options_idx++;
01541             for(int i = non_options_idx; i < argc; i++)
01542                 length_all_app_args += strlen(argv[i]) + 1;
01543             if (length_all_app_args) {
01544                 app_args = (char *) xmalloc(length_all_app_args);
01545                 strcpy(app_args, argv[non_options_idx]);
01546                 non_options_idx++;
01547                 while (non_options_idx < argc) {
01548                     strcat(app_args, " ");
01549                     strcat(app_args, argv[non_options_idx]);
01550                     non_options_idx++;
01551                 }
01552             }
01553         }
01554         if (validate_app_name() < 0) {
01555             __print_usage_and_exit(NULL);
01556         }
01557     } else {  // non_options_idx == 0
01558         if (operf_options::pid) {
01559             if (operf_options::system_wide)
01560                 __print_usage_and_exit(NULL);
01561             app_PID = operf_options::pid;
01562         } else if (operf_options::system_wide) {
01563             app_PID = -1;
01564         } else {
01565             __print_usage_and_exit(NULL);
01566         }
01567     }
01568     /*  At this point, we know which of the three kinds of profiles the user requested:
01569      *    - profile app by name
01570      *    - profile app by PID
01571      *    - profile whole system
01572      */
01573 
01574     if (!verbose::setup(verbose_string)) {
01575         cerr << "unknown --verbose= options\n";
01576         exit(EXIT_FAILURE);
01577     }
01578 
01579     _process_session_dir();
01580     if (operf_options::post_conversion)
01581         outputfile = samples_dir + "/" + DEFAULT_OPERF_OUTFILE;
01582 
01583     if (operf_options::evts.empty()) {
01584         // Use default event
01585         get_default_event();
01586     } else  {
01587         _process_events_list();
01588     }
01589     op_nr_counters = events.size();
01590 
01591     if (operf_options::vmlinux.empty()) {
01592         no_vmlinux = true;
01593         operf_create_vmlinux(NULL, NULL);
01594     } else {
01595         string startEnd = _process_vmlinux(operf_options::vmlinux);
01596         operf_create_vmlinux(operf_options::vmlinux.c_str(), startEnd.c_str());
01597     }
01598 
01599     return;
01600 }
01601 
01602 static int _check_perf_events_cap(void)
01603 {
01604     /* If perf_events syscall is not implemented, the syscall below will fail
01605      * with ENOSYS (38).  If implemented, but the processor type on which this
01606      * program is running is not supported by perf_events, the syscall returns
01607      * ENOENT (2).
01608      */
01609     struct perf_event_attr attr;
01610     pid_t pid ;
01611         memset(&attr, 0, sizeof(attr));
01612         attr.size = sizeof(attr);
01613         attr.sample_type = PERF_SAMPLE_IP;
01614 
01615     pid = getpid();
01616     syscall(__NR_perf_event_open, &attr, pid, 0, -1, 0);
01617     return errno;
01618 
01619 }
01620 
01621 static void _precheck_permissions_to_samplesdir(string sampledir, bool for_current)
01622 {
01623     /* Pre-check to make sure we have permission to remove old sample data
01624      * or to create new sample data in the specified sample data directory.
01625      * If the user wants us to remove old data, we don't actually do it now,
01626      * since the profile session may fail for some reason or the user may do ctl-c.
01627      * We should exit without unnecessarily removing the old sample data as
01628      * the user may expect it to still be there after an aborted run.
01629      */
01630     string sampledir_testfile = sampledir + "/.xxxTeStFiLe";
01631     ofstream afile;
01632     errno = 0;
01633     afile.open(sampledir_testfile.c_str());
01634     if (!afile.is_open() && (errno != ENOENT)) {
01635         if (operf_options::append && for_current)
01636             cerr << "Unable to write to sample data directory at "
01637                  << sampledir << "." << endl;
01638         else
01639             cerr << "Unable to remove old sample data at "
01640                  << sampledir << "." << endl;
01641         if (errno)
01642             cerr << strerror(errno) << endl;
01643         cerr << "Try a manual removal of " << sampledir << endl;
01644         cleanup();
01645         exit(1);
01646     }
01647     afile.close();
01648 
01649 }
01650 
01651 static int _get_sys_value(const char * filename)
01652 {
01653     char str[10];
01654     int _val = -999;
01655     FILE * fp = fopen(filename, "r");
01656     if (fp == NULL)
01657         return _val;
01658     if (fgets(str, 9, fp))
01659         sscanf(str, "%d", &_val);
01660     fclose(fp);
01661     return _val;
01662 }
01663 
01664 
01665 int main(int argc, char * const argv[])
01666 {
01667     int rc;
01668     throttled = false;
01669     if ((rc = _check_perf_events_cap())) {
01670         if (rc == EBUSY) {
01671             cerr << "Performance monitor unit is busy.  Do 'opcontrol --deinit' and try again." << endl;
01672             exit(1);
01673         }
01674         if (rc == ENOSYS) {
01675             cerr << "Your kernel does not implement a required syscall"
01676                  << "  for the operf program." << endl;
01677         } else if (rc == ENOENT) {
01678             cerr << "Your kernel's Performance Events Subsystem does not support"
01679                  << " your processor type." << endl;
01680         } else {
01681             cerr << "Unexpected error running operf: " << strerror(rc) << endl;
01682         }
01683         cerr << "Please use the opcontrol command instead of operf." << endl;
01684         exit(1);
01685     }
01686 
01687     cpu_type = op_get_cpu_type();
01688     cpu_speed = op_cpu_frequency();
01689     process_args(argc, argv);
01690 
01691     int perf_event_paranoid = _get_sys_value("/proc/sys/kernel/perf_event_paranoid");
01692     my_uid = geteuid();
01693     if (operf_options::system_wide && ((my_uid != 0) && (perf_event_paranoid > 0))) {
01694         cerr << "To do system-wide profiling, either you must be root or" << endl;
01695         cerr << "/proc/sys/kernel/perf_event_paranoid must be set to 0 or -1." << endl;
01696         cleanup();
01697         exit(1);
01698     }
01699 
01700     if (cpu_type == CPU_NO_GOOD) {
01701         cerr << "Unable to ascertain cpu type.  Exiting." << endl;
01702         cleanup();
01703         exit(1);
01704     }
01705 
01706     if (my_uid != 0) {
01707         bool for_current = true;
01708         string current_sampledir = samples_dir + "/current";
01709         _precheck_permissions_to_samplesdir(current_sampledir, for_current);
01710         if (!operf_options::append) {
01711             string previous_sampledir = samples_dir + "/previous";
01712             for_current = false;
01713             _precheck_permissions_to_samplesdir(previous_sampledir, for_current);
01714         }
01715     }
01716     kptr_restrict = _get_sys_value("/proc/sys/kernel/kptr_restrict");
01717     end_code_t run_result;
01718     if ((run_result = _run())) {
01719         if (startApp && app_started && (run_result != APP_ABNORMAL_END)) {
01720             int rc;
01721             cverb << vdebug << "Killing profiled app . . ." << endl;
01722             rc = kill(app_PID, SIGKILL);
01723             if (rc) {
01724                 if (errno == ESRCH)
01725                     cverb << vdebug
01726                           << "Unable to kill profiled app because it has already ended"
01727                           << endl;
01728                 else
01729                     perror("Attempt to kill profiled app failed.");
01730             }
01731         }
01732         if ((run_result == PERF_RECORD_ERROR) || (run_result == PERF_BOTH_ERROR)) {
01733             cerr <<  "Error running profiler" << endl;
01734         } else if (run_result == PERF_READ_ERROR) {
01735             cerr << "Error converting operf sample data to oprofile sample format" << endl;
01736         } else {
01737             cerr << "WARNING: Profile results may be incomplete due to to abend of profiled app." << endl;
01738         }
01739     } else {
01740         cerr << endl << "Profiling done." << endl;
01741     }
01742     if (operf_options::post_conversion) {
01743         if (!(!app_started && !operf_options::system_wide))
01744             convert_sample_data();
01745     }
01746     cleanup();
01747     return run_result;;
01748 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1