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 : // This file declares the Call Trace "Client" class, which is responsible
16 : // for providing all of the Call Trace DLL functionality.
17 :
18 : #ifndef SYZYGY_AGENT_CALL_TRACE_CLIENT_RPC_H_
19 : #define SYZYGY_AGENT_CALL_TRACE_CLIENT_RPC_H_
20 :
21 : #include <map>
22 : #include <utility>
23 : #include <vector>
24 :
25 : #include "base/synchronization/lock.h"
26 : #include "base/threading/thread_local.h"
27 : #include "syzygy/agent/common/entry_frame.h"
28 : #include "syzygy/trace/client/rpc_session.h"
29 :
30 : // Assembly instrumentation stubs to handle function entry and exit. These
31 : // respectively invoke Client::FunctionEntryHook, Client::DllMainEntryHook,
32 : // Client::FunctionExitHook and Client::DllMainExitHook.
33 m : extern "C" void _cdecl _indirect_penter();
34 m : extern "C" void _cdecl _indirect_penter_dllmain();
35 :
36 m : namespace agent {
37 m : namespace client {
38 :
39 m : class Client {
40 m : public:
41 m : Client();
42 m : ~Client();
43 :
44 m : static Client* Instance();
45 :
46 m : BOOL WINAPI DllMain(HMODULE module, DWORD reason, LPVOID reserved);
47 :
48 m : protected:
49 m : typedef agent::EntryFrame EntryFrame;
50 m : friend void _indirect_penter();
51 m : friend void _indirect_penter_dll_main();
52 :
53 : // Invoked by _indirect_penter_dllmain on entry to a DLL's entry point.
54 : //
55 : // This function will initialize a call trace session if none currently
56 : // exists and will transmit module information to the call trace service.
57 : // It will then log the entry into the DLL's entry point.
58 : //
59 : // @param entry_frame The entry frame for the module entry point
60 : // @param function The module entry point
61 m : static void WINAPI DllMainEntryHook(EntryFrame* entry_frame,
62 m : FuncAddr function);
63 :
64 : // Invoked by _indirect_penter on function entry.
65 : //
66 : // @param entry_frame The entry frame for the called function.
67 : // @param function The called function.
68 m : static void WINAPI FunctionEntryHook(EntryFrame* entry_frame,
69 m : FuncAddr function);
70 :
71 m : private:
72 : // We keep a structure of this type for each thread.
73 m : class ThreadLocalData;
74 :
75 : // The functions we use to manage the thread local data.
76 m : ThreadLocalData* GetThreadData();
77 m : ThreadLocalData* GetOrAllocateThreadData();
78 m : void FreeThreadData(ThreadLocalData* data);
79 m : void FreeThreadData();
80 :
81 : // DllMain Handler functions. We only handle detach events in DllMain, the
82 : // attachment events are deferred to the first use of an event hook. This
83 : // is an attempt to avoid running afoul of the module loader lock and/or
84 : // load order problems. Further, we don't need/want to handle attachment
85 : // events for non-instrumented modules, anyway.
86 m : void OnClientProcessDetach();
87 m : void OnClientThreadDetach();
88 :
89 : // This function will initialize a call trace session if none currently
90 : // exists and the event is DLL_PROCESS_ATTACH. It will then transmit a
91 : // module event record to the call trace service.
92 : //
93 : // @param data the thread local data describing this threads call trace
94 : // log buffer.
95 : // @param entry_frame the entry frame for the module entry point
96 : // @param function the module entry point
97 m : void LogEvent_ModuleEvent(ThreadLocalData *data,
98 m : HMODULE module,
99 m : DWORD reason);
100 :
101 : // Called by FunctionEntryHook and DllMainEntryHook.
102 : //
103 : // This function will log the entry into the given function.
104 : //
105 : // If module is not NULL and reason is either DLL_THREAD_ATTACH or
106 : // DLL_PROCESS_ATTACH, the function first logs the module event before
107 : // logging the function entry.
108 : //
109 : // @param entry_frame The entry frame for the called function.
110 : // @param function The called function.
111 : // @param module NULL unless the entry denotes an instrumented dll's entry
112 : // point being called.
113 : // @param reason If module is NULL this is ignored; otherwise, it must be
114 : // DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH or
115 : // DLL_THREAD_DETACH.
116 m : void LogEvent_FunctionEntry(EntryFrame* entry_frame,
117 m : FuncAddr function,
118 m : HMODULE module,
119 m : DWORD reason);
120 :
121 : // The initialization lock.
122 m : base::Lock init_lock_;
123 :
124 : // Our RPC session state.
125 m : trace::client::RpcSession session_;
126 :
127 : // This points to our per-thread state.
128 m : mutable base::ThreadLocalPointer<ThreadLocalData> tls_;
129 m : };
130 :
131 m : } // namespace client
132 m : } // namespace agent
133 :
134 : #endif // SYZYGY_AGENT_CALL_TRACE_CLIENT_RPC_H_
|