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 entry counting agent. This is
16 : // responsible for initializing the RPC connection and per-thread entry-count
17 : // buffer on demand as necessary as well as saturation incrementing the
18 : // appropriate 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 handle entry to a basic-block.
37 m : extern "C" void _cdecl _basic_block_enter();
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 entry counting agent.
50 : // @note: There's a single instance of this class.
51 m : class BasicBlockEntry {
52 m : public:
53 m : typedef ::common::IndexedFrequencyData IndexedFrequencyData;
54 m : typedef ::agent::common::ThreadStateManager ThreadStateManager;
55 :
56 : // This structure describes the contents of the stack above a call to
57 : // BasicBlockEntry::BasicBlockEntryHook. A pointer to this structure will
58 : // be given to the BasicBlockEntryHook by _basic_block_enter.
59 m : struct BasicBlockEntryFrame;
60 :
61 : // This structure describes the contents of the stack above a call to
62 : // BasicBlockEntry::DllMainEntryHook(). A pointer to this structure will
63 : // be given to the DllMainEntryHook by _indirect_penter_dllmain.
64 m : struct DllMainEntryFrame;
65 :
66 : // This structure describes the contents of the stack above a call to
67 : // BasicBlockEntry::ExeMainEntryHook(). A pointer to this structure will
68 : // be given to the ExeMainEntryHook by _indirect_penter_exemain.
69 m : struct ExeMainEntryFrame;
70 :
71 : // Retrieves the basic block entry singleton instance.
72 m : static BasicBlockEntry* Instance();
73 :
74 : // Returns a pointer to thread local frequency data. Used by the fast-path.
75 m : static uint32* WINAPI GetRawFrequencyData(IndexedFrequencyData* data);
76 :
77 : // Called from _basic_block_enter().
78 m : static void WINAPI BasicBlockEntryHook(BasicBlockEntryFrame* entry_frame);
79 :
80 : // Called from _indirect_penter_dllmain.
81 m : static void WINAPI DllMainEntryHook(DllMainEntryFrame* entry_frame);
82 :
83 : // Called from _indirect_penter_exemain.
84 m : static void WINAPI ExeMainEntryHook(ExeMainEntryFrame* entry_frame);
85 :
86 m : protected:
87 : // This class defines the per-thread-per-instrumented-module state managed
88 : // by this agent.
89 m : class ThreadState;
90 m : friend class ThreadState;
91 :
92 : // Make sure the LazyInstance can be created.
93 m : friend struct base::DefaultLazyInstanceTraits<BasicBlockEntry>;
94 :
95 m : BasicBlockEntry();
96 m : ~BasicBlockEntry();
97 :
98 : // Handles EXE startup on ExeMainEntryHook and DLL_PROCESS_ATTACH messages
99 : // received by DllMainEntryHook().
100 m : void OnProcessAttach(IndexedFrequencyData* module_data);
101 :
102 : // Handles DLL_THREAD_DETACH and DLL_PROCESS_DETACH messages received by
103 : // DllMainEntryHook().
104 m : void OnThreadDetach(IndexedFrequencyData* module_data);
105 :
106 : // Registers the module containing @p addr with the call_trace_service.
107 m : void RegisterModule(const void* addr);
108 :
109 : // Create the local thread state for the current thread. This should only
110 : // be called if the local thread state has not already been created.
111 m : ThreadState* CreateThreadState(IndexedFrequencyData* module_data);
112 :
113 : // The RPC session we're logging to/through.
114 m : trace::client::RpcSession session_;
115 :
116 : // A helper to manage the life-cycle of the ThreadState instances allocated
117 : // by this agent.
118 m : ThreadStateManager thread_state_manager_;
119 m : };
120 :
121 m : } // namespace basic_block_entry
122 m : } // namespace agent
123 :
124 : #endif // SYZYGY_AGENT_BASIC_BLOCK_ENTRY_BASIC_BLOCK_ENTRY_H_
|