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/strings/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::BasicBlockAssembler::Immediate ImmediateType;
67 : typedef block_graph::BlockGraph BlockGraph;
68 : typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
69 :
70 : EntryThunkTransform();
71 :
72 : // @name Accessors.
73 : // @{
74 E : void set_instrument_unsafe_references(bool instrument) {
75 E : instrument_unsafe_references_ = instrument;
76 E : }
77 E : bool instrument_unsafe_references() const {
78 E : return instrument_unsafe_references_;
79 E : }
80 :
81 E : void set_src_ranges_for_thunks(bool src_ranges_for_thunks) {
82 E : src_ranges_for_thunks_ = src_ranges_for_thunks;
83 E : }
84 E : bool src_ranges_for_thunks() const {
85 E : return src_ranges_for_thunks_;
86 E : }
87 :
88 E : void set_only_instrument_module_entry(bool only_instrument_module_entry) {
89 E : only_instrument_module_entry_ = only_instrument_module_entry;
90 E : }
91 :
92 E : bool only_instrument_module_entry() const {
93 E : return only_instrument_module_entry_;
94 E : }
95 :
96 E : void set_instrument_dll_name(const base::StringPiece& instrument_dll_name) {
97 E : instrument_dll_name.CopyToString(&instrument_dll_name_);
98 E : }
99 : const char* instrument_dll_name() const {
100 : return instrument_dll_name_.c_str();
101 : }
102 :
103 E : const ImmediateType& entry_thunk_parameter() const {
104 E : return entry_thunk_parameter_;
105 E : }
106 E : const ImmediateType& function_thunk_parameter() const {
107 E : return function_thunk_parameter_;
108 E : }
109 :
110 E : BlockGraph::Section* thunk_section() const { return thunk_section_; }
111 : // @}
112 :
113 : // @{
114 : // Sets the parameter to be used by entry/function thunks. Only 32-bit
115 : // parameters may be used. Set to an invalid parameter (default constructed)
116 : // with a size of core::kSizeNone in order to disable parameterized thunks.
117 : // @param ImmediateType the parameter to be used.
118 : // @returns true if the parameter was accepted, false otherwise.
119 : bool SetEntryThunkParameter(const ImmediateType& ImmediateType);
120 : bool SetFunctionThunkParameter(const ImmediateType& ImmediateType);
121 : // @}
122 :
123 : // @{
124 : // @returns true if the thunk type will be parameterized.
125 : bool EntryThunkIsParameterized() const;
126 : bool FunctionThunkIsParameterized() const;
127 : // @}
128 :
129 : // The name of the import for general entry hooks.
130 : static const char kEntryHookName[];
131 : // The name of the import for DllMain-like function entry hooks.
132 : static const char kDllMainEntryHookName[];
133 : // The name of the import for EXE entry point hook.
134 : static const char kExeMainEntryHookName[];
135 :
136 : // The name of the DLL imported default.
137 : static const char kDefaultInstrumentDll[];
138 :
139 : protected:
140 : typedef std::map<BlockGraph::Offset, BlockGraph::Block*> ThunkBlockMap;
141 :
142 : // @name IterativeTransformImpl implementation.
143 : // @{
144 : bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
145 : BlockGraph* block_graph,
146 : BlockGraph::Block* header_block);
147 : bool OnBlock(const TransformPolicyInterface* policy,
148 : BlockGraph* block_graph,
149 : BlockGraph::Block* block);
150 : // @}
151 :
152 : // Instrument a single block.
153 : bool InstrumentCodeBlock(BlockGraph* block_graph, BlockGraph::Block* block);
154 :
155 : // Instruments a single referrer to a code block.
156 : bool InstrumentCodeBlockReferrer(const BlockGraph::Block::Referrer& referrer,
157 : BlockGraph* block_graph,
158 : BlockGraph::Block* block,
159 : ThunkBlockMap* thunk_block_map);
160 :
161 : // Create a single thunk to destination.
162 : // @param block_graph the block-graph being instrumented.
163 : // @param destination the destination reference.
164 : // @param hook a reference to the hook to use.
165 : // @param parameter the parameter to be passed to the thunk. If this is NULL
166 : // then an unparameterized thunk will be created.
167 : BlockGraph::Block* CreateOneThunk(BlockGraph* block_graph,
168 : const BlockGraph::Reference& destination,
169 : const BlockGraph::Reference& hook,
170 : const ImmediateType* parameter);
171 :
172 : private:
173 : friend IterativeTransformImpl<EntryThunkTransform>;
174 : friend NamedBlockGraphTransformImpl<EntryThunkTransform>;
175 :
176 : bool GetEntryPoints(BlockGraph::Block* header_block);
177 :
178 : // For NamedBlockGraphTransformImpl.
179 : static const char kTransformName[];
180 :
181 : // The section we put our thunks in. Valid after successful
182 : // PreBlockGraphIteration.
183 : BlockGraph::Section* thunk_section_;
184 :
185 : // References to _indirect_penter and _indirect_penter_dllmain import
186 : // entries. Valid after successful PreBlockGraphIteration.
187 : BlockGraph::Reference hook_ref_;
188 : BlockGraph::Reference hook_dllmain_ref_;
189 : BlockGraph::Reference hook_exe_entry_ref_;
190 :
191 : // Iff true, instrument references with a non-zero offset into the
192 : // destination block.
193 : bool instrument_unsafe_references_;
194 :
195 : // Iff true, thunks will be adorned with a source range identifying them
196 : // with the function they address. This makes the output more debugging
197 : // friendly, at the cost of the uniqueness of address->name resolution.
198 : bool src_ranges_for_thunks_;
199 :
200 : // If true, only instrument DLL entry points.
201 : bool only_instrument_module_entry_;
202 :
203 : // If has a size of 32 bits, then entry thunks will be set up with an extra
204 : // parameter on the stack prior to the address of the original function.
205 : ImmediateType entry_thunk_parameter_;
206 :
207 : // If has a size of 32 bits, then function hook thunks will be set up with an
208 : // extra parameter on the stack prior to the address of the original function.
209 : ImmediateType function_thunk_parameter_;
210 :
211 : // Name of the instrumentation DLL we import.
212 : // Defaults to "call_trace_client.dll".
213 : std::string instrument_dll_name_;
214 :
215 : // This contains the set of entrypoints that have DllMain calling conventions.
216 : // These are thunked to the dllmain hook import, instead of the generic
217 : // hook import. Valid after successful call to GetEntryPoints.
218 : pe::EntryPointSet dllmain_entrypoints_;
219 : // If the module being instrumented is an executable, this will hold the
220 : // EXE main entry point. Valid after successful call to GetEntryPoints.
221 : pe::EntryPoint exe_entry_point_;
222 :
223 : DISALLOW_COPY_AND_ASSIGN(EntryThunkTransform);
224 : };
225 :
226 : } // namespace transforms
227 : } // namespace instrument
228 :
229 : #endif // SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
|