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_PDB_PDB_DATA_H_
16 : #define SYZYGY_PDB_PDB_DATA_H_
17 :
18 : #include <windows.h>
19 :
20 : #include <map>
21 : #include <string>
22 : #include <vector>
23 :
24 : #include "base/basictypes.h"
25 : #include "syzygy/common/assertions.h"
26 : #include "syzygy/pdb/pdb_constants.h"
27 :
28 : namespace pdb {
29 :
30 : // Pdb Info Stream Header, this is at the start of stream #1.
31 : struct PdbInfoHeader70 {
32 : // Equal to kPdbCurrentVersion for PDBs seen from VS 9.0.
33 : uint32 version;
34 : // This looks to be the time of the PDB file creation.
35 : uint32 timestamp;
36 : // Updated every time the PDB file is written.
37 : uint32 pdb_age;
38 : // This must match the GUID stored off the image's debug directory.
39 : GUID signature;
40 : };
41 : COMPILE_ASSERT_IS_POD_OF_SIZE(PdbInfoHeader70, 28);
42 :
43 : // A structure that we find in the type info hash header, this is not totally
44 : // deciphered yet.
45 : struct OffsetCb {
46 : uint32 offset;
47 : uint32 cb;
48 : };
49 : COMPILE_ASSERT_IS_POD_OF_SIZE(OffsetCb, 8);
50 :
51 : // Type Info Stream Hash, this is contained in the type info header. This part
52 : // hasn't been deciphered yet (the field names are known but we still need to
53 : // find out what their content mean).
54 : struct TypeInfoHashHeader {
55 : uint16 stream_number;
56 : uint16 padding;
57 : uint32 hash_key;
58 : uint32 cb_hash_buckets;
59 : OffsetCb offset_cb_hash_vals;
60 : OffsetCb offset_cb_type_info_offset;
61 : OffsetCb offset_cb_hash_adj;
62 : };
63 : COMPILE_ASSERT_IS_POD_OF_SIZE(TypeInfoHashHeader, 36);
64 :
65 : // Type Info Stream Header, this is at the beginning of stream #2.
66 : // See http://moyix.blogspot.ca/2007_10_01_archive.html
67 : struct TypeInfoHeader {
68 : uint32 version;
69 : uint32 len;
70 : uint32 type_min;
71 : uint32 type_max;
72 : uint32 type_info_data_size;
73 : TypeInfoHashHeader type_info_hash;
74 : };
75 : // We coerce a stream of bytes to this structure, so we require it to be
76 : // exactly 56 bytes in size.
77 : COMPILE_ASSERT_IS_POD_OF_SIZE(TypeInfoHeader, 56);
78 :
79 : // Dbi Info Stream Header, this is at the start of stream #3.
80 : // See http://code.google.com/p/pdbparser/wiki/DBI_Format
81 : struct DbiHeader {
82 : int32 signature;
83 : uint32 version;
84 : uint32 age;
85 : int16 global_symbol_info_stream;
86 : uint16 pdb_dll_version;
87 : int16 public_symbol_info_stream;
88 : uint16 pdb_dll_build_major;
89 : int16 symbol_record_stream;
90 : uint16 pdb_dll_build_minor;
91 : uint32 gp_modi_size;
92 : uint32 section_contribution_size;
93 : uint32 section_map_size;
94 : uint32 file_info_size;
95 : uint32 ts_map_size;
96 : uint32 mfc_index;
97 : uint32 dbg_header_size;
98 : uint32 ec_info_size;
99 : uint16 flags;
100 : uint16 machine;
101 : uint32 reserved;
102 : };
103 : // We coerce a stream of bytes to this structure, so we require it to be
104 : // exactly 64 bytes in size.
105 : COMPILE_ASSERT_IS_POD_OF_SIZE(DbiHeader, 64);
106 :
107 : // Dbi Debug Header
108 : // See http://ccimetadata.codeplex.com/SourceControl/changeset/view/52123#96529
109 : // From introspection, it looks like these are stream numbers or -1 if not
110 : // defined.
111 : struct DbiDbgHeader {
112 : int16 fpo;
113 : int16 exception;
114 : int16 fixup;
115 : int16 omap_to_src;
116 : int16 omap_from_src;
117 : int16 section_header;
118 : int16 token_rid_map;
119 : int16 x_data;
120 : int16 p_data;
121 : int16 new_fpo;
122 : int16 section_header_origin;
123 : };
124 : // We coerce a stream of bytes to this structure, so we require it to be
125 : // exactly 22 bytes in size.
126 : COMPILE_ASSERT_IS_POD_OF_SIZE(DbiDbgHeader, 22);
127 :
128 : // Dbi Section Contrib
129 : // Represent an element for the section contrib substream of the Dbi stream.
130 : struct DbiSectionContrib {
131 : int16 section;
132 : int16 pad1;
133 : int32 offset;
134 : int32 size;
135 : uint32 flags;
136 : int16 module;
137 : int16 pad2;
138 : uint32 data_crc;
139 : uint32 reloc_crc;
140 : };
141 : // We coerce a stream of bytes to this structure, so we require it to be
142 : // exactly 28 bytes in size.
143 : COMPILE_ASSERT_IS_POD_OF_SIZE(DbiSectionContrib, 28);
144 :
145 : // Dbi Module Info
146 : // Represent an element for the module info substream of the Dbi stream. This
147 : // struct doesn't contain the full module and object name.
148 : struct DbiModuleInfoBase {
149 : uint32 opened;
150 : DbiSectionContrib section;
151 : uint16 flags;
152 : int16 stream;
153 : uint32 symbol_bytes;
154 : uint32 old_lines_bytes;
155 : uint32 lines_bytes;
156 : int16 num_files;
157 : uint16 padding;
158 : uint32 offsets;
159 : uint32 num_source;
160 : uint32 num_compiler;
161 : // There are two trailing null-terminated 8-bit strings, the first being the
162 : // module_name and the second being the object_name. Then this structure is
163 : // padded with zeros to have a length that is a multiple of 4.
164 : };
165 : // We coerce a stream of bytes to this structure, so we require it to be
166 : // exactly 64 bytes in size.
167 : COMPILE_ASSERT_IS_POD_OF_SIZE(DbiModuleInfoBase, 64);
168 :
169 : // Dbi Section Map
170 : // Represent an element for the section map substream of the Dbi stream.
171 : struct DbiSectionMapItem {
172 : uint8 flags;
173 : uint8 section_type;
174 : // This field hasn't been deciphered but it is always 0x00000000 or 0xFFFFFFFF
175 : // and modifying it doesn't seem to invalidate the PDB.
176 : uint16 unknown_data_1[2];
177 : uint16 section_number;
178 : // Same thing as for unknown_data_1.
179 : uint16 unknown_data_2[2];
180 : // Value added to the address offset when calculating the RVA.
181 : uint32 rva_offset;
182 : uint32 section_length;
183 : };
184 : // We coerce a stream of bytes to this structure, so we require it to be
185 : // exactly 20 bytes in size.
186 : COMPILE_ASSERT_IS_POD_OF_SIZE(DbiSectionMapItem, 20);
187 :
188 : // Multi-Stream Format (MSF) Header
189 : // See http://code.google.com/p/pdbparser/wiki/MSF_Format
190 : struct PdbHeader {
191 : uint8 magic_string[kPdbHeaderMagicStringSize];
192 : uint32 page_size;
193 : uint32 free_page_map;
194 : uint32 num_pages;
195 : uint32 directory_size;
196 : uint32 reserved;
197 : uint32 root_pages[kPdbMaxDirPages];
198 : };
199 : COMPILE_ASSERT_IS_POD_OF_SIZE(PdbHeader, 344);
200 :
201 : // This is for parsing the FIXUP stream in PDB files generated with the
202 : // '/PROFILE' flag. The form of this struct was inferred from looking at
203 : // binary dumps of FIXUP streams and correlating them with the disassembly
204 : // of the image they refer to. These efforts are documented here:
205 : // http://go/syzygy-fixups
206 : struct PdbFixup {
207 : enum Type {
208 : TYPE_ABSOLUTE = 0x6,
209 : TYPE_RELATIVE = 0x7,
210 : TYPE_OFFSET_32BIT = 0xB,
211 : TYPE_OFFSET_8BIT = 0xD,
212 : TYPE_PC_RELATIVE = 0x14,
213 : };
214 :
215 : enum Flags {
216 : FLAG_IS_DATA = 0x4000,
217 : FLAG_REFERS_TO_CODE = 0x8000,
218 : FLAG_UNKNOWN = 0x3fff,
219 : };
220 :
221 : // The fixup header.
222 : union {
223 : uint32 header;
224 : struct {
225 : Type type:16;
226 : unsigned int flags:16;
227 : };
228 : };
229 : // The location of the reference in the image, stored as an RVA. The reference
230 : // will always take 4-bytes in the image.
231 : uint32 rva_location;
232 : // The base to which this reference is tied, stored as an RVA.
233 : uint32 rva_base;
234 :
235 : // This validates that the fixup is of a known type. Any FIXUP that does not
236 : // conform to a type that we have already witnessed in sample data will cause
237 : // this to return false.
238 : bool ValidHeader() const;
239 :
240 : // Refers to code as opposed to data.
241 E : bool refers_to_code() const { return (flags & FLAG_REFERS_TO_CODE) != 0; }
242 :
243 : // Is stored in data as opposed to being part of an instruction. This is
244 : // not always reported properly, as immediate operands to 'jmp'
245 : // instructions in thunks (__imp__function_name) set this bit.
246 E : bool is_data() const { return (flags & FLAG_IS_DATA) != 0; }
247 :
248 : // Returns true if the fixup is an offset from some address.
249 : bool is_offset() const;
250 :
251 : // This function returns the size of the reference as encoded at the
252 : // address 'rva_location'.
253 : size_t size() const;
254 : };
255 : // We coerce a stream of bytes to this structure, so we require it to be
256 : // exactly 12 bytes in size.
257 : COMPILE_ASSERT_IS_POD_OF_SIZE(PdbFixup, 12);
258 :
259 : } // namespace pdb
260 :
261 : #endif // SYZYGY_PDB_PDB_DATA_H_
|