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