1 : // Copyright 2013 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 : // The PECoffImageLayoutBuilder is the base class for PE and COFF image
16 : // layout builders, which contains common functions for laying out blocks
17 : // and sections.
18 :
19 : #ifndef SYZYGY_PE_PE_COFF_IMAGE_LAYOUT_BUILDER_H_
20 : #define SYZYGY_PE_PE_COFF_IMAGE_LAYOUT_BUILDER_H_
21 :
22 : #include <windows.h>
23 :
24 : #include "syzygy/block_graph/block_graph.h"
25 : #include "syzygy/block_graph/ordered_block_graph.h"
26 : #include "syzygy/pe/image_layout.h"
27 : #include "syzygy/pe/pe_file_parser.h"
28 :
29 : namespace pe {
30 :
31 : // A helper class that assists in mapping PE or COFF image sections and
32 : // blocks to an address space.
33 : //
34 : // Image layout builders are stateful objects that progressively lay out
35 : // blocks at increasing addresses. A builder keeps information on the
36 : // current position (address to build at) and section being laid out.
37 : class PECoffImageLayoutBuilder {
38 : public:
39 : typedef block_graph::BlockGraph BlockGraph;
40 : typedef block_graph::OrderedBlockGraph OrderedBlockGraph;
41 : typedef core::RelativeAddress RelativeAddress;
42 :
43 : // Set the inter-block padding. If this is non-zero, it specifies the
44 : // minimum amount of blank space that will be left between blocks laid out
45 : // within a same section. The content of the padding is left unspecified
46 : // and will appear as a gap in the address space, usually filled by the
47 : // file writer with appropriate padding bytes.
48 : //
49 : // @param padding the new inter-block padding.
50 E : void set_padding(size_t padding) { padding_ = padding; }
51 :
52 : // @returns the current inter-block padding.
53 : // @see set_padding(size_t)
54 E : size_t padding() const { return padding_; }
55 :
56 : // @param alignment the minimal alignment for a code block.
57 E : void set_code_alignment(size_t alignment) { code_alignment_ = alignment; }
58 :
59 : // @returns the current code block alignment.
60 E : size_t code_alignment() const { return code_alignment_; }
61 :
62 : // @returns the mutable image layout this builder builds to.
63 E : ImageLayout* image_layout() { return image_layout_; }
64 :
65 : // @returns the image layout this builder builds to.
66 : const ImageLayout* image_layout() const {
67 : return image_layout_;
68 : }
69 :
70 : // @returns the mutable block graph this builder builds from.
71 : // @note The block graph matches that returned by image_layout().
72 E : BlockGraph* block_graph() { return image_layout_->blocks.graph(); }
73 :
74 : // @returns the block graph this builder builds from.
75 : // @note The block graph matches that returned by image_layout().
76 : const BlockGraph* block_graph() const {
77 : return image_layout_->blocks.graph();
78 : }
79 :
80 : // Start laying out a new section. If another section is currently open,
81 : // it will first be closed.
82 : //
83 : // @param name the name of the section.
84 : // @param characteristics the section characteristics.
85 : // @returns true on success, false on failure.
86 : // @note Sections cannot be laid out at offset zero; derived classes are
87 : // expected to lay out some headers before laying out sections.
88 : bool OpenSection(const char* name, uint32 characteristics);
89 :
90 : // Start laying out a new section. If another section is currently open,
91 : // it will first be closed.
92 : //
93 : // @param section the section to be laid out.
94 : // @returns true on success, false on failure.
95 : // @see OpenSection(const char*, uint32)
96 : bool OpenSection(const BlockGraph::Section& section);
97 :
98 : // Lay out the provided block, enforcing to the inter-block block
99 : // padding. The block is aligned according to the internal alignment of
100 : // @p block.
101 : //
102 : // @param block the block to lay out.
103 : // @returns true on success, false on failure.
104 : bool LayoutBlock(BlockGraph::Block* block);
105 :
106 : // Lay out the provided block, using the specified alignment.
107 : //
108 : // @param alignment the explicit alignment to use.
109 : // @param block the block to lay out.
110 : // @returns true on success, false on failure.
111 : // @see LayoutBlock(BlockGraph::Block*)
112 : bool LayoutBlock(size_t alignment, BlockGraph::Block* block);
113 :
114 : // Mark the end of the initialized data portion of the section that is
115 : // currently being laid out. If not explicitly called for a given section,
116 : // the span of initialized data will be automatically determined based on
117 : // block contents.
118 : //
119 : // @note A section must be open for layout.
120 : void CloseExplicitSectionData();
121 :
122 : // Mark the end of the section that is currently being laid out.
123 : //
124 : // @returns true on success, false on failure.
125 : // @note A section must be open for layout.
126 : bool CloseSection();
127 :
128 : protected:
129 : // Construct a new image layout builder that populates the provided image
130 : // layout. The image layout must outlive the builder.
131 : //
132 : // @param image_layout the image layout to build into.
133 : explicit PECoffImageLayoutBuilder(ImageLayout* image_layout);
134 :
135 : // Lay out a block at the current cursor location.
136 : //
137 : // @param block the block to lay out.
138 : // @returns true on success, false on failure.
139 : bool LayoutBlockImpl(BlockGraph::Block* block);
140 :
141 : // Initialize the layout builder with the specified alignment constraints.
142 : // Section alignment should be equal or greater than raw data (file)
143 : // alignment.
144 : //
145 : // According to the PE specifications, file alignment should be a power of
146 : // two between 512 and 64K for PE files. For object files, it may be zero.
147 : //
148 : // @param section_alignment the alignment of layed out sections.
149 : // @param file_alignment the alignment of raw data.
150 : void Init(size_t section_alignment, size_t file_alignment);
151 :
152 : // The image layout this object builds into.
153 : ImageLayout* image_layout_;
154 :
155 : // The inter-block padding.
156 : size_t padding_;
157 :
158 : // The minimal code block alignment.
159 : size_t code_alignment_;
160 :
161 : // The current position of the output cursor.
162 : RelativeAddress cursor_;
163 :
164 : // The start of the section currently being laid out.
165 : RelativeAddress section_start_;
166 :
167 : // The automatic estimate of the end of initialized data in the section
168 : // currently being laid out.
169 : RelativeAddress section_auto_init_end_;
170 :
171 : // The explicit end of initialized data in the section currently being
172 : // laid out, if any; valid if greater than the cursor position.
173 : RelativeAddress section_init_end_;
174 :
175 : // The (virtual) alignment of sections.
176 : size_t section_alignment_;
177 :
178 : // The alignment of section raw data in the image file.
179 : size_t file_alignment_;
180 :
181 : private:
182 : DISALLOW_COPY_AND_ASSIGN(PECoffImageLayoutBuilder);
183 : };
184 :
185 : } // namespace pe
186 :
187 : #endif // SYZYGY_PE_PE_COFF_IMAGE_LAYOUT_BUILDER_H_
|