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