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/time.h"
24 : #include "base/files/file_path.h"
25 : #include "syzygy/common/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
32 : // base::win::SamplingProfiler instance to every module of interest. The output
33 : // is then shuttled to trace data files.
34 : class SamplerApp : public common::AppImplBase {
35 : public:
36 : SamplerApp();
37 : ~SamplerApp();
38 :
39 : // @name Implementation of the AppImplbase interface.
40 : // @{
41 : bool ParseCommandLine(const CommandLine* command_line);
42 : int Run();
43 : // @}
44 :
45 : // @name Command-line switches.
46 : // @{
47 : static const char kBlacklistPids[];
48 : static const char kBucketSize[];
49 : static const char kPids[];
50 : static const char kSamplingInterval[];
51 : static const char kOutputDir[];
52 : // @}
53 :
54 : // @name Default command-line values.
55 : // @{
56 : static const size_t kDefaultLog2BucketSize;
57 : // @}
58 :
59 : // These are exposed for use by anonymous helper functions.
60 : struct ModuleSignature;
61 : typedef std::set<ModuleSignature> ModuleSignatureSet;
62 :
63 : protected:
64 : // Inner implementation of Run().
65 : int RunImpl();
66 :
67 : // @name Unittesting seams.
68 : // @{
69 i : virtual void OnStartProfiling(const SampledModuleCache::Module* module) { }
70 i : virtual void OnStopProfiling(const SampledModuleCache::Module* module) { }
71 : // @}
72 :
73 : // Helper function for printing a usage statement.
74 : // @param program The path to the executable.
75 : // @param message An optional message that will precede the usage statement.
76 : // @returns false.
77 : bool PrintUsage(const base::FilePath& program,
78 : const base::StringPiece& message);
79 :
80 : // Parses a comma-separated list of PIDs (non-negative integers) and
81 : // populates pids_.
82 : // @param pids A comma-separated list of PIDs.
83 : // @returns true on success, false otherwise.
84 : bool ParsePids(const std::string& pids);
85 :
86 : // The callback that is invoked for modules once we have finished profiling
87 : // them.
88 : // @param module The module that has just finished profiling.
89 : void OnDeadModule(const SampledModuleCache::Module* module);
90 :
91 : // Initializes a ModuleSignature given a path. Logs an error on failure.
92 : // @param module The path to the module.
93 : // @param sig The signature object to be initialized.
94 : // @returns true on success, false otherwise.
95 : static bool GetModuleSignature(
96 : const base::FilePath& module, ModuleSignature* sig);
97 :
98 : // Used for handling console messages.
99 : // @param ctrl_type The type of the console control message.
100 : // @returns TRUE if the signal was handled, FALSE otherwise.
101 : static BOOL WINAPI OnConsoleCtrl(DWORD ctrl_type);
102 :
103 : // @name Accessors/mutators for running_.
104 : // @{
105 : bool running();
106 : void set_running(bool running);
107 : // @}
108 :
109 : // Used for storing a set of PIDs. This plays the role of a whitelist or a
110 : // blacklist for selecting processes of interest.
111 : typedef std::set<DWORD> PidSet;
112 : PidSet pids_;
113 :
114 : // If this is true then the PidSet plays the role of a blacklist. If false it
115 : // is a whitelist.
116 : bool blacklist_pids_;
117 :
118 : // Sampling profiler parameters.
119 : size_t log2_bucket_size_;
120 : base::TimeDelta sampling_interval_;
121 :
122 : // The output directory where trace files will be written.
123 : base::FilePath output_dir_;
124 :
125 : // List of modules of interest. Any instances of these modules that are
126 : // loaded in processes of interest (those that get through our process
127 : // filter) will be profiled.
128 : ModuleSignatureSet module_sigs_;
129 :
130 : // Used to indicate whether or not the sampler should continue running.
131 : base::Lock lock_;
132 : bool running_; // Under lock.
133 :
134 : // @name Internal state and calculations.
135 : // @{
136 : uint64 sampling_interval_in_cycles_;
137 : // @}
138 :
139 : // Only one instance of this class can register for console control messages,
140 : // on a first-come first-serve basis.
141 : static base::Lock console_ctrl_lock_;
142 : static SamplerApp* console_ctrl_owner_; // Under console_ctrl_lock_.
143 : };
144 :
145 : // Used for storing a bare minimum signature of a module.
146 : struct SamplerApp::ModuleSignature {
147 : uint32 size;
148 : uint32 time_date_stamp;
149 : uint32 checksum;
150 :
151 : // Comparison operator
152 : bool operator<(const ModuleSignature& rhs) const;
153 : };
154 :
155 : } // namespace sampler
156 :
157 : #endif // SYZYGY_SAMPLER_SAMPLER_APP_H_
|