#include #include #include #include #include //Initialize with actual program name in main() const char* gsProgramName = "Unknown!"; /** * Helper Macro used to handle TraceEvent() errors - taken from examples section * of QNX kernel trace documentation */ #define TRACE_EVENT(trace_event) \ if((int)((trace_event))==(-1)) \ { \ (void) fprintf \ ( \ stderr, \ "%s: line:%d function call TraceEvent() failed, errno(%d): %s\n", \ gsProgramName, \ __LINE__, \ errno, \ strerror(errno) \ ); \ \ return (-1); \ } #define ARRAYLEN(X) sizeof(X)/sizeof(X[0]) static int clearFilters (); static int traceProcess (pid_t pid, int traceClass, int traceMode); static int applyFilters (pid_t pid); static const int VERSION_MAJOR = 0; static const int VERSION_MINOR = 9; /** * Setup static kernel trace filters for specified processes * Main goal is to reduce amount of kernel traces. * Usage : event_filter pid1 pid2 ... pidn */ int main(int argc, char **argv) { gsProgramName = argv[0]; // Setup program name for TRACE_EVENT macro printf ("%s: event_filter ver. %i.%i\n", gsProgramName, VERSION_MAJOR, VERSION_MINOR); if (argc < 2){ // Check that at least one pid has been specified fprintf (stderr, "%s: at least one PID should be specified\n", gsProgramName); return -1; } /** * Stop currently running trace * Should not be the case as we don`t execute mcd_event_filter while tracelogger from previous * trace session is running */ TRACE_EVENT(TraceEvent(_NTO_TRACE_STOP)); /** * Clear any possible existing filters */ if (-1 == clearFilters ()){ return -1; } /** * Problem : only output for last PID is provided -> try to set * trace mode for each class/PID individually within applyFilters */ //TRACE_EVENT(TraceEvent(_NTO_TRACE_SETALLCLASSESFAST)); /** * Parse command line and setup kernel filters for each process specified */ for (int i = 1; i < argc; ++i){ const char* pidStr = argv[i]; pid_t pid = atoi (pidStr); if (pid != 0){ printf ("Apply filters to <%i>...\n", pid); if (-1 == applyFilters (pid)){ return -1; } } // get '0' in case of PID=0 or parse error : any case is invalid else { fprintf (stderr, "%s: <%s> argument invalid\n", gsProgramName, pidStr); return -1; } } /** * Currently unable to setup kernel trace filters in the way to track all specified processes * Uncomment if tracing of the whole system is OK (it works). */ #if 0 TraceEvent(_NTO_TRACE_ADDCLASS, _NTO_TRACE_COMM); TraceEvent(_NTO_TRACE_ADDCLASS, _NTO_TRACE_THREAD); TraceEvent(_NTO_TRACE_ADDCLASS, _NTO_TRACE_SYSTEM); TraceEvent(_NTO_TRACE_ADDCLASS, _NTO_TRACE_KERCALL); #endif // Step 3. Start tracing (tracelogger should be executed in daemon mode) TRACE_EVENT(TraceEvent(_NTO_TRACE_START)); printf ("Tracing started...\n"); return (0); } /** * Clear previously set filters in the way suggested by QNX documentation */ static int clearFilters () { TRACE_EVENT (TraceEvent(_NTO_TRACE_DELALLCLASSES)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSPID, _NTO_TRACE_KERCALL)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSTID, _NTO_TRACE_KERCALL)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSPID, _NTO_TRACE_THREAD)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSTID, _NTO_TRACE_THREAD)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSPID, _NTO_TRACE_VTHREAD)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSTID, _NTO_TRACE_VTHREAD)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSPID, _NTO_TRACE_SYSTEM)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSTID, _NTO_TRACE_SYSTEM)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSPID, _NTO_TRACE_COMM)); TRACE_EVENT (TraceEvent(_NTO_TRACE_CLRCLASSTID, _NTO_TRACE_COMM)); return 0; } /** * Add specified process to trace configuration */ static int traceProcess (pid_t pid, int traceClass, int traceMode) { /** * Enable specified trace class * Initially, I`ve enabled it once at the top before, but then there was a kernel trace * for last specified PID only. * Try to enable it each time when a tracing for specific process is enabled (with no success though) */ TRACE_EVENT (TraceEvent(_NTO_TRACE_ADDCLASS, traceClass)); /** * Enable trace class for the process of interest * The only TraceEvent() call within this routine that is definitely required. */ TRACE_EVENT (TraceEvent(_NTO_TRACE_SETCLASSPID, traceClass, pid)); /** * Specify trace mode (fast/wide) for this class. */ TRACE_EVENT (TraceEvent(traceMode, _NTO_TRACE_COMM)); return 0; } /** * Apply common set of kernel trace filters for the specified process */ static int applyFilters (pid_t pid) { // A list of trace classes to enable for specified PID const int traceClassList [] = { _NTO_TRACE_COMM, _NTO_TRACE_THREAD, _NTO_TRACE_SYSTEM, _NTO_TRACE_KERCALL }; const int traceMode = _NTO_TRACE_SETALLCLASSESWIDE; for (int i = 0; i < ARRAYLEN(traceClassList); ++i){ if (-1 == traceProcess (pid, traceClassList[i], traceMode)) { return -1; } } return 0; }