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 : // Declaration of the entry thunk instrumentation transform. This instruments
16 : // module entry points (DLL and EXE) and individual functions with different
17 : // hook functions (provided to the transform). The details as to which
18 : // entry points and functions are hooked (and how) can be individually
19 : // controlled.
20 : //
21 : // A generic hook (without a parameter) redirects a call to a thunk of the
22 : // form:
23 : //
24 : // 0x68 0x44 0x33 0x22 0x11 push 0x11223344
25 : // 0xff 0x25 0x88 0x77 0x66 0x55 jmp [0x55667788]
26 : //
27 : // Where 0x11223344 is the address of the original function to be invoked,
28 : // and 0x55667788 is the address of the import pointing at the hook to be
29 : // invoked. The hook is responsible for cleaning up the stack with a 'ret' so
30 : // that 0x11223344 is popped, and control is transferred to the original
31 : // function.
32 : //
33 : // A parameterized hook redirects a call to a thunk of the form:
34 : //
35 : // 0x68 0xdd 0xcc 0xbb 0xaa push 0xaabbccdd ; must be a 32 bit value.
36 : // 0x68 0x44 0x33 0x22 0x11 push 0x11223344
37 : // 0xff 0x25 0x88 0x77 0x66 0x55 jmp [0x55667788]
38 : //
39 : // Where 0xaabbccdd is an additional immediate value, the semantics of which
40 : // are known to the hook function. The hook is responsible for cleaning up
41 : // the stack with a 'ret 4' so that both 0xaabbccdd and 0x11223344 are popped
42 : // and control is returned to the original function.
43 : //
44 : // Prior to executing the thunk the stack is set up as if the call was going to
45 : // be directly to the original function.
46 :
47 : #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
48 : #define SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
49 :
50 : #include <set>
51 : #include <string>
52 :
53 : #include "base/string_piece.h"
54 : #include "syzygy/block_graph/basic_block_assembler.h"
55 : #include "syzygy/block_graph/iterate.h"
56 : #include "syzygy/block_graph/transforms/iterative_transform.h"
57 : #include "syzygy/pe/pe_utils.h"
58 :
59 : namespace instrument {
60 : namespace transforms {
61 :
62 : class EntryThunkTransform
63 : : public block_graph::transforms::IterativeTransformImpl<
64 : EntryThunkTransform> {
65 : public:
66 : typedef block_graph::Immediate Immediate;
67 : typedef block_graph::BlockGraph BlockGraph;
68 :
69 : EntryThunkTransform();
70 :
71 : // @name Accessors.
72 : // @{
73 E : void set_instrument_unsafe_references(bool instrument) {
74 E : instrument_unsafe_references_ = instrument;
75 E : }
76 E : bool instrument_unsafe_references() const {
77 E : return instrument_unsafe_references_;
78 E : }
79 :
80 E : void set_src_ranges_for_thunks(bool src_ranges_for_thunks) {
81 E : src_ranges_for_thunks_ = src_ranges_for_thunks;
82 E : }
83 E : bool src_ranges_for_thunks() const {
84 E : return src_ranges_for_thunks_;
85 E : }
86 :
87 E : void set_only_instrument_module_entry(bool only_instrument_module_entry) {
88 E : only_instrument_module_entry_ = only_instrument_module_entry;
89 E : }
90 :
91 E : bool only_instrument_module_entry() const {
92 E : return only_instrument_module_entry_;
93 E : }
94 :
95 E : void set_instrument_dll_name(const base::StringPiece& instrument_dll_name) {
96 E : instrument_dll_name.CopyToString(&instrument_dll_name_);
97 E : }
98 : const char* instrument_dll_name() const {
99 : return instrument_dll_name_.c_str();
100 : }
101 :
102 E : const Immediate& entry_thunk_parameter() const {
103 E : return entry_thunk_parameter_;
104 E : }
105 E : const Immediate& function_thunk_parameter() const {
106 E : return function_thunk_parameter_;
107 E : }
108 :
109 E : BlockGraph::Section* thunk_section() const { return thunk_section_; }
110 : // @}
111 :
112 : // @{
113 : // Sets the parameter to be used by entry/function thunks. Only 32-bit
114 : // parameters may be used. Set to an invalid parameter (default constructed)
115 : // with a size of core::kSizeNone in order to disable parameterized thunks.
116 : // @param immediate the parameter to be used.
117 : // @returns true if the parameter was accepted, false otherwise.
118 : bool SetEntryThunkParameter(const Immediate& immediate);
119 : bool SetFunctionThunkParameter(const Immediate& immediate);
120 : // @}
121 :
122 : // @{
123 : // @returns true if the thunk type will be parameterized.
124 : bool EntryThunkIsParameterized() const;
125 : bool FunctionThunkIsParameterized() const;
126 : // @}
127 :
128 : // The name of the import for general entry hooks.
129 : static const char kEntryHookName[];
130 : // The name of the import for DllMain-like function entry hooks.
131 : static const char kDllMainEntryHookName[];
132 : // The name of the import for EXE entry point hook.
133 : static const char kExeMainEntryHookName[];
134 :
135 : // The name of the DLL imported default.
136 : static const char kDefaultInstrumentDll[];
137 :
138 : protected:
139 : typedef std::map<BlockGraph::Offset, BlockGraph::Block*> ThunkBlockMap;
140 :
141 : // @name IterativeTransformImpl implementation.
142 : // @{
143 : bool PreBlockGraphIteration(
144 : BlockGraph* block_graph, BlockGraph::Block* header_block);
145 : bool OnBlock(BlockGraph* block_graph, BlockGraph::Block* block);
146 : // @}
147 :
148 : // Instrument a single block.
149 : bool InstrumentCodeBlock(BlockGraph* block_graph, BlockGraph::Block* block);
150 :
151 : // Instruments a single referrer to a code block.
152 : bool InstrumentCodeBlockReferrer(const BlockGraph::Block::Referrer& referrer,
153 : BlockGraph* block_graph,
154 : BlockGraph::Block* block,
155 : ThunkBlockMap* thunk_block_map);
156 :
157 : // Create a single thunk to destination.
158 : // @param block_graph the block-graph being instrumented.
159 : // @param destination the destination reference.
160 : // @param hook a reference to the hook to use.
161 : // @param parameter the parameter to be passed to the thunk. If this is NULL
162 : // then an unparameterized thunk will be created.
163 : BlockGraph::Block* CreateOneThunk(BlockGraph* block_graph,
164 : const BlockGraph::Reference& destination,
165 : const BlockGraph::Reference& hook,
166 : const Immediate* parameter);
167 :
168 : private:
169 : friend IterativeTransformImpl<EntryThunkTransform>;
170 : friend NamedBlockGraphTransformImpl<EntryThunkTransform>;
171 :
172 : bool GetEntryPoints(BlockGraph::Block* header_block);
173 :
174 : // For NamedBlockGraphTransformImpl.
175 : static const char kTransformName[];
176 :
177 : // The section we put our thunks in. Valid after successful
178 : // PreBlockGraphIteration.
179 : BlockGraph::Section* thunk_section_;
180 :
181 : // References to _indirect_penter and _indirect_penter_dllmain import
182 : // entries. Valid after successful PreBlockGraphIteration.
183 : BlockGraph::Reference hook_ref_;
184 : BlockGraph::Reference hook_dllmain_ref_;
185 : BlockGraph::Reference hook_exe_entry_ref_;
186 :
187 : // Iff true, instrument references with a non-zero offset into the
188 : // destination block.
189 : bool instrument_unsafe_references_;
190 :
191 : // Iff true, thunks will be adorned with a source range identifying them
192 : // with the function they address. This makes the output more debugging
193 : // friendly, at the cost of the uniqueness of address->name resolution.
194 : bool src_ranges_for_thunks_;
195 :
196 : // If true, only instrument DLL entry points.
197 : bool only_instrument_module_entry_;
198 :
199 : // If has a size of 32 bits, then entry thunks will be set up with an extra
200 : // parameter on the stack prior to the address of the original function.
201 : Immediate entry_thunk_parameter_;
202 :
203 : // If has a size of 32 bits, then function hook thunks will be set up with an
204 : // extra parameter on the stack prior to the address of the original function.
205 : Immediate function_thunk_parameter_;
206 :
207 : // Name of the instrumentation DLL we import.
208 : // Defaults to "call_trace_client.dll".
209 : std::string instrument_dll_name_;
210 :
211 : // This contains the set of entrypoints that have DllMain calling conventions.
212 : // These are thunked to the dllmain hook import, instead of the generic
213 : // hook import. Valid after successful call to GetEntryPoints.
214 : pe::EntryPointSet dllmain_entrypoints_;
215 : // If the module being instrumented is an executable, this will hold the
216 : // EXE main entry point. Valid after successful call to GetEntryPoints.
217 : pe::EntryPoint exe_entry_point_;
218 :
219 : DISALLOW_COPY_AND_ASSIGN(EntryThunkTransform);
220 : };
221 :
222 : } // namespace transforms
223 : } // namespace instrument
224 :
225 : #endif // SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
|