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