1 : // Copyright 2012 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 : // The runtime portion of a basic-block counting agent. This is responsible for
16 : // initializing the RPC connection and per-thread indexed-data-count buffer on
17 : // demand as necessary as well as saturation incrementing the appropriate
18 : // counter when requested.
19 : //
20 : // The instrumenter can be used to inject a run-time dependency on this
21 : // library as well as to add the appropriate entry-hook code.
22 :
23 : #ifndef SYZYGY_AGENT_BASIC_BLOCK_ENTRY_BASIC_BLOCK_ENTRY_H_
24 : #define SYZYGY_AGENT_BASIC_BLOCK_ENTRY_BASIC_BLOCK_ENTRY_H_
25 :
26 : #include <windows.h>
27 : #include <winnt.h>
28 : #include <vector>
29 :
30 : #include "base/lazy_instance.h"
31 : #include "base/win/pe_image.h"
32 : #include "syzygy/agent/common/thread_state.h"
33 : #include "syzygy/common/indexed_frequency_data.h"
34 : #include "syzygy/trace/client/rpc_session.h"
35 :
36 : // Instrumentation stub to increment an indexed frequency data counter.
37 m : extern "C" void _cdecl _increment_indexed_freq_data();
38 :
39 : // Instrumentation stub to handle the invocation of a DllMain-like entry point.
40 m : extern "C" void _cdecl _indirect_penter_dllmain();
41 :
42 : // Instrumentation stub to handle a request for a pointer to frequency data.
43 m : extern "C" uint32* _stdcall _get_raw_frequency_data(
44 m : ::common::IndexedFrequencyData* data);
45 :
46 m : namespace agent {
47 m : namespace basic_block_entry {
48 :
49 : // The basic-block counting agent.
50 : // @note: There's a single instance of this class.
51 : // TODO(sebmarchand): Rename this class to BasicBlockAgent (or something
52 : // similar) as this is used by various modes of instrumentation (basic block
53 : // entry counting, basic block arc counts, jump table entry counts, etc).
54 m : class BasicBlockEntry {
55 m : public:
56 m : typedef ::common::IndexedFrequencyData IndexedFrequencyData;
57 m : typedef ::agent::common::ThreadStateManager ThreadStateManager;
58 :
59 : // This structure describes the contents of the stack above a call to
60 : // BasicBlockEntry::IncrementIndexedFreqDataHook. A pointer to this structure
61 : // will be given to the IncrementIndexedFreqDataHook by
62 : // _increment_indexed_freq_data.
63 m : struct IncrementIndexedFreqDataFrame;
64 :
65 : // This structure describes the contents of the stack above a call to
66 : // BasicBlockEntry::DllMainEntryHook(). A pointer to this structure will
67 : // be given to the DllMainEntryHook by _indirect_penter_dllmain.
68 m : struct DllMainEntryFrame;
69 :
70 : // This structure describes the contents of the stack above a call to
71 : // BasicBlockEntry::ExeMainEntryHook(). A pointer to this structure will
72 : // be given to the ExeMainEntryHook by _indirect_penter_exemain.
73 m : struct ExeMainEntryFrame;
74 :
75 : // Retrieves the basic block entry singleton instance.
76 m : static BasicBlockEntry* Instance();
77 :
78 : // Returns a pointer to thread local frequency data. Used by the fast-path.
79 m : static uint32* WINAPI GetRawFrequencyData(IndexedFrequencyData* data);
80 :
81 : // Called from _increment_indexed_freq_data().
82 m : static void WINAPI IncrementIndexedFreqDataHook(
83 m : IncrementIndexedFreqDataFrame* entry_frame);
84 :
85 : // Called from _indirect_penter_dllmain.
86 m : static void WINAPI DllMainEntryHook(DllMainEntryFrame* entry_frame);
87 :
88 : // Called from _indirect_penter_exemain.
89 m : static void WINAPI ExeMainEntryHook(ExeMainEntryFrame* entry_frame);
90 :
91 m : protected:
92 : // This class defines the per-thread-per-instrumented-module state managed
93 : // by this agent.
94 m : class ThreadState;
95 m : friend class ThreadState;
96 :
97 : // Make sure the LazyInstance can be created.
98 m : friend struct base::DefaultLazyInstanceTraits<BasicBlockEntry>;
99 :
100 m : BasicBlockEntry();
101 m : ~BasicBlockEntry();
102 :
103 : // Handles EXE startup on ExeMainEntryHook and DLL_PROCESS_ATTACH messages
104 : // received by DllMainEntryHook().
105 m : void OnProcessAttach(IndexedFrequencyData* module_data);
106 :
107 : // Handles DLL_THREAD_DETACH and DLL_PROCESS_DETACH messages received by
108 : // DllMainEntryHook().
109 m : void OnThreadDetach(IndexedFrequencyData* module_data);
110 :
111 : // Registers the module containing @p addr with the call_trace_service.
112 m : void RegisterModule(const void* addr);
113 :
114 : // Create the local thread state for the current thread. This should only
115 : // be called if the local thread state has not already been created.
116 m : ThreadState* CreateThreadState(IndexedFrequencyData* module_data);
117 :
118 : // The RPC session we're logging to/through.
119 m : trace::client::RpcSession session_;
120 :
121 : // A helper to manage the life-cycle of the ThreadState instances allocated
122 : // by this agent.
123 m : ThreadStateManager thread_state_manager_;
124 m : };
125 :
126 m : } // namespace basic_block_entry
127 m : } // namespace agent
128 :
129 : #endif // SYZYGY_AGENT_BASIC_BLOCK_ENTRY_BASIC_BLOCK_ENTRY_H_
|