1 : // Copyright 2012 Google Inc.
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 : // Implementation of the entry thunk instrumentation transform.
16 :
17 : #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
18 : #define SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
19 :
20 : #include <set>
21 : #include <string>
22 :
23 : #include "base/string_piece.h"
24 : #include "syzygy/block_graph/iterate.h"
25 : #include "syzygy/block_graph/transforms/iterative_transform.h"
26 : #include "syzygy/pe/pe_utils.h"
27 :
28 : namespace instrument {
29 : namespace transforms {
30 :
31 : class EntryThunkTransform
32 : : public block_graph::transforms::IterativeTransformImpl<
33 : EntryThunkTransform> {
34 : public:
35 : EntryThunkTransform();
36 :
37 : // @name Accessors.
38 : // @{
39 E : void set_instrument_unsafe_references(bool instrument) {
40 E : instrument_unsafe_references_ = instrument;
41 E : }
42 : bool instrument_unsafe_references() const {
43 : return instrument_unsafe_references_;
44 : }
45 :
46 E : void set_src_ranges_for_thunks(bool src_ranges_for_thunks) {
47 E : src_ranges_for_thunks_ = src_ranges_for_thunks;
48 E : }
49 : bool src_ranges_for_thunks() const {
50 : return src_ranges_for_thunks_;
51 : }
52 :
53 E : void set_only_instrument_module_entry(bool only_instrument_module_entry) {
54 E : only_instrument_module_entry_ = only_instrument_module_entry;
55 E : }
56 :
57 : bool only_instrument_module_entry() const {
58 : return only_instrument_module_entry_;
59 : }
60 :
61 E : void set_instrument_dll_name(const base::StringPiece& instrument_dll_name) {
62 E : instrument_dll_name.CopyToString(&instrument_dll_name_);
63 E : }
64 : const char* instrument_dll_name() const {
65 : return instrument_dll_name_.c_str();
66 : }
67 : // @}
68 :
69 : // The name of the import for general entry hooks.
70 : static const char kEntryHookName[];
71 : // The name of the import for DllMain-like function entry hooks.
72 : static const char kDllMainEntryHookName[];
73 : // The name of the import for EXE entry point hook.
74 : static const char kExeEntryHookName[];
75 :
76 : // The name of the DLL imported default.
77 : static const char kDefaultInstrumentDll[];
78 :
79 : protected:
80 : typedef block_graph::BlockGraph BlockGraph;
81 : typedef std::map<BlockGraph::Offset, BlockGraph::Block*> ThunkBlockMap;
82 : struct Thunk;
83 :
84 : // @name IterativeTransformImpl implementation.
85 : // @{
86 : bool PreBlockGraphIteration(
87 : BlockGraph* block_graph, BlockGraph::Block* header_block);
88 : bool OnBlock(BlockGraph* block_graph, BlockGraph::Block* block);
89 : // @}
90 :
91 : // Accessor.
92 : BlockGraph::Section* thunk_section() const { return thunk_section_; }
93 :
94 : // Instrument a single block.
95 : bool InstrumentCodeBlock(BlockGraph* block_graph, BlockGraph::Block* block);
96 :
97 : // Instruments a single referrer to a code block.
98 : bool InstrumentCodeBlockReferrer(const BlockGraph::Block::Referrer& referrer,
99 : BlockGraph* block_graph,
100 : BlockGraph::Block* block,
101 : ThunkBlockMap* thunk_block_map);
102 :
103 : // Create a single thunk to destination.
104 : // @param block_graph the block-graph being instrumented.
105 : // @param destination the destination reference.
106 : // @param hook a reference to the hook to use.
107 : BlockGraph::Block* CreateOneThunk(BlockGraph* block_graph,
108 : const BlockGraph::Reference& destination,
109 : const BlockGraph::Reference& hook);
110 :
111 : // Initializes the references in thunk_block, which must be an allocated
112 : // thunk of size sizeof(Thunk), containing data of the same size.
113 : static bool InitializeThunk(BlockGraph::Block* thunk_block,
114 : const BlockGraph::Reference& destination,
115 : const BlockGraph::Reference& import_entry);
116 :
117 : private:
118 : friend IterativeTransformImpl<EntryThunkTransform>;
119 : friend NamedBlockGraphTransformImpl<EntryThunkTransform>;
120 :
121 : bool GetEntryPoints(BlockGraph::Block* header_block);
122 :
123 : // For NamedBlockGraphTransformImpl.
124 : static const char kTransformName[];
125 :
126 : // The section we put our thunks in. Valid after successful
127 : // PreBlockGraphIteration.
128 : BlockGraph::Section* thunk_section_;
129 :
130 : // References to _indirect_penter and _indirect_penter_dllmain import
131 : // entries. Valid after successful PreBlockGraphIteration.
132 : BlockGraph::Reference hook_ref_;
133 : BlockGraph::Reference hook_dllmain_ref_;
134 : BlockGraph::Reference hook_exe_entry_ref_;
135 :
136 : // Iff true, instrument references with a non-zero offset into the
137 : // destination block.
138 : bool instrument_unsafe_references_;
139 :
140 : // Iff true, thunks will be adorned with a source range identifying them
141 : // with the function they address. This makes the output more debugging
142 : // friendly, at the cost of the uniqueness of address->name resolution.
143 : bool src_ranges_for_thunks_;
144 :
145 : // If true, only instrument DLL entry points.
146 : bool only_instrument_module_entry_;
147 :
148 : // Name of the instrumentation DLL we import.
149 : // Defaults to "call_trace_client.dll".
150 : std::string instrument_dll_name_;
151 :
152 : // This contains the set of entrypoints that have DllMain calling conventions.
153 : // These are thunked to the dllmain hook import, instead of the generic
154 : // hook import. Valid after successful call to GetEntryPoints.
155 : pe::EntryPointSet dllmain_entrypoints_;
156 : // If the module being instrumented is an executable, this will hold the
157 : // EXE main entry point. Valid after successful call to GetEntryPoints.
158 : pe::EntryPoint exe_entry_point_;
159 :
160 : static const Thunk kThunkTemplate;
161 :
162 : DISALLOW_COPY_AND_ASSIGN(EntryThunkTransform);
163 : };
164 :
165 : // This defines the memory layout for the thunks we create.
166 : #pragma pack(push)
167 : #pragma pack(1)
168 : struct EntryThunkTransform::Thunk {
169 : BYTE push;
170 : DWORD func_addr; // The real function to invoke.
171 : WORD jmp;
172 : DWORD hook_addr; // The instrumentation hook that gets called beforehand.
173 : };
174 : #pragma pack(pop)
175 :
176 : } // namespace transforms
177 : } // namespace instrument
178 :
179 : #endif // SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
|