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