1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares the Sampler applications. This is an application for sampling
16 : // profiling modules. It can profile multiple uninstrumented modules across
17 : // multiple processes.
18 : #ifndef SYZYGY_SAMPLER_SAMPLER_APP_H_
19 : #define SYZYGY_SAMPLER_SAMPLER_APP_H_
20 :
21 : #include <set>
22 :
23 : #include "base/files/file_path.h"
24 : #include "base/time/time.h"
25 : #include "syzygy/application/application.h"
26 : #include "syzygy/sampler/sampled_module_cache.h"
27 :
28 : namespace sampler {
29 :
30 : // The application class that takes care of running a profiling sampler. This
31 : // works by polling running processes and attaching a SamplingProfiler instance
32 : // to every module of interest. The output is then shuttled to trace data files.
33 : class SamplerApp : public application::AppImplBase {
34 : public:
35 : SamplerApp();
36 : ~SamplerApp();
37 :
38 : // @name Implementation of the AppImplbase interface.
39 : // @{
40 : bool ParseCommandLine(const CommandLine* command_line);
41 : int Run();
42 : // @}
43 :
44 : // @name Command-line switches.
45 : // @{
46 : static const char kBlacklistPids[];
47 : static const char kBucketSize[];
48 : static const char kPids[];
49 : static const char kSamplingInterval[];
50 : static const char kOutputDir[];
51 : // @}
52 :
53 : // @name Default command-line values.
54 : // @{
55 : static const size_t kDefaultLog2BucketSize;
56 : // @}
57 :
58 : // These are exposed for use by anonymous helper functions.
59 : struct ModuleSignature;
60 : typedef std::set<ModuleSignature> ModuleSignatureSet;
61 :
62 : protected:
63 : // Inner implementation of Run().
64 : int RunImpl();
65 :
66 : // @name Unittesting seams.
67 : // @{
68 i : virtual void OnStartProfiling(const SampledModuleCache::Module* module) { }
69 i : virtual void OnStopProfiling(const SampledModuleCache::Module* module) { }
70 : // @}
71 :
72 : // Helper function for printing a usage statement.
73 : // @param program The path to the executable.
74 : // @param message An optional message that will precede the usage statement.
75 : // @returns false.
76 : bool PrintUsage(const base::FilePath& program,
77 : const base::StringPiece& message);
78 :
79 : // Parses a comma-separated list of PIDs (non-negative integers) and
80 : // populates pids_.
81 : // @param pids A comma-separated list of PIDs.
82 : // @returns true on success, false otherwise.
83 : bool ParsePids(const std::string& pids);
84 :
85 : // The callback that is invoked for modules once we have finished profiling
86 : // them.
87 : // @param module The module that has just finished profiling.
88 : void OnDeadModule(const SampledModuleCache::Module* module);
89 :
90 : // Initializes a ModuleSignature given a path. Logs an error on failure.
91 : // @param module The path to the module.
92 : // @param sig The signature object to be initialized.
93 : // @returns true on success, false otherwise.
94 : static bool GetModuleSignature(
95 : const base::FilePath& module, ModuleSignature* sig);
96 :
97 : // Used for handling console messages.
98 : // @param ctrl_type The type of the console control message.
99 : // @returns TRUE if the signal was handled, FALSE otherwise.
100 : static BOOL WINAPI OnConsoleCtrl(DWORD ctrl_type);
101 :
102 : // @name Accessors/mutators for running_.
103 : // @{
104 : bool running();
105 : void set_running(bool running);
106 : // @}
107 :
108 : // Used for storing a set of PIDs. This plays the role of a whitelist or a
109 : // blacklist for selecting processes of interest.
110 : typedef std::set<DWORD> PidSet;
111 : PidSet pids_;
112 :
113 : // If this is true then the PidSet plays the role of a blacklist. If false it
114 : // is a whitelist.
115 : bool blacklist_pids_;
116 :
117 : // Sampling profiler parameters.
118 : size_t log2_bucket_size_;
119 : base::TimeDelta sampling_interval_;
120 :
121 : // The output directory where trace files will be written.
122 : base::FilePath output_dir_;
123 :
124 : // List of modules of interest. Any instances of these modules that are
125 : // loaded in processes of interest (those that get through our process
126 : // filter) will be profiled.
127 : ModuleSignatureSet module_sigs_;
128 :
129 : // Used to indicate whether or not the sampler should continue running.
130 : base::Lock lock_;
131 : bool running_; // Under lock.
132 :
133 : // @name Internal state and calculations.
134 : // @{
135 : uint64 sampling_interval_in_cycles_;
136 : // @}
137 :
138 : // Only one instance of this class can register for console control messages,
139 : // on a first-come first-serve basis.
140 : static base::Lock console_ctrl_lock_;
141 : static SamplerApp* console_ctrl_owner_; // Under console_ctrl_lock_.
142 : };
143 :
144 : // Used for storing a bare minimum signature of a module.
145 : struct SamplerApp::ModuleSignature {
146 : uint32 size;
147 : uint32 time_date_stamp;
148 : uint32 checksum;
149 :
150 : // Comparison operator
151 : bool operator<(const ModuleSignature& rhs) const;
152 : };
153 :
154 : } // namespace sampler
155 :
156 : #endif // SYZYGY_SAMPLER_SAMPLER_APP_H_
|