1 : // Copyright 2012 Google Inc.
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 : #ifndef SYZYGY_PE_PE_FILE_H_
16 : #define SYZYGY_PE_PE_FILE_H_
17 :
18 : #include <windows.h>
19 : #include <winnt.h>
20 : #include <map>
21 : #include <set>
22 : #include <string>
23 : #include <vector>
24 :
25 : #include "base/file_path.h"
26 : #include "syzygy/core/address.h"
27 : #include "syzygy/core/address_space.h"
28 : #include "syzygy/core/serialization.h"
29 :
30 : namespace pe {
31 :
32 : // This duplicates a similar constant in the core namespace, declared by
33 : // block_graph.h. We duplicate it here so as not to add an uneccessary
34 : // dependency.
35 : // Header data and other data not from a regular section is considered as
36 : // being from an invalid section.
37 : extern const size_t kInvalidSection;
38 :
39 : class PEFile {
40 : public:
41 : // Used for storing the signature of a PE file.
42 : struct Signature;
43 :
44 : typedef core::AbsoluteAddress AbsoluteAddress;
45 : typedef core::FileOffsetAddress FileOffsetAddress;
46 : typedef core::RelativeAddress RelativeAddress;
47 :
48 : // Contains relocation addresses.
49 : typedef std::set<RelativeAddress> RelocSet;
50 :
51 : // Contains the decoded relocation information, where each item
52 : // in the map is the address and value of a relocatable entry.
53 : typedef std::map<RelativeAddress, AbsoluteAddress> RelocMap;
54 :
55 : // Information about a single export.
56 : struct ExportInfo;
57 : typedef std::vector<ExportInfo> ExportInfoVector;
58 :
59 : // Information about a single import.
60 : struct ImportInfo;
61 : typedef std::vector<ImportInfo> ImportInfoVector;
62 :
63 : // Information about all imports for a given DLL.
64 : struct ImportDll;
65 : typedef std::vector<ImportDll> ImportDllVector;
66 :
67 : PEFile();
68 : ~PEFile();
69 :
70 E : const FilePath& path() const { return path_; }
71 :
72 : // Read in the image file at path.
73 : bool Init(const FilePath& path);
74 :
75 : // Populates a signature object with the signature of this PE file. This
76 : // is only valid if called after Init.
77 : void GetSignature(Signature* signature) const;
78 :
79 : // Decodes the relocation information from the image to relocs.
80 : // TODO(siggi): Consider folding this member into ReadRelocs.
81 : bool DecodeRelocs(RelocSet* relocs) const;
82 : // Reads all reloc values from the image.
83 : bool ReadRelocs(const RelocSet& relocs, RelocMap* reloc_values) const;
84 :
85 : // Decodes the import information in the image.
86 : bool DecodeImports(ImportDllVector* imports) const;
87 :
88 : // Decodes the export information in the image.
89 : bool DecodeExports(ExportInfoVector* exports) const;
90 :
91 : // @{
92 : // Translate between relative and absolute addresses.
93 : bool Translate(RelativeAddress rel, AbsoluteAddress* abs) const;
94 : bool Translate(AbsoluteAddress abs, RelativeAddress* rel) const;
95 : bool Translate(FileOffsetAddress offs, RelativeAddress* rel) const;
96 : bool Translate(RelativeAddress rel, FileOffsetAddress* offs) const;
97 : // @}
98 :
99 : // Read len bytes from image at offset offs to data.
100 : bool ReadImage(RelativeAddress rel, void* data, size_t len) const;
101 : bool ReadImage(AbsoluteAddress abs, void* data, size_t len) const;
102 :
103 : // Read a zero-terminated string from offs into str.
104 : bool ReadImageString(RelativeAddress rel, std::string* str) const;
105 : bool ReadImageString(AbsoluteAddress abs, std::string* str) const;
106 :
107 : // Get a pointer to the image at addr, provided the image contains data
108 : // for [addr, addr + len)
109 : const uint8* GetImageData(RelativeAddress rel, size_t len) const;
110 : const uint8* GetImageData(AbsoluteAddress abs, size_t len) const;
111 : uint8* GetImageData(RelativeAddress rel, size_t len);
112 : uint8* GetImageData(AbsoluteAddress abs, size_t len);
113 :
114 : // Check whether or not a given address range is inside the
115 : // address space of the PE image.
116 : bool Contains(RelativeAddress rel, size_t len) const;
117 : bool Contains(AbsoluteAddress abs, size_t len) const;
118 :
119 : // Returns the section index associated with a given address. Returns
120 : // kInvalidSection if the address does not lie within a section.
121 : size_t GetSectionIndex(RelativeAddress rel, size_t len) const;
122 : size_t GetSectionIndex(AbsoluteAddress abs, size_t len) const;
123 :
124 : // Returns a pointer to the section header associated with a given address.
125 : // Returns NULL if the address does not lie within a section.
126 : const IMAGE_SECTION_HEADER* GetSectionHeader(RelativeAddress rel,
127 : size_t len) const;
128 : const IMAGE_SECTION_HEADER* GetSectionHeader(AbsoluteAddress rel,
129 : size_t len) const;
130 :
131 : // Returns the section index associated with the given name. Returns
132 : // kInvalidSection if no section with that name is found.
133 : size_t GetSectionIndex(const char* name) const;
134 :
135 : // Returns the section header associated with the given name. Returns
136 : // kInvalidSection if no section with the name is found.
137 : const IMAGE_SECTION_HEADER* GetSectionHeader(const char* name) const;
138 :
139 : // Helper to stringify the name of a section.
140 : std::string GetSectionName(size_t section_index) const;
141 : static std::string GetSectionName(const IMAGE_SECTION_HEADER& section);
142 :
143 : // Accessors.
144 E : const IMAGE_DOS_HEADER* dos_header() const {
145 E : return dos_header_;
146 E : }
147 :
148 E : const IMAGE_NT_HEADERS* nt_headers() const {
149 E : return nt_headers_;
150 E : }
151 :
152 E : const IMAGE_SECTION_HEADER* section_headers() const {
153 E : return section_headers_;
154 E : }
155 :
156 E : const IMAGE_SECTION_HEADER* section_header(size_t num_section) const {
157 : if (nt_headers_ != NULL &&
158 E : num_section < nt_headers_->FileHeader.NumberOfSections)
159 E : return section_headers_ + num_section;
160 :
161 E : return NULL;
162 E : }
163 :
164 : private:
165 : bool ReadHeaders(FILE* file);
166 : bool ReadSections(FILE* file);
167 :
168 : FilePath path_;
169 : const IMAGE_DOS_HEADER* dos_header_;
170 : const IMAGE_NT_HEADERS* nt_headers_;
171 : const IMAGE_SECTION_HEADER* section_headers_;
172 :
173 : typedef std::vector<uint8> SectionBuffer;
174 : struct SectionInfo {
175 E : SectionInfo() : id(kInvalidSection) {
176 E : }
177 : size_t id;
178 : SectionBuffer buffer;
179 : };
180 : typedef core::AddressSpace<RelativeAddress, size_t, SectionInfo>
181 : ImageAddressSpace;
182 :
183 : // Contains all data in the image. The address space has a range defined
184 : // for the header and each section in the image, with its associated
185 : // SectionBuffer as the data.
186 : ImageAddressSpace image_data_;
187 :
188 : DISALLOW_COPY_AND_ASSIGN(PEFile);
189 : };
190 :
191 : // This structure holds a PE file signature.
192 : struct PEFile::Signature {
193 E : Signature() : module_size(0), module_time_date_stamp(0), module_checksum(0) {
194 E : }
195 :
196 : // The original path is kept for convenience. This should always be an
197 : // absolute path.
198 : // TODO(chrisha): Check that the path is absolute at all sites where this
199 : // path is used.
200 : std::wstring path;
201 :
202 : // The signature consists of the following 4 fields.
203 : AbsoluteAddress base_address;
204 : size_t module_size;
205 : uint32 module_time_date_stamp;
206 : uint32 module_checksum;
207 :
208 : // Compares this signature to another one. The paths do not have to match.
209 : bool IsConsistent(const Signature& signature) const;
210 :
211 : // We need an equality operator for serialization unittests.
212 E : bool operator==(const Signature& signature) const {
213 E : return path == signature.path && IsConsistent(signature);
214 E : }
215 :
216 : // For serialization.
217 : bool Save(core::OutArchive* out_archive) const;
218 : bool Load(core::InArchive* in_archive);
219 : };
220 :
221 : // Information about a single export.
222 : struct PEFile::ExportInfo {
223 : // Address of the exported function.
224 : RelativeAddress function;
225 :
226 : // Name of the export, if any.
227 : std::string name;
228 :
229 : // Export forward string, if any.
230 : std::string forward;
231 :
232 : // Export ordinal.
233 : uint16 ordinal;
234 : };
235 :
236 : // Information about a single import.
237 : struct PEFile::ImportInfo {
238 : ImportInfo(uint16 h, uint16 o, const char* n)
239 : : hint(h),
240 : ordinal(o),
241 E : function(n) {
242 E : }
243 :
244 : explicit ImportInfo(const char* function_name)
245 : : hint(0),
246 : ordinal(0),
247 : function(function_name) {
248 : }
249 : explicit ImportInfo(uint16 function_ordinal)
250 : : hint(0),
251 : ordinal(function_ordinal) {
252 : }
253 E : ImportInfo() : hint(0), ordinal(0) {
254 E : }
255 :
256 E : bool operator==(const ImportInfo& o) const {
257 E : return hint == o.hint && ordinal == o.ordinal && function == o.function;
258 E : }
259 :
260 : // The loader ordinal hint for this import.
261 : uint16 hint;
262 :
263 : // The ordinal of the function if function.empty().
264 : uint16 ordinal;
265 :
266 : // If non-empty, the name of the function.
267 : std::string function;
268 : };
269 :
270 : // Information about all imports for a given DLL.
271 : struct PEFile::ImportDll {
272 E : ImportDll() {
273 E : memset(&desc, 0, sizeof(desc));
274 E : desc.ForwarderChain = -1;
275 E : }
276 :
277 : // The import descriptor.
278 : IMAGE_IMPORT_DESCRIPTOR desc;
279 :
280 : // Name of the DLL imported.
281 : std::string name;
282 :
283 : // One entry for each imported function.
284 : ImportInfoVector functions;
285 : };
286 :
287 : } // namespace pe
288 :
289 : #endif // SYZYGY_PE_PE_FILE_H_
|