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