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 : // Sets whether or not debug information is parsed. If true then the
72 : // decomposed block-graph will be decorated with extensive debug information.
73 : // If false then a functionally equivalent but undecorated decomposition
74 : // will be created. Defaults to true.
75 : // @param parse_debug_info controls whether or not debug information will
76 : // be parsed.
77 E : void set_parse_debug_info(bool parse_debug_info) {
78 E : parse_debug_info_ = parse_debug_info;
79 E : }
80 : // @}
81 :
82 : // @name Accessors
83 : // @{
84 : // Accessor to the PDB path. If Decompose has been called successfully this
85 : // will reflect the path of the PDB file that was used to perform the
86 : // decomposition.
87 : // @returns the PDB path.
88 E : const base::FilePath& pdb_path() const { return pdb_path_; }
89 : // @returns true if the decomposed block-graph will contain debug information.
90 E : bool parse_debug_info() const { return parse_debug_info_; }
91 : // @}
92 :
93 : protected:
94 : typedef block_graph::BlockGraph BlockGraph;
95 : typedef core::RelativeAddress RelativeAddress;
96 :
97 : // Searches for (if necessary) the PDB file to be used in the decomposition,
98 : // and validates that the file exists and matches the module.
99 : bool FindAndValidatePdbPath();
100 :
101 : // @name Used for round-trip decomposition when a serialized block graph is
102 : // in the PDB. Exposed here for unittesting.
103 : // @{
104 : static bool LoadBlockGraphFromPdbStream(const PEFile& image_file,
105 : pdb::PdbStream* block_graph_stream,
106 : ImageLayout* image_layout);
107 : static bool LoadBlockGraphFromPdb(const base::FilePath& pdb_path,
108 : const PEFile& image_file,
109 : ImageLayout* image_layout,
110 : bool* stream_exists);
111 : // @}
112 :
113 : // @name Decomposition steps, in order.
114 : // @{
115 : // Performs the actual decomposition.
116 : bool DecomposeImpl();
117 : // Creates sections in the block-graph corresponding to those in the image.
118 : bool CreateBlockGraphSections();
119 : // Parses PE-related blocks and references.
120 : bool CreatePEImageBlocksAndReferences(IntermediateReferences* references);
121 : // Creates blocks from the COFF group symbols in the linker symbol stream.
122 : bool CreateBlocksFromCoffGroups();
123 : // Processes the SectionContribution table, creating code/data blocks from it.
124 : bool CreateBlocksFromSectionContribs(IDiaSession* session);
125 : // Creates gap blocks to flesh out the image. After this has been run all
126 : // references should be resolvable.
127 : bool CreateGapBlocks();
128 : // Finalizes the given vector of intermediate references.
129 : bool FinalizeIntermediateReferences(const IntermediateReferences& references);
130 : // Creates inter-block references from fixups.
131 : bool CreateReferencesFromFixups(IDiaSession* session);
132 : // Disassembles code blocks and labels jump and case tables.
133 : bool DisassembleCodeBlocksAndLabelData();
134 : // Processes symbols from the PDB, setting block names and labels. This
135 : // step is purely optional and only necessary to provide debug information.
136 : // This adds names to blocks, adds code labels and their names, and adds
137 : // more informative names to data labels. Only called if parse_debug_info_
138 : // is true.
139 : bool ProcessSymbols(IDiaSymbol* root);
140 : // @}
141 :
142 : // @{
143 : // @name Callbacks and context structures used by the COFF group parsing
144 : // mechanism.
145 : struct VisitLinkerSymbolContext;
146 : bool VisitLinkerSymbol(VisitLinkerSymbolContext* context,
147 : uint16 symbol_length,
148 : uint16 symbol_type,
149 : pdb::PdbStream* stream);
150 : // @}
151 :
152 : // @{
153 : // @name Callbacks used when parsing DIA symbols. Symbols only need to be
154 : // parsed for debug information and can be completely ignored otherwise.
155 : DiaBrowser::BrowserDirective OnPushFunctionOrThunkSymbol(
156 : const DiaBrowser& dia_browser,
157 : const DiaBrowser::SymTagVector& sym_tags,
158 : const DiaBrowser::SymbolPtrVector& symbols);
159 : DiaBrowser::BrowserDirective OnPopFunctionOrThunkSymbol(
160 : const DiaBrowser& dia_browser,
161 : const DiaBrowser::SymTagVector& sym_tags,
162 : const DiaBrowser::SymbolPtrVector& symbols);
163 : DiaBrowser::BrowserDirective OnFunctionChildSymbol(
164 : const DiaBrowser& dia_browser,
165 : const DiaBrowser::SymTagVector& sym_tags,
166 : const DiaBrowser::SymbolPtrVector& symbols);
167 : DiaBrowser::BrowserDirective OnDataSymbol(
168 : const DiaBrowser& dia_browser,
169 : const DiaBrowser::SymTagVector& sym_tags,
170 : const DiaBrowser::SymbolPtrVector& symbols);
171 : DiaBrowser::BrowserDirective OnPublicSymbol(
172 : const DiaBrowser& dia_browser,
173 : const DiaBrowser::SymTagVector& sym_tags,
174 : const DiaBrowser::SymbolPtrVector& symbols);
175 : DiaBrowser::BrowserDirective OnLabelSymbol(
176 : const DiaBrowser& dia_browser,
177 : const DiaBrowser::SymTagVector& sym_tags,
178 : const DiaBrowser::SymbolPtrVector& symbols);
179 : // @}
180 :
181 : // @name These are called within the scope of OnFunctionChildSymbol, during
182 : // which current_block_ is always set.
183 : // @{
184 : DiaBrowser::BrowserDirective OnScopeSymbol(enum SymTagEnum type,
185 : DiaBrowser::SymbolPtr symbol);
186 : DiaBrowser::BrowserDirective OnCallSiteSymbol(DiaBrowser::SymbolPtr symbol);
187 : // @}
188 :
189 : // @name Block creation members.
190 : // @{
191 : // Creates a new block with the given properties, and attaches the
192 : // data to it. This assumes that no conflicting block exists.
193 : BlockGraph::Block* CreateBlock(BlockGraph::BlockType type,
194 : RelativeAddress address,
195 : BlockGraph::Size size,
196 : const base::StringPiece& name);
197 : // Creates a new block with the given properties, or finds an existing PE
198 : // parsed block that subsumes it.
199 : BlockGraph::Block* CreateBlockOrFindCoveringPeBlock(
200 : BlockGraph::BlockType type,
201 : RelativeAddress address,
202 : BlockGraph::Size size,
203 : const base::StringPiece& name);
204 : // Creates a gap block of type @p block_type for the given range. For use by
205 : // CreateSectionGapBlocks.
206 : bool CreateGapBlock(BlockGraph::BlockType block_type,
207 : RelativeAddress address,
208 : BlockGraph::Size size);
209 : // Create blocks of type @p block_type for any gaps in the image
210 : // section represented by @p header.
211 : bool CreateSectionGapBlocks(const IMAGE_SECTION_HEADER* header,
212 : BlockGraph::BlockType block_type);
213 : // @}
214 :
215 : // The PEFile that is being decomposed.
216 : const PEFile& image_file_;
217 : // The path to corresponding PDB file.
218 : base::FilePath pdb_path_;
219 : // Controls whether or not debug information is added to the decomposed
220 : // image. If this is false then a completely functional but non-decorated
221 : // decomposition will be created.
222 : bool parse_debug_info_;
223 :
224 : // @name Temporaries that are only valid while inside DecomposeImpl.
225 : // Prevents us from having to pass these around everywhere.
226 : // @{
227 : // The image layout we're building.
228 : ImageLayout* image_layout_;
229 : // The image address space we're decomposing to.
230 : BlockGraph::AddressSpace* image_;
231 : // @}
232 :
233 : // @name Temporaries that are only valid while in DiaBrowser.
234 : // @{
235 : BlockGraph::Block* current_block_;
236 : RelativeAddress current_address_;
237 : size_t current_scope_count_;
238 : // @}
239 : };
240 :
241 : } // namespace pe
242 :
243 : #endif // SYZYGY_PE_NEW_DECOMPOSER_H_
|