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 thunk import references instrumentation transform.
16 : //
17 : // This transform is designed to traverse all blocks containing references to
18 : // entries in the import tables and replace them with references to conjured-up
19 : // thunks that delegate to the instrumentation machinery.
20 : // It accepts a list of modules to exclude from this process to allow for
21 : // e.g. not thunking the instrumentation.
22 :
23 : #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_THUNK_IMPORT_REFERENCES_TRANSFORM_H_
24 : #define SYZYGY_INSTRUMENT_TRANSFORMS_THUNK_IMPORT_REFERENCES_TRANSFORM_H_
25 :
26 : #include <set>
27 : #include <string>
28 :
29 : #include "base/strings/string_piece.h"
30 : #include "syzygy/block_graph/iterate.h"
31 : #include "syzygy/block_graph/transforms/iterative_transform.h"
32 : #include "syzygy/pe/transforms/pe_add_imports_transform.h"
33 :
34 : namespace instrument {
35 : namespace transforms {
36 :
37 : // A transform that replaces references to imports with a reference to
38 : // an entry hook thunk.
39 : class ThunkImportReferencesTransform
40 : : public block_graph::transforms::NamedBlockGraphTransformImpl<
41 : ThunkImportReferencesTransform> {
42 : public:
43 : typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
44 :
45 : ThunkImportReferencesTransform();
46 :
47 : // Adds a module to the list of those from which imports are excluded from
48 : // being thunked.
49 : // @param module_name the base name, including extension, of the module
50 : // to exclude e.g. "kernel32.dll". The module name is case insensitive.
51 : // @note that the instrumentation DLL is implicitly always excluded from
52 : // instrumentation.
53 : void ExcludeModule(const base::StringPiece& module_name);
54 :
55 : // Accessors.
56 E : const char* instrument_dll_name() const {
57 E : return instrument_dll_name_.c_str();
58 E : }
59 E : void set_instrument_dll_name(const base::StringPiece& name) {
60 E : instrument_dll_name_.assign(name.begin(), name.end());
61 E : }
62 :
63 : // The name of the import for general entry hooks.
64 : static const char kEntryHookName[];
65 :
66 : // The name of the instrumentation DLL imported by default.
67 : static const char kDefaultInstrumentDll[];
68 :
69 : protected:
70 : friend NamedBlockGraphTransformImpl<ThunkImportReferencesTransform>;
71 : typedef block_graph::BlockGraph BlockGraph;
72 : class ModuleNameLess;
73 : typedef std::set<std::string, ModuleNameLess> ModuleNameSet;
74 :
75 : // We keep a map from the blocks/offsets where there are imports we want to
76 : // thunk (e.g. imports to non-excluded modules) to their dll/function names,
77 : // during instrumentation.
78 : typedef std::pair<BlockGraph::Block*, BlockGraph::Offset>
79 : ImportAddressLocation;
80 : typedef std::map<ImportAddressLocation, std::string>
81 : ImportAddressLocationNameMap;
82 : typedef std::set<BlockGraph::Block*> BlockSet;
83 :
84 : // Comparator for module names, this class wants to be fully declared before
85 : // use of the typedefs referencing it.
86 : class ModuleNameLess {
87 : public:
88 : bool operator()(const std::string& lhs, const std::string& rhs) const;
89 : };
90 :
91 : // @name IterativeTransformImpl implementation.
92 : // @{
93 : virtual bool TransformBlockGraph(const TransformPolicyInterface* policy,
94 : BlockGraph* block_graph,
95 : BlockGraph::Block* header_block) override;
96 : // @}
97 :
98 : // Accessor.
99 : BlockGraph::Section* thunk_section() const { return thunk_section_; }
100 :
101 : // Instrument all references to @p iat_block that have an entry
102 : // in @p import_locations, excluding references from @p iidt_block.
103 : // @param block_graph the block graph to operate on.
104 : // @param import_locations tags the entries to instrument.
105 : // @returns true on success, false on failure.
106 : bool InstrumentImportReferences(
107 : BlockGraph* block_graph,
108 : const ImportAddressLocationNameMap& import_locations);
109 :
110 : // Create a single thunk to destination.
111 : // @param destination the destination reference.
112 : // @param is_dll_entry_signature true iff this should be a DLL entry thunk.
113 : // @param name is the name of the import referenced.
114 : BlockGraph::Block* CreateOneThunk(BlockGraph* block_graph,
115 : const BlockGraph::Reference& destination,
116 : const base::StringPiece& name);
117 :
118 : // Exposed for testing. Valid after Apply() is called.
119 : pe::transforms::PEAddImportsTransform& add_imports_transform() {
120 : return add_imports_transform_;
121 : }
122 :
123 : // Retrieves the set of blocks referenced by import_locations.
124 : static bool GetImportBlocks(
125 : const ImportAddressLocationNameMap& import_locations,
126 : BlockSet* import_blocks);
127 :
128 : // Implementation function, exposed for testing.
129 : static bool LookupImportLocations(
130 : const ModuleNameSet& exclusions,
131 : BlockGraph::Block* header_block,
132 : ImportAddressLocationNameMap* import_locations);
133 :
134 : // Implementation function, exposed for testing.
135 : static bool LookupDelayImportLocations(
136 : const ModuleNameSet& exclusions,
137 : BlockGraph::Block* header_block,
138 : ImportAddressLocationNameMap* import_locations);
139 :
140 : // For NamedBlockGraphTransformImpl.
141 : static const char kTransformName[];
142 :
143 : // The section we put our thunks in.
144 : BlockGraph::Section* thunk_section_;
145 :
146 : // References to _indirect_penter and _indirect_penter_dllmain import
147 : // entries.
148 : BlockGraph::Reference hook_ref_;
149 :
150 : // The transform used to add imports for our instrumentation. It also
151 : // conveniently stores references to the blocks containing the IAT and IDT.
152 : pe::transforms::PEAddImportsTransform add_imports_transform_;
153 :
154 : // Name of the instrumentation DLL we import. Defaults to "call_trace.dll".
155 : std::string instrument_dll_name_;
156 :
157 : // Set of names of modules whose imports will not be thunked.
158 : ModuleNameSet modules_to_exclude_;
159 :
160 : DISALLOW_COPY_AND_ASSIGN(ThunkImportReferencesTransform);
161 : };
162 :
163 : } // namespace transforms
164 : } // namespace instrument
165 :
166 : #endif // SYZYGY_INSTRUMENT_TRANSFORMS_THUNK_IMPORT_REFERENCES_TRANSFORM_H_
|