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 : // Implementation of the SyzyAsan instrumentation transform.
16 :
17 : #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_ASAN_TRANSFORM_H_
18 : #define SYZYGY_INSTRUMENT_TRANSFORMS_ASAN_TRANSFORM_H_
19 :
20 : #include <map>
21 : #include <set>
22 : #include <string>
23 : #include <utility>
24 :
25 : #include "base/string_piece.h"
26 : #include "syzygy/block_graph/filterable.h"
27 : #include "syzygy/block_graph/iterate.h"
28 : #include "syzygy/block_graph/analysis/liveness_analysis.h"
29 : #include "syzygy/block_graph/analysis/memory_access_analysis.h"
30 : #include "syzygy/block_graph/transforms/iterative_transform.h"
31 : #include "syzygy/block_graph/transforms/named_transform.h"
32 :
33 : namespace instrument {
34 : namespace transforms {
35 :
36 : // This class implements the transformation applied to each basic block.
37 : class AsanBasicBlockTransform
38 : : public block_graph::transforms::NamedBasicBlockSubGraphTransformImpl<
39 : AsanBasicBlockTransform>,
40 : public block_graph::Filterable {
41 : public:
42 : // Represent the different kind of access to the memory.
43 : enum MemoryAccessMode {
44 : kNoAccess,
45 : kReadAccess,
46 : kWriteAccess,
47 : kInstrAccess,
48 : kRepzAccess,
49 : kRepnzAccess,
50 : };
51 :
52 : enum StackAccessMode {
53 : kUnsafeStackAccess,
54 : kSafeStackAccess,
55 : };
56 :
57 : // Contains memory access information.
58 : struct MemoryAccessInfo {
59 : MemoryAccessMode mode;
60 : uint8_t size;
61 : uint16_t opcode;
62 : // True iff we need to save the flags for this access.
63 : bool save_flags;
64 : };
65 :
66 : typedef block_graph::BlockGraph BlockGraph;
67 : typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
68 : typedef MemoryAccessInfo AsanHookMapEntryKey;
69 : // Map of hooks to asan check access functions.
70 : typedef std::map<AsanHookMapEntryKey, BlockGraph::Reference> AsanHookMap;
71 : typedef std::map<MemoryAccessMode, BlockGraph::Reference> AsanDefaultHookMap;
72 :
73 : // Constructor.
74 : // @param hooks_read_access a reference to the read access check import entry.
75 : // @param hooks_write_access a reference to the write access check import
76 : // entry.
77 : explicit AsanBasicBlockTransform(AsanHookMap* check_access_hooks) :
78 : check_access_hooks_(check_access_hooks),
79 : debug_friendly_(false),
80 : use_liveness_analysis_(false),
81 E : remove_redundant_checks_(false) {
82 E : DCHECK(check_access_hooks != NULL);
83 E : }
84 :
85 : // @name Accessors.
86 : // @{
87 : bool debug_friendly() const { return debug_friendly_; }
88 E : void set_debug_friendly(bool flag) { debug_friendly_ = flag; }
89 :
90 E : bool use_liveness_analysis() { return use_liveness_analysis_; }
91 E : void set_use_liveness_analysis(bool use_liveness_analysis) {
92 E : use_liveness_analysis_ = use_liveness_analysis;
93 E : }
94 :
95 E : bool remove_redundant_checks() const { return remove_redundant_checks_; }
96 E : void set_remove_redundant_checks(bool remove_redundant_checks) {
97 E : remove_redundant_checks_ = remove_redundant_checks;
98 E : }
99 :
100 : // @}
101 :
102 : // The transform name.
103 : static const char kTransformName[];
104 :
105 : protected:
106 : // @name BasicBlockSubGraphTransformInterface method.
107 : virtual bool TransformBasicBlockSubGraph(
108 : BlockGraph* block_graph,
109 : BasicBlockSubGraph* basic_block_subgraph) OVERRIDE;
110 :
111 : // Instruments the memory accesses in a basic block.
112 : // @param basic_block The basic block to be instrumented.
113 : // @param stack_mode Give some assumptions to the transformation on stack
114 : // frame manipulations inside @p basic_block. The transformation assume a
115 : // standard calling convention, unless specified by this parameter.
116 : // (note: Unsafe blocks may be produced with the compiler flag
117 : // frame-pointer-omission).
118 : // @returns true on success, false otherwise.
119 : bool InstrumentBasicBlock(block_graph::BasicCodeBlock* basic_block,
120 : StackAccessMode stack_mode);
121 :
122 : private:
123 : // Liveness analysis and liveness information for this subgraph.
124 : block_graph::analysis::LivenessAnalysis liveness_;
125 :
126 : // Memory accesses value numbering.
127 : block_graph::analysis::MemoryAccessAnalysis memory_accesses_;
128 :
129 : // The references to the Asan access check import entries.
130 : AsanHookMap* check_access_hooks_;
131 :
132 : // Activate the overwriting of source range for created instructions.
133 : bool debug_friendly_;
134 :
135 : // Set iff we should use the liveness analysis to do smarter instrumentation.
136 : bool use_liveness_analysis_;
137 :
138 : // When activated, a redundancy elimination is performed to minimize the
139 : // memory checks added by this transform.
140 : bool remove_redundant_checks_;
141 :
142 : DISALLOW_COPY_AND_ASSIGN(AsanBasicBlockTransform);
143 : };
144 :
145 : class AsanTransform
146 : : public block_graph::transforms::IterativeTransformImpl<AsanTransform>,
147 : public block_graph::Filterable {
148 : public:
149 : typedef block_graph::BlockGraph BlockGraph;
150 : typedef AsanBasicBlockTransform::MemoryAccessInfo MemoryAccessInfo;
151 : typedef AsanBasicBlockTransform::MemoryAccessMode MemoryAccessMode;
152 :
153 : // Initialize a new AsanTransform instance.
154 : AsanTransform();
155 :
156 : // @name IterativeTransformImpl implementation.
157 : // @{
158 : bool PreBlockGraphIteration(BlockGraph* block_graph,
159 : BlockGraph::Block* header_block);
160 : bool OnBlock(BlockGraph* block_graph, BlockGraph::Block* block);
161 : bool PostBlockGraphIteration(BlockGraph* block_graph,
162 : BlockGraph::Block* header_block);
163 : // @}
164 :
165 : // @name Accessors.
166 : // @{
167 E : void set_instrument_dll_name(const base::StringPiece& instrument_dll_name) {
168 E : instrument_dll_name.CopyToString(&asan_dll_name_);
169 E : }
170 E : const char* instrument_dll_name() const {
171 E : return asan_dll_name_.c_str();
172 E : }
173 :
174 E : bool debug_friendly() const { return debug_friendly_; }
175 E : void set_debug_friendly(bool flag) { debug_friendly_ = flag; }
176 :
177 E : bool use_liveness_analysis() const { return use_liveness_analysis_; }
178 E : void set_use_liveness_analysis(bool use_liveness_analysis) {
179 E : use_liveness_analysis_ = use_liveness_analysis;
180 E : }
181 :
182 E : bool remove_redundant_checks() const { return remove_redundant_checks_; }
183 E : void set_remove_redundant_checks(bool remove_redundant_checks) {
184 E : remove_redundant_checks_ = remove_redundant_checks;
185 E : }
186 :
187 : // @}
188 :
189 : // The name of the DLL that is imported by default.
190 : static const char kSyzyAsanDll[];
191 :
192 : // The transform name.
193 : static const char kTransformName[];
194 :
195 : // The hooks stub name.
196 : static const char kAsanHookStubName[];
197 :
198 : protected:
199 : // Name of the asan_rtl DLL we import. Defaults to "asan_rtl.dll".
200 : std::string asan_dll_name_;
201 :
202 : // Activate the overwriting of source range for created instructions.
203 : bool debug_friendly_;
204 :
205 : // Set iff we should use the liveness analysis to do smarter instrumentation.
206 : bool use_liveness_analysis_;
207 :
208 : // When activated, a redundancy elimination is performed to minimize the
209 : // memory checks added by this transform.
210 : bool remove_redundant_checks_;
211 :
212 : // References to the different asan check access import entries. Valid after
213 : // successful PreBlockGraphIteration.
214 : AsanBasicBlockTransform::AsanHookMap check_access_hooks_ref_;
215 :
216 : DISALLOW_COPY_AND_ASSIGN(AsanTransform);
217 : };
218 :
219 : bool operator<(const AsanBasicBlockTransform::MemoryAccessInfo& left,
220 : const AsanBasicBlockTransform::MemoryAccessInfo& right);
221 :
222 : } // namespace transforms
223 : } // namespace instrument
224 :
225 : #endif // SYZYGY_INSTRUMENT_TRANSFORMS_ASAN_TRANSFORM_H_
|