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 : // Declares the decomposer, which decomposes a PE file into an ImageLayout and
16 : // its corresponding BlockGraph.
17 : //
18 : // TODO(chrisha): When the new decomposer is ready, swap out the old for the
19 : // new and rename this. The new decomposer does not use all of the block
20 : // attributes, so some cleanup can be done there once we switch over!
21 :
22 : #ifndef SYZYGY_PE_NEW_DECOMPOSER_H_
23 : #define SYZYGY_PE_NEW_DECOMPOSER_H_
24 :
25 : #include <windows.h> // NOLINT
26 : #include <dia2.h>
27 : #include <vector>
28 :
29 : #include "syzygy/pdb/pdb_file.h"
30 : #include "syzygy/pdb/pdb_stream.h"
31 : #include "syzygy/pe/dia_browser.h"
32 : #include "syzygy/pe/image_layout.h"
33 : #include "syzygy/pe/pe_file.h"
34 :
35 : namespace pe {
36 :
37 : // Forward declaration of a helper class where we hide our implementation
38 : // details.
39 : class NewDecomposerImpl;
40 :
41 : class NewDecomposer {
42 : public:
43 : struct IntermediateReference;
44 : typedef std::vector<IntermediateReference> IntermediateReferences;
45 :
46 : // The separator that is used between the multiple symbol names that can be
47 : // associated with a single label.
48 : static const char kLabelNameSep[];
49 :
50 : // Initialize the decomposer for a given image file.
51 : // @param image_file the image file to decompose. This must outlive the
52 : // instance of the decomposer.
53 : explicit NewDecomposer(const PEFile& image_file);
54 :
55 : // Decomposes the image file into a BlockGraph and an ImageLayout, which
56 : // have the breakdown of code and data blocks with typed references and
57 : // information on where the blocks resided in the original image,
58 : // respectively.
59 : // @returns true on success, false on failure.
60 : bool Decompose(ImageLayout* image_layout);
61 :
62 : // @name Mutators.
63 : // @{
64 : // Sets the PDB path to be used. If this is not called it will be inferred
65 : // using the information in the module, and searched for using the OS
66 : // search functionality.
67 : // @param pdb_path the path to the PDB file to be used in decomposing the
68 : // image.
69 E : void set_pdb_path(const base::FilePath& pdb_path) { pdb_path_ = pdb_path; }
70 : // @}
71 :
72 : // @name Accessors
73 : // @{
74 : // Accessor to the PDB path. If Decompose has been called successfully this
75 : // will reflect the path of the PDB file that was used to perform the
76 : // decomposition.
77 : // @returns the PDB path.
78 E : const base::FilePath& pdb_path() const { return pdb_path_; }
79 : // @}
80 :
81 : protected:
82 : typedef block_graph::BlockGraph BlockGraph;
83 : typedef core::RelativeAddress RelativeAddress;
84 :
85 : // Searches for (if necessary) the PDB file to be used in the decomposition,
86 : // and validates that the file exists and matches the module.
87 : bool FindAndValidatePdbPath();
88 :
89 : // @name Used for round-trip decomposition when a serialized block graph is
90 : // in the PDB. Exposed here for unittesting.
91 : // @{
92 : static bool LoadBlockGraphFromPdbStream(const PEFile& image_file,
93 : pdb::PdbStream* block_graph_stream,
94 : ImageLayout* image_layout);
95 : static bool LoadBlockGraphFromPdb(const base::FilePath& pdb_path,
96 : const PEFile& image_file,
97 : ImageLayout* image_layout,
98 : bool* stream_exists);
99 : // @}
100 :
101 : // @name Decomposition steps, in order.
102 : // @{
103 : // Performs the actual decomposition.
104 : bool DecomposeImpl();
105 : // Parses PE-related blocks and references.
106 : bool CreatePEImageBlocksAndReferences(IntermediateReferences* references);
107 : // Creates blocks from the COFF group symbols in the linker symbol stream.
108 : bool CreateBlocksFromCoffGroups();
109 : // Processes the SectionContribution table, creating code/data blocks from it.
110 : bool CreateBlocksFromSectionContribs(IDiaSession* session);
111 : // Creates gap blocks to flesh out the image. After this has been run all
112 : // references should be resolvable.
113 : bool CreateGapBlocks();
114 : // Finalizes the given vector of intermediate references.
115 : bool FinalizeIntermediateReferences(const IntermediateReferences& references);
116 : // Creates inter-block references from fixups.
117 : bool CreateReferencesFromFixups(IDiaSession* session);
118 : // Processes symbols from the PDB, setting block names and labels. This
119 : // step is purely optional and only necessary to provide debug information.
120 : // This adds names to blocks, adds code labels and their names, and adds
121 : // more informative names to data labels.
122 : bool ProcessSymbols(IDiaSymbol* root);
123 : // @}
124 :
125 : // @{
126 : // @name Callbacks and context structures used by the COFF group parsing
127 : // mechanism.
128 : struct VisitLinkerSymbolContext;
129 : bool VisitLinkerSymbol(VisitLinkerSymbolContext* context,
130 : uint16 symbol_length,
131 : uint16 symbol_type,
132 : pdb::PdbStream* stream);
133 : // @}
134 :
135 : // @{
136 : // @name Callbacks used when parsing DIA symbols. Symbols only need to be
137 : // parsed for debug information and can be completely ignored otherwise.
138 : DiaBrowser::BrowserDirective OnPushFunctionOrThunkSymbol(
139 : const DiaBrowser& dia_browser,
140 : const DiaBrowser::SymTagVector& sym_tags,
141 : const DiaBrowser::SymbolPtrVector& symbols);
142 : DiaBrowser::BrowserDirective OnPopFunctionOrThunkSymbol(
143 : const DiaBrowser& dia_browser,
144 : const DiaBrowser::SymTagVector& sym_tags,
145 : const DiaBrowser::SymbolPtrVector& symbols);
146 : DiaBrowser::BrowserDirective OnFunctionChildSymbol(
147 : const DiaBrowser& dia_browser,
148 : const DiaBrowser::SymTagVector& sym_tags,
149 : const DiaBrowser::SymbolPtrVector& symbols);
150 : DiaBrowser::BrowserDirective OnDataSymbol(
151 : const DiaBrowser& dia_browser,
152 : const DiaBrowser::SymTagVector& sym_tags,
153 : const DiaBrowser::SymbolPtrVector& symbols);
154 : DiaBrowser::BrowserDirective OnPublicSymbol(
155 : const DiaBrowser& dia_browser,
156 : const DiaBrowser::SymTagVector& sym_tags,
157 : const DiaBrowser::SymbolPtrVector& symbols);
158 : DiaBrowser::BrowserDirective OnLabelSymbol(
159 : const DiaBrowser& dia_browser,
160 : const DiaBrowser::SymTagVector& sym_tags,
161 : const DiaBrowser::SymbolPtrVector& symbols);
162 : // @}
163 :
164 : // @name These are called within the scope of OnFunctionChildSymbol, during
165 : // which current_block_ is always set.
166 : // @{
167 : DiaBrowser::BrowserDirective OnScopeSymbol(enum SymTagEnum type,
168 : DiaBrowser::SymbolPtr symbol);
169 : DiaBrowser::BrowserDirective OnCallSiteSymbol(DiaBrowser::SymbolPtr symbol);
170 : // @}
171 :
172 : // @name Block creation members.
173 : // @{
174 : // Creates a new block with the given properties, and attaches the
175 : // data to it. This assumes that no conflicting block exists.
176 : BlockGraph::Block* CreateBlock(BlockGraph::BlockType type,
177 : RelativeAddress address,
178 : BlockGraph::Size size,
179 : const base::StringPiece& name);
180 : // Creates a new block with the given properties, or finds an existing PE
181 : // parsed block that subsumes it.
182 : BlockGraph::Block* CreateBlockOrFindCoveringPeBlock(
183 : BlockGraph::BlockType type,
184 : RelativeAddress address,
185 : BlockGraph::Size size,
186 : const base::StringPiece& name);
187 : // Creates a gap block of type @p block_type for the given range. For use by
188 : // CreateSectionGapBlocks.
189 : bool CreateGapBlock(BlockGraph::BlockType block_type,
190 : RelativeAddress address,
191 : BlockGraph::Size size);
192 : // Create blocks of type @p block_type for any gaps in the image
193 : // section represented by @p header.
194 : bool CreateSectionGapBlocks(const IMAGE_SECTION_HEADER* header,
195 : BlockGraph::BlockType block_type);
196 : // @}
197 :
198 : // The PEFile that is being decomposed.
199 : const PEFile& image_file_;
200 : // The path to corresponding PDB file.
201 : base::FilePath pdb_path_;
202 :
203 : // @name Temporaries that are only valid while inside DecomposeImpl.
204 : // Prevents us from having to pass these around everywhere.
205 : // @{
206 : // The image layout we're building.
207 : ImageLayout* image_layout_;
208 : // The image address space we're decomposing to.
209 : BlockGraph::AddressSpace* image_;
210 : // @}
211 :
212 : // @name Temporaries that are only valid while in DiaBrowser.
213 : // @{
214 : BlockGraph::Block* current_block_;
215 : RelativeAddress current_address_;
216 : size_t current_scope_count_;
217 : // @}
218 : };
219 :
220 : } // namespace pe
221 :
222 : #endif // SYZYGY_PE_NEW_DECOMPOSER_H_
|