gdiplus: Add GdipGetPenCompoundCount implementation.
[wine.git] / dlls / dbghelp / msc.c
blob872b0e70b58bf5b76f4b8f65d6502157a6de5e9c
1 /*
2 * File msc.c - read VC++ debug information from COFF and eventually
3 * from PDB files.
5 * Copyright (C) 1996, Eric Youngdale.
6 * Copyright (C) 1999-2000, Ulrich Weigand.
7 * Copyright (C) 2004-2009, Eric Pouech.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 * Note - this handles reading debug information for 32 bit applications
26 * that run under Windows-NT for example. I doubt that this would work well
27 * for 16 bit applications, but I don't think it really matters since the
28 * file format is different, and we should never get in here in such cases.
30 * TODO:
31 * Get 16 bit CV stuff working.
32 * Add symbol size to internal symbol table.
35 #define NONAMELESSUNION
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
42 #include <stdarg.h>
43 #include "windef.h"
44 #include "winbase.h"
45 #include "winternl.h"
47 #include "wine/exception.h"
48 #include "wine/debug.h"
49 #include "dbghelp_private.h"
50 #include "wine/mscvpdb.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_msc);
54 struct pdb_stream_name
56 const char* name;
57 unsigned index;
60 struct pdb_file_info
62 enum pdb_kind kind;
63 DWORD age;
64 HANDLE hMap;
65 const char* image;
66 struct pdb_stream_name* stream_dict;
67 unsigned fpoext_stream;
68 union
70 struct
72 DWORD timestamp;
73 struct PDB_JG_TOC* toc;
74 } jg;
75 struct
77 GUID guid;
78 struct PDB_DS_TOC* toc;
79 } ds;
80 } u;
83 /* FIXME: don't make it static */
84 #define CV_MAX_MODULES 32
85 struct pdb_module_info
87 unsigned used_subfiles;
88 struct pdb_file_info pdb_files[CV_MAX_MODULES];
91 #define loc_cv_local_range (loc_user + 0) /* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */
93 struct cv_module_snarf
95 const struct codeview_type_parse* ipi_ctp;
96 const struct CV_DebugSSubsectionHeader_t* dbgsubsect;
97 unsigned dbgsubsect_size;
98 const PDB_STRING_TABLE* strimage;
101 /*========================================================================
102 * Debug file access helper routines
105 static void dump(const void* ptr, unsigned len)
107 unsigned int i, j;
108 char msg[128];
109 const char* hexof = "0123456789abcdef";
110 const BYTE* x = ptr;
112 for (i = 0; i < len; i += 16)
114 sprintf(msg, "%08x: ", i);
115 memset(msg + 10, ' ', 3 * 16 + 1 + 16);
116 for (j = 0; j < min(16, len - i); j++)
118 msg[10 + 3 * j + 0] = hexof[x[i + j] >> 4];
119 msg[10 + 3 * j + 1] = hexof[x[i + j] & 15];
120 msg[10 + 3 * j + 2] = ' ';
121 msg[10 + 3 * 16 + 1 + j] = (x[i + j] >= 0x20 && x[i + j] < 0x7f) ?
122 x[i + j] : '.';
124 msg[10 + 3 * 16] = ' ';
125 msg[10 + 3 * 16 + 1 + 16] = '\0';
126 FIXME("%s\n", msg);
130 /*========================================================================
131 * Process CodeView type information.
134 static struct symt* cv_basic_types[T_MAXPREDEFINEDTYPE];
136 struct cv_defined_module
138 BOOL allowed;
139 unsigned int first_type_index;
140 unsigned int last_type_index;
141 struct symt** defined_types;
143 /* FIXME: don't make it static */
144 #define CV_MAX_MODULES 32
145 static struct cv_defined_module cv_zmodules[CV_MAX_MODULES];
146 static struct cv_defined_module*cv_current_module;
148 static void codeview_init_basic_types(struct module* module)
150 unsigned ptrsz = module->cpu->word_size;
153 * These are the common builtin types that are used by VC++.
155 cv_basic_types[T_NOTYPE] = NULL;
156 cv_basic_types[T_ABS] = NULL;
157 cv_basic_types[T_VOID] = &symt_get_basic(btVoid, 0)->symt; /* void */
158 cv_basic_types[T_CHAR] = &symt_get_basic(btInt, 1)->symt; /* signed char (and char in C) */
159 cv_basic_types[T_SHORT] = &symt_get_basic(btInt, 2)->symt; /* short int */
160 cv_basic_types[T_LONG] = &symt_get_basic(btLong, 4)->symt; /* long int */
161 cv_basic_types[T_QUAD] = &symt_get_basic(btInt, 8)->symt; /* long long int */
162 cv_basic_types[T_UCHAR] = &symt_get_basic(btUInt, 1)->symt; /* unsigned char */
163 cv_basic_types[T_USHORT] = &symt_get_basic(btUInt, 2)->symt; /* unsigned short */
164 cv_basic_types[T_ULONG] = &symt_get_basic(btULong, 4)->symt; /* unsigned long */
165 cv_basic_types[T_UQUAD] = &symt_get_basic(btUInt, 8)->symt; /* unsigned long long */
166 cv_basic_types[T_BOOL08] = &symt_get_basic(btBool, 1)->symt; /* BOOL08 */
167 cv_basic_types[T_BOOL16] = &symt_get_basic(btBool, 2)->symt; /* BOOL16 */
168 cv_basic_types[T_BOOL32] = &symt_get_basic(btBool, 4)->symt; /* BOOL32 */
169 cv_basic_types[T_BOOL64] = &symt_get_basic(btBool, 8)->symt; /* BOOL64 */
170 cv_basic_types[T_REAL32] = &symt_get_basic(btFloat, 4)->symt; /* float */
171 cv_basic_types[T_REAL64] = &symt_get_basic(btFloat, 8)->symt; /* double */
172 cv_basic_types[T_REAL80] = &symt_get_basic(btFloat, 10)->symt; /* long double */
173 cv_basic_types[T_RCHAR] = &symt_get_basic(btChar, 1)->symt; /* "real" char (char in C++) */
174 cv_basic_types[T_WCHAR] = &symt_get_basic(btWChar, 2)->symt; /* char8_t */
175 cv_basic_types[T_CHAR16] = &symt_get_basic(btChar16, 2)->symt; /* char16_t */
176 cv_basic_types[T_CHAR32] = &symt_get_basic(btChar32, 4)->symt; /* char32_t */
177 cv_basic_types[T_CHAR8] = &symt_get_basic(btChar8, 1)->symt; /* char8_t */
178 cv_basic_types[T_INT2] = &symt_get_basic(btInt, 2)->symt; /* INT2 */
179 cv_basic_types[T_UINT2] = &symt_get_basic(btUInt, 2)->symt; /* UINT2 */
180 cv_basic_types[T_INT4] = &symt_get_basic(btInt, 4)->symt; /* INT4 */
181 cv_basic_types[T_UINT4] = &symt_get_basic(btUInt, 4)->symt; /* UINT4 */
182 cv_basic_types[T_INT8] = &symt_get_basic(btInt, 8)->symt; /* INT8 */
183 cv_basic_types[T_UINT8] = &symt_get_basic(btUInt, 8)->symt; /* UINT8 */
184 cv_basic_types[T_HRESULT]= &symt_get_basic(btUInt, 4)->symt; /* HRESULT */
186 cv_basic_types[T_32PVOID] = &symt_new_pointer(module, cv_basic_types[T_VOID], 4)->symt;
187 cv_basic_types[T_32PCHAR] = &symt_new_pointer(module, cv_basic_types[T_CHAR], 4)->symt;
188 cv_basic_types[T_32PSHORT] = &symt_new_pointer(module, cv_basic_types[T_SHORT], 4)->symt;
189 cv_basic_types[T_32PLONG] = &symt_new_pointer(module, cv_basic_types[T_LONG], 4)->symt;
190 cv_basic_types[T_32PQUAD] = &symt_new_pointer(module, cv_basic_types[T_QUAD], 4)->symt;
191 cv_basic_types[T_32PUCHAR] = &symt_new_pointer(module, cv_basic_types[T_UCHAR], 4)->symt;
192 cv_basic_types[T_32PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT], 4)->symt;
193 cv_basic_types[T_32PULONG] = &symt_new_pointer(module, cv_basic_types[T_ULONG], 4)->symt;
194 cv_basic_types[T_32PUQUAD] = &symt_new_pointer(module, cv_basic_types[T_UQUAD], 4)->symt;
195 cv_basic_types[T_32PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08], 4)->symt;
196 cv_basic_types[T_32PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16], 4)->symt;
197 cv_basic_types[T_32PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32], 4)->symt;
198 cv_basic_types[T_32PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64], 4)->symt;
199 cv_basic_types[T_32PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32], 4)->symt;
200 cv_basic_types[T_32PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64], 4)->symt;
201 cv_basic_types[T_32PREAL80] = &symt_new_pointer(module, cv_basic_types[T_REAL80], 4)->symt;
202 cv_basic_types[T_32PRCHAR] = &symt_new_pointer(module, cv_basic_types[T_RCHAR], 4)->symt;
203 cv_basic_types[T_32PWCHAR] = &symt_new_pointer(module, cv_basic_types[T_WCHAR], 4)->symt;
204 cv_basic_types[T_32PCHAR16] = &symt_new_pointer(module, cv_basic_types[T_CHAR16], 4)->symt;
205 cv_basic_types[T_32PCHAR32] = &symt_new_pointer(module, cv_basic_types[T_CHAR32], 4)->symt;
206 cv_basic_types[T_32PCHAR8] = &symt_new_pointer(module, cv_basic_types[T_CHAR8], 4)->symt;
207 cv_basic_types[T_32PINT2] = &symt_new_pointer(module, cv_basic_types[T_INT2], 4)->symt;
208 cv_basic_types[T_32PUINT2] = &symt_new_pointer(module, cv_basic_types[T_UINT2], 4)->symt;
209 cv_basic_types[T_32PINT4] = &symt_new_pointer(module, cv_basic_types[T_INT4], 4)->symt;
210 cv_basic_types[T_32PUINT4] = &symt_new_pointer(module, cv_basic_types[T_UINT4], 4)->symt;
211 cv_basic_types[T_32PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8], 4)->symt;
212 cv_basic_types[T_32PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8], 4)->symt;
213 cv_basic_types[T_32PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT], 4)->symt;
215 cv_basic_types[T_64PVOID] = &symt_new_pointer(module, cv_basic_types[T_VOID], 8)->symt;
216 cv_basic_types[T_64PCHAR] = &symt_new_pointer(module, cv_basic_types[T_CHAR], 8)->symt;
217 cv_basic_types[T_64PSHORT] = &symt_new_pointer(module, cv_basic_types[T_SHORT], 8)->symt;
218 cv_basic_types[T_64PLONG] = &symt_new_pointer(module, cv_basic_types[T_LONG], 8)->symt;
219 cv_basic_types[T_64PQUAD] = &symt_new_pointer(module, cv_basic_types[T_QUAD], 8)->symt;
220 cv_basic_types[T_64PUCHAR] = &symt_new_pointer(module, cv_basic_types[T_UCHAR], 8)->symt;
221 cv_basic_types[T_64PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT], 8)->symt;
222 cv_basic_types[T_64PULONG] = &symt_new_pointer(module, cv_basic_types[T_ULONG], 8)->symt;
223 cv_basic_types[T_64PUQUAD] = &symt_new_pointer(module, cv_basic_types[T_UQUAD], 8)->symt;
224 cv_basic_types[T_64PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08], 8)->symt;
225 cv_basic_types[T_64PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16], 8)->symt;
226 cv_basic_types[T_64PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32], 8)->symt;
227 cv_basic_types[T_64PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64], 8)->symt;
228 cv_basic_types[T_64PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32], 8)->symt;
229 cv_basic_types[T_64PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64], 8)->symt;
230 cv_basic_types[T_64PREAL80] = &symt_new_pointer(module, cv_basic_types[T_REAL80], 8)->symt;
231 cv_basic_types[T_64PRCHAR] = &symt_new_pointer(module, cv_basic_types[T_RCHAR], 8)->symt;
232 cv_basic_types[T_64PWCHAR] = &symt_new_pointer(module, cv_basic_types[T_WCHAR], 8)->symt;
233 cv_basic_types[T_64PCHAR16] = &symt_new_pointer(module, cv_basic_types[T_CHAR16], 8)->symt;
234 cv_basic_types[T_64PCHAR32] = &symt_new_pointer(module, cv_basic_types[T_CHAR32], 8)->symt;
235 cv_basic_types[T_64PCHAR8] = &symt_new_pointer(module, cv_basic_types[T_CHAR8], 8)->symt;
236 cv_basic_types[T_64PINT2] = &symt_new_pointer(module, cv_basic_types[T_INT2], 8)->symt;
237 cv_basic_types[T_64PUINT2] = &symt_new_pointer(module, cv_basic_types[T_UINT2], 8)->symt;
238 cv_basic_types[T_64PINT4] = &symt_new_pointer(module, cv_basic_types[T_INT4], 8)->symt;
239 cv_basic_types[T_64PUINT4] = &symt_new_pointer(module, cv_basic_types[T_UINT4], 8)->symt;
240 cv_basic_types[T_64PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8], 8)->symt;
241 cv_basic_types[T_64PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8], 8)->symt;
242 cv_basic_types[T_64PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT], 8)->symt;
244 cv_basic_types[T_PVOID] = &symt_new_pointer(module, cv_basic_types[T_VOID], ptrsz)->symt;
245 cv_basic_types[T_PCHAR] = &symt_new_pointer(module, cv_basic_types[T_CHAR], ptrsz)->symt;
246 cv_basic_types[T_PSHORT] = &symt_new_pointer(module, cv_basic_types[T_SHORT], ptrsz)->symt;
247 cv_basic_types[T_PLONG] = &symt_new_pointer(module, cv_basic_types[T_LONG], ptrsz)->symt;
248 cv_basic_types[T_PQUAD] = &symt_new_pointer(module, cv_basic_types[T_QUAD], ptrsz)->symt;
249 cv_basic_types[T_PUCHAR] = &symt_new_pointer(module, cv_basic_types[T_UCHAR], ptrsz)->symt;
250 cv_basic_types[T_PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT], ptrsz)->symt;
251 cv_basic_types[T_PULONG] = &symt_new_pointer(module, cv_basic_types[T_ULONG], ptrsz)->symt;
252 cv_basic_types[T_PUQUAD] = &symt_new_pointer(module, cv_basic_types[T_UQUAD], ptrsz)->symt;
253 cv_basic_types[T_PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08], ptrsz)->symt;
254 cv_basic_types[T_PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16], ptrsz)->symt;
255 cv_basic_types[T_PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32], ptrsz)->symt;
256 cv_basic_types[T_PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64], ptrsz)->symt;
257 cv_basic_types[T_PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32], ptrsz)->symt;
258 cv_basic_types[T_PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64], ptrsz)->symt;
259 cv_basic_types[T_PREAL80] = &symt_new_pointer(module, cv_basic_types[T_REAL80], ptrsz)->symt;
260 cv_basic_types[T_PRCHAR] = &symt_new_pointer(module, cv_basic_types[T_RCHAR], ptrsz)->symt;
261 cv_basic_types[T_PWCHAR] = &symt_new_pointer(module, cv_basic_types[T_WCHAR], ptrsz)->symt;
262 cv_basic_types[T_PCHAR16] = &symt_new_pointer(module, cv_basic_types[T_CHAR16], ptrsz)->symt;
263 cv_basic_types[T_PCHAR32] = &symt_new_pointer(module, cv_basic_types[T_CHAR32], ptrsz)->symt;
264 cv_basic_types[T_PCHAR8] = &symt_new_pointer(module, cv_basic_types[T_CHAR8], ptrsz)->symt;
265 cv_basic_types[T_PINT2] = &symt_new_pointer(module, cv_basic_types[T_INT2], ptrsz)->symt;
266 cv_basic_types[T_PUINT2] = &symt_new_pointer(module, cv_basic_types[T_UINT2], ptrsz)->symt;
267 cv_basic_types[T_PINT4] = &symt_new_pointer(module, cv_basic_types[T_INT4], ptrsz)->symt;
268 cv_basic_types[T_PUINT4] = &symt_new_pointer(module, cv_basic_types[T_UINT4], ptrsz)->symt;
269 cv_basic_types[T_PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8], ptrsz)->symt;
270 cv_basic_types[T_PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8], ptrsz)->symt;
273 static int leaf_as_variant(VARIANT* v, const unsigned short int* leaf)
275 unsigned short int type = *leaf++;
276 int length = 2;
278 if (type < LF_NUMERIC)
280 V_VT(v) = VT_UINT;
281 V_UINT(v) = type;
283 else
285 switch (type)
287 case LF_CHAR:
288 length += 1;
289 V_VT(v) = VT_I1;
290 V_I1(v) = *(const char*)leaf;
291 break;
293 case LF_SHORT:
294 length += 2;
295 V_VT(v) = VT_I2;
296 V_I2(v) = *(const short*)leaf;
297 break;
299 case LF_USHORT:
300 length += 2;
301 V_VT(v) = VT_UI2;
302 V_UI2(v) = *leaf;
303 break;
305 case LF_LONG:
306 length += 4;
307 V_VT(v) = VT_I4;
308 V_I4(v) = *(const int*)leaf;
309 break;
311 case LF_ULONG:
312 length += 4;
313 V_VT(v) = VT_UI4;
314 V_UI4(v) = *(const unsigned int*)leaf;
315 break;
317 case LF_QUADWORD:
318 length += 8;
319 V_VT(v) = VT_I8;
320 V_I8(v) = *(const long long int*)leaf;
321 break;
323 case LF_UQUADWORD:
324 length += 8;
325 V_VT(v) = VT_UI8;
326 V_UI8(v) = *(const long long unsigned int*)leaf;
327 break;
329 case LF_REAL32:
330 length += 4;
331 V_VT(v) = VT_R4;
332 V_R4(v) = *(const float*)leaf;
333 break;
335 case LF_REAL48:
336 FIXME("Unsupported numeric leaf type %04x\n", type);
337 length += 6;
338 V_VT(v) = VT_EMPTY; /* FIXME */
339 break;
341 case LF_REAL64:
342 length += 8;
343 V_VT(v) = VT_R8;
344 V_R8(v) = *(const double*)leaf;
345 break;
347 case LF_REAL80:
348 FIXME("Unsupported numeric leaf type %04x\n", type);
349 length += 10;
350 V_VT(v) = VT_EMPTY; /* FIXME */
351 break;
353 case LF_REAL128:
354 FIXME("Unsupported numeric leaf type %04x\n", type);
355 length += 16;
356 V_VT(v) = VT_EMPTY; /* FIXME */
357 break;
359 case LF_COMPLEX32:
360 FIXME("Unsupported numeric leaf type %04x\n", type);
361 length += 4;
362 V_VT(v) = VT_EMPTY; /* FIXME */
363 break;
365 case LF_COMPLEX64:
366 FIXME("Unsupported numeric leaf type %04x\n", type);
367 length += 8;
368 V_VT(v) = VT_EMPTY; /* FIXME */
369 break;
371 case LF_COMPLEX80:
372 FIXME("Unsupported numeric leaf type %04x\n", type);
373 length += 10;
374 break;
376 case LF_COMPLEX128:
377 FIXME("Unsupported numeric leaf type %04x\n", type);
378 length += 16;
379 V_VT(v) = VT_EMPTY; /* FIXME */
380 break;
382 case LF_VARSTRING:
383 FIXME("Unsupported numeric leaf type %04x\n", type);
384 length += 2 + *leaf;
385 V_VT(v) = VT_EMPTY; /* FIXME */
386 break;
388 default:
389 FIXME("Unknown numeric leaf type %04x\n", type);
390 V_VT(v) = VT_EMPTY; /* FIXME */
391 break;
395 return length;
398 static int numeric_leaf(int* value, const unsigned short int* leaf)
400 unsigned short int type = *leaf++;
401 int length = 2;
403 if (type < LF_NUMERIC)
405 *value = type;
407 else
409 switch (type)
411 case LF_CHAR:
412 length += 1;
413 *value = *(const char*)leaf;
414 break;
416 case LF_SHORT:
417 length += 2;
418 *value = *(const short*)leaf;
419 break;
421 case LF_USHORT:
422 length += 2;
423 *value = *leaf;
424 break;
426 case LF_LONG:
427 length += 4;
428 *value = *(const int*)leaf;
429 break;
431 case LF_ULONG:
432 length += 4;
433 *value = *(const unsigned int*)leaf;
434 break;
436 case LF_QUADWORD:
437 case LF_UQUADWORD:
438 FIXME("Unsupported numeric leaf type %04x\n", type);
439 length += 8;
440 *value = 0; /* FIXME */
441 break;
443 case LF_REAL32:
444 FIXME("Unsupported numeric leaf type %04x\n", type);
445 length += 4;
446 *value = 0; /* FIXME */
447 break;
449 case LF_REAL48:
450 FIXME("Unsupported numeric leaf type %04x\n", type);
451 length += 6;
452 *value = 0; /* FIXME */
453 break;
455 case LF_REAL64:
456 FIXME("Unsupported numeric leaf type %04x\n", type);
457 length += 8;
458 *value = 0; /* FIXME */
459 break;
461 case LF_REAL80:
462 FIXME("Unsupported numeric leaf type %04x\n", type);
463 length += 10;
464 *value = 0; /* FIXME */
465 break;
467 case LF_REAL128:
468 FIXME("Unsupported numeric leaf type %04x\n", type);
469 length += 16;
470 *value = 0; /* FIXME */
471 break;
473 case LF_COMPLEX32:
474 FIXME("Unsupported numeric leaf type %04x\n", type);
475 length += 4;
476 *value = 0; /* FIXME */
477 break;
479 case LF_COMPLEX64:
480 FIXME("Unsupported numeric leaf type %04x\n", type);
481 length += 8;
482 *value = 0; /* FIXME */
483 break;
485 case LF_COMPLEX80:
486 FIXME("Unsupported numeric leaf type %04x\n", type);
487 length += 10;
488 *value = 0; /* FIXME */
489 break;
491 case LF_COMPLEX128:
492 FIXME("Unsupported numeric leaf type %04x\n", type);
493 length += 16;
494 *value = 0; /* FIXME */
495 break;
497 case LF_VARSTRING:
498 FIXME("Unsupported numeric leaf type %04x\n", type);
499 length += 2 + *leaf;
500 *value = 0; /* FIXME */
501 break;
503 default:
504 FIXME("Unknown numeric leaf type %04x\n", type);
505 *value = 0;
506 break;
510 return length;
513 /* convert a pascal string (as stored in debug information) into
514 * a C string (null terminated).
516 static const char* terminate_string(const struct p_string* p_name)
518 static char symname[256];
520 memcpy(symname, p_name->name, p_name->namelen);
521 symname[p_name->namelen] = '\0';
523 return (!*symname || strcmp(symname, "__unnamed") == 0) ? NULL : symname;
526 static struct symt* codeview_get_type(unsigned int typeno, BOOL quiet)
528 struct symt* symt = NULL;
531 * Convert Codeview type numbers into something we can grok internally.
532 * Numbers < T_MAXPREDEFINEDTYPE all fixed builtin types.
533 * Numbers from T_FIRSTDEFINABLETYPE and up are all user defined (structs, etc).
535 if (typeno < T_MAXPREDEFINEDTYPE)
536 symt = cv_basic_types[typeno];
537 else if (typeno >= T_FIRSTDEFINABLETYPE)
539 unsigned mod_index = typeno >> 24;
540 unsigned mod_typeno = typeno & 0x00FFFFFF;
541 struct cv_defined_module* mod;
543 mod = (mod_index == 0) ? cv_current_module : &cv_zmodules[mod_index];
545 if (mod_index >= CV_MAX_MODULES || !mod->allowed)
546 FIXME("Module of index %d isn't loaded yet (%x)\n", mod_index, typeno);
547 else
549 if (mod_typeno >= mod->first_type_index && mod_typeno < mod->last_type_index)
550 symt = mod->defined_types[mod_typeno - mod->first_type_index];
553 if (!quiet && !symt && typeno) FIXME("Returning NULL symt for type-id %x\n", typeno);
554 return symt;
557 struct hash_link
559 unsigned id;
560 struct hash_link* next;
563 struct codeview_type_parse
565 struct module* module;
566 PDB_TYPES header;
567 const BYTE* table;
568 const DWORD* offset; /* typeindex => offset in 'table' */
569 BYTE* hash_stream; /* content of stream header.hash_file */
570 struct hash_link** hash; /* hash_table (deserialized from PDB hash table) */
571 struct hash_link* alloc_hash; /* allocated hash_link (id => hash_link) */
574 static inline const void* codeview_jump_to_type(const struct codeview_type_parse* ctp, DWORD idx)
576 return (idx >= ctp->header.first_index && idx < ctp->header.last_index) ?
577 ctp->table + ctp->offset[idx - ctp->header.first_index] : NULL;
580 static int codeview_add_type(unsigned int typeno, struct symt* dt)
582 unsigned idx;
583 if (!cv_current_module)
585 FIXME("Adding %x to non allowed module\n", typeno);
586 return FALSE;
588 if ((typeno >> 24) != 0)
589 FIXME("No module index while inserting type-id assumption is wrong %x\n",
590 typeno);
591 if (typeno < cv_current_module->first_type_index || typeno >= cv_current_module->last_type_index)
593 FIXME("Type number %x out of bounds [%x, %x)\n",
594 typeno, cv_current_module->first_type_index, typeno >= cv_current_module->last_type_index);
595 return FALSE;
597 idx = typeno - cv_current_module->first_type_index;
598 if (cv_current_module->defined_types[idx])
600 if (cv_current_module->defined_types[idx] != dt)
601 FIXME("Overwriting at %x\n", typeno);
603 cv_current_module->defined_types[idx] = dt;
604 return TRUE;
607 static void codeview_clear_type_table(void)
609 int i;
611 for (i = 0; i < CV_MAX_MODULES; i++)
613 if (cv_zmodules[i].allowed)
614 free(cv_zmodules[i].defined_types);
615 cv_zmodules[i].allowed = FALSE;
616 cv_zmodules[i].defined_types = NULL;
617 cv_zmodules[i].first_type_index = 0;
618 cv_zmodules[i].last_type_index = 0;
620 cv_current_module = NULL;
623 static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp,
624 unsigned curr_type,
625 const union codeview_type* type);
627 static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp,
628 unsigned typeno)
630 struct symt* symt;
631 const union codeview_type* p;
633 if (!typeno) return NULL;
634 if ((symt = codeview_get_type(typeno, TRUE))) return symt;
636 if ((p = codeview_jump_to_type(ctp, typeno)))
637 symt = codeview_parse_one_type(ctp, typeno, p);
638 if (!symt) FIXME("Couldn't load type %x\n", typeno);
639 return symt;
642 static UINT32 codeview_compute_hash(const char* ptr, unsigned len)
644 const char* last = ptr + len;
645 UINT32 ret = 0;
647 while (ptr + sizeof(UINT32) <= last)
649 ret ^= *(UINT32*)ptr;
650 ptr += sizeof(UINT32);
652 if (ptr + sizeof(UINT16) <= last)
654 ret ^= *(UINT16*)ptr;
655 ptr += sizeof(UINT16);
657 if (ptr + sizeof(BYTE) <= last)
658 ret ^= *(BYTE*)ptr;
659 ret |= 0x20202020;
660 ret ^= (ret >> 11);
661 return ret ^ (ret >> 16);
664 /* We call 'forwardable' a type which can have a forward declaration, and we need to merge
665 * (when they both exist) the type record of the forward declaration and the type record
666 * of the full definition into a single symt.
668 static BOOL codeview_is_forwardable_type(const union codeview_type* type)
670 switch (type->generic.id)
672 case LF_CLASS_V1:
673 case LF_CLASS_V2:
674 case LF_CLASS_V3:
675 case LF_ENUM_V1:
676 case LF_ENUM_V2:
677 case LF_ENUM_V3:
678 case LF_STRUCTURE_V1:
679 case LF_STRUCTURE_V2:
680 case LF_STRUCTURE_V3:
681 case LF_UNION_V1:
682 case LF_UNION_V2:
683 case LF_UNION_V3:
684 return TRUE;
685 default:
686 return FALSE;
690 static BOOL codeview_type_is_forward(const union codeview_type* cvtype)
692 cv_property_t property;
694 switch (cvtype->generic.id)
696 case LF_STRUCTURE_V1:
697 case LF_CLASS_V1: property = cvtype->struct_v1.property; break;
698 case LF_STRUCTURE_V2:
699 case LF_CLASS_V2: property = cvtype->struct_v2.property; break;
700 case LF_STRUCTURE_V3:
701 case LF_CLASS_V3: property = cvtype->struct_v3.property; break;
702 case LF_UNION_V1: property = cvtype->union_v1.property; break;
703 case LF_UNION_V2: property = cvtype->union_v2.property; break;
704 case LF_UNION_V3: property = cvtype->union_v3.property; break;
705 case LF_ENUM_V1: property = cvtype->enumeration_v1.property; break;
706 case LF_ENUM_V2: property = cvtype->enumeration_v1.property; break;
707 case LF_ENUM_V3: property = cvtype->enumeration_v1.property; break;
708 default:
709 return FALSE;
711 return property.is_forward_defn;
714 static BOOL codeview_type_extract_name(const union codeview_type* cvtype,
715 const char** name, unsigned* len, const char** decorated_name)
717 int value, leaf_len;
718 const struct p_string* p_name = NULL;
719 const char* c_name = NULL;
720 BOOL decorated = FALSE;
722 switch (cvtype->generic.id)
724 case LF_STRUCTURE_V1:
725 case LF_CLASS_V1:
726 leaf_len = numeric_leaf(&value, &cvtype->struct_v1.structlen);
727 p_name = (const struct p_string*)((const unsigned char*)&cvtype->struct_v1.structlen + leaf_len);
728 break;
729 case LF_STRUCTURE_V2:
730 case LF_CLASS_V2:
731 leaf_len = numeric_leaf(&value, &cvtype->struct_v2.structlen);
732 p_name = (const struct p_string*)((const unsigned char*)&cvtype->struct_v2.structlen + leaf_len);
733 break;
734 case LF_STRUCTURE_V3:
735 case LF_CLASS_V3:
736 leaf_len = numeric_leaf(&value, &cvtype->struct_v3.structlen);
737 c_name = (const char*)&cvtype->struct_v3.structlen + leaf_len;
738 decorated = cvtype->struct_v3.property.has_decorated_name;
739 break;
740 case LF_UNION_V1:
741 leaf_len = numeric_leaf(&value, &cvtype->union_v1.un_len);
742 p_name = (const struct p_string*)((const unsigned char*)&cvtype->union_v1.un_len + leaf_len);
743 break;
744 case LF_UNION_V2:
745 leaf_len = numeric_leaf(&value, &cvtype->union_v2.un_len);
746 p_name = (const struct p_string*)((const unsigned char*)&cvtype->union_v2.un_len + leaf_len);
747 break;
748 case LF_UNION_V3:
749 leaf_len = numeric_leaf(&value, &cvtype->union_v3.un_len);
750 c_name = (const char*)&cvtype->union_v3.un_len + leaf_len;
751 decorated = cvtype->union_v3.property.has_decorated_name;
752 break;
753 case LF_ENUM_V1:
754 p_name = &cvtype->enumeration_v1.p_name;
755 break;
756 case LF_ENUM_V2:
757 p_name = &cvtype->enumeration_v2.p_name;
758 break;
759 case LF_ENUM_V3:
760 c_name = cvtype->enumeration_v3.name;
761 decorated = cvtype->union_v3.property.has_decorated_name;
762 break;
763 default:
764 return FALSE;
766 if (p_name)
768 *name = p_name->name;
769 *len = p_name->namelen;
770 *decorated_name = NULL;
771 return TRUE;
773 if (c_name)
775 *name = c_name;
776 *len = strlen(c_name);
777 *decorated_name = decorated ? (c_name + *len + 1) : NULL;
778 return TRUE;
780 return FALSE;
783 static unsigned pdb_read_hash_value(const struct codeview_type_parse* ctp, unsigned idx)
785 const void* where = ctp->hash_stream + ctp->header.hash_offset + (idx - ctp->header.first_index) * ctp->header.hash_size;
786 switch (ctp->header.hash_size)
788 case 2: return *(unsigned short*)where;
789 case 4: return *(unsigned*)where;
791 return 0;
794 static BOOL codeview_resolve_forward_type(struct codeview_type_parse* ctp, const union codeview_type* cvref,
795 unsigned reftype, unsigned *impl_type)
797 const union codeview_type* cvdecl;
798 struct hash_link* hl;
799 const char* nameref;
800 const char* decoratedref;
801 unsigned lenref;
802 unsigned hash;
804 /* Unfortunately, hash of forward defs are computed on the whole type record, not its name
805 * (unlike hash of UDT & enum implementations which is based primarily on the name... sigh)
806 * So compute the hash of the expected implementation.
808 if (!codeview_type_extract_name(cvref, &nameref, &lenref, &decoratedref)) return FALSE;
809 hash = codeview_compute_hash(nameref, lenref) % ctp->header.hash_num_buckets;
811 for (hl = ctp->hash[hash]; hl; hl = hl->next)
813 if (hl->id == reftype) continue;
814 cvdecl = codeview_jump_to_type(ctp, hl->id);
815 if (cvdecl && !codeview_type_is_forward(cvdecl) && cvref->generic.id == cvdecl->generic.id)
817 const char* namedecl;
818 const char* decorateddecl;
819 unsigned lendecl;
821 if (codeview_type_extract_name(cvdecl, &namedecl, &lendecl, &decorateddecl) &&
822 ((decoratedref && decorateddecl && !strcmp(decoratedref, decorateddecl)) ||
823 (!decoratedref && !decorateddecl && lenref == lendecl && !memcmp(nameref, namedecl, lenref))))
825 TRACE("mapping forward type %.*s (%s) %x into %x\n", lenref, nameref, debugstr_a(decoratedref), reftype, hl->id);
826 *impl_type = hl->id;
827 return TRUE;
831 return FALSE;
834 static struct symt* codeview_add_type_pointer(struct codeview_type_parse* ctp,
835 unsigned int pointee_type)
837 struct symt* pointee;
839 pointee = codeview_fetch_type(ctp, pointee_type);
840 if (!pointee) return NULL;
841 return &symt_new_pointer(ctp->module, pointee, ctp->module->cpu->word_size)->symt;
844 static struct symt* codeview_add_type_array(struct codeview_type_parse* ctp,
845 const char* name,
846 unsigned int elemtype,
847 unsigned int indextype,
848 unsigned int arr_len)
850 struct symt* elem = codeview_fetch_type(ctp, elemtype);
851 struct symt* index = codeview_fetch_type(ctp, indextype);
852 DWORD64 elem_size;
853 DWORD count = 0;
855 if (symt_get_info(ctp->module, elem, TI_GET_LENGTH, &elem_size) && elem_size)
857 if (arr_len % (DWORD)elem_size)
858 FIXME("array size should be a multiple of element size %u %I64u\n", arr_len, elem_size);
859 count = arr_len / (unsigned)elem_size;
861 return &symt_new_array(ctp->module, 0, count, elem, index)->symt;
864 static BOOL codeview_add_type_enum_field_list(struct codeview_type_parse* ctp,
865 struct symt_enum* symt,
866 unsigned typeno)
868 const union codeview_reftype* ref_type;
869 const unsigned char* ptr;
870 const unsigned char* last;
871 const union codeview_fieldtype* type;
873 if (!typeno) return TRUE;
874 if (!(ref_type = codeview_jump_to_type(ctp, typeno))) return FALSE;
875 ptr = ref_type->fieldlist.list;
876 last = (const BYTE*)ref_type + ref_type->generic.len + 2;
878 while (ptr < last)
880 if (*ptr >= 0xf0) /* LF_PAD... */
882 ptr += *ptr & 0x0f;
883 continue;
886 type = (const union codeview_fieldtype*)ptr;
888 switch (type->generic.id)
890 case LF_ENUMERATE_V1:
892 int value, vlen = numeric_leaf(&value, &type->enumerate_v1.value);
893 const struct p_string* p_name = (const struct p_string*)((const unsigned char*)&type->enumerate_v1.value + vlen);
895 symt_add_enum_element(ctp->module, symt, terminate_string(p_name), value);
896 ptr += 2 + 2 + vlen + (1 + p_name->namelen);
897 break;
899 case LF_ENUMERATE_V3:
901 int value, vlen = numeric_leaf(&value, &type->enumerate_v3.value);
902 const char* name = (const char*)&type->enumerate_v3.value + vlen;
904 symt_add_enum_element(ctp->module, symt, name, value);
905 ptr += 2 + 2 + vlen + (1 + strlen(name));
906 break;
909 case LF_INDEX_V1:
910 if (!codeview_add_type_enum_field_list(ctp, symt, type->index_v1.ref))
911 return FALSE;
912 ptr += 2 + 2;
913 break;
915 case LF_INDEX_V2:
916 if (!codeview_add_type_enum_field_list(ctp, symt, type->index_v2.ref))
917 return FALSE;
918 ptr += 2 + 2 + 4;
919 break;
921 default:
922 FIXME("Unsupported type %04x in ENUM field list\n", type->generic.id);
923 return FALSE;
926 return TRUE;
929 static void codeview_add_udt_element(struct codeview_type_parse* ctp,
930 struct symt_udt* symt, const char* name,
931 int value, unsigned type)
933 struct symt* subtype;
934 const union codeview_reftype*cv_type;
936 if ((cv_type = codeview_jump_to_type(ctp, type)))
938 switch (cv_type->generic.id)
940 case LF_BITFIELD_V1:
941 symt_add_udt_element(ctp->module, symt, name,
942 codeview_fetch_type(ctp, cv_type->bitfield_v1.type),
943 value, cv_type->bitfield_v1.bitoff,
944 cv_type->bitfield_v1.nbits);
945 return;
946 case LF_BITFIELD_V2:
947 symt_add_udt_element(ctp->module, symt, name,
948 codeview_fetch_type(ctp, cv_type->bitfield_v2.type),
949 value, cv_type->bitfield_v2.bitoff,
950 cv_type->bitfield_v2.nbits);
951 return;
954 subtype = codeview_fetch_type(ctp, type);
956 if (subtype)
958 DWORD64 elem_size = 0;
959 symt_get_info(ctp->module, subtype, TI_GET_LENGTH, &elem_size);
960 symt_add_udt_element(ctp->module, symt, name, subtype, value, 0, 0);
964 static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp,
965 struct symt_udt* symt,
966 unsigned fieldlistno)
968 const unsigned char* ptr;
969 const unsigned char* last;
970 int value, leaf_len;
971 const struct p_string* p_name;
972 const char* c_name;
973 const union codeview_reftype*type_ref;
974 const union codeview_fieldtype* type;
976 if (!fieldlistno) return TRUE;
977 type_ref = codeview_jump_to_type(ctp, fieldlistno);
978 ptr = type_ref->fieldlist.list;
979 last = (const BYTE*)type_ref + type_ref->generic.len + 2;
981 while (ptr < last)
983 if (*ptr >= 0xf0) /* LF_PAD... */
985 ptr += *ptr & 0x0f;
986 continue;
989 type = (const union codeview_fieldtype*)ptr;
991 switch (type->generic.id)
993 case LF_BCLASS_V1:
994 leaf_len = numeric_leaf(&value, &type->bclass_v1.offset);
996 /* FIXME: ignored for now */
998 ptr += 2 + 2 + 2 + leaf_len;
999 break;
1001 case LF_BCLASS_V2:
1002 leaf_len = numeric_leaf(&value, &type->bclass_v2.offset);
1004 /* FIXME: ignored for now */
1006 ptr += 2 + 2 + 4 + leaf_len;
1007 break;
1009 case LF_VBCLASS_V1:
1010 case LF_IVBCLASS_V1:
1012 const unsigned short int* p_vboff;
1013 int vpoff, vplen;
1014 leaf_len = numeric_leaf(&value, &type->vbclass_v1.vbpoff);
1015 p_vboff = (const unsigned short int*)((const char*)&type->vbclass_v1.vbpoff + leaf_len);
1016 vplen = numeric_leaf(&vpoff, p_vboff);
1018 /* FIXME: ignored for now */
1020 ptr += 2 + 2 + 2 + 2 + leaf_len + vplen;
1022 break;
1024 case LF_VBCLASS_V2:
1025 case LF_IVBCLASS_V2:
1027 const unsigned short int* p_vboff;
1028 int vpoff, vplen;
1029 leaf_len = numeric_leaf(&value, &type->vbclass_v2.vbpoff);
1030 p_vboff = (const unsigned short int*)((const char*)&type->vbclass_v2.vbpoff + leaf_len);
1031 vplen = numeric_leaf(&vpoff, p_vboff);
1033 /* FIXME: ignored for now */
1035 ptr += 2 + 2 + 4 + 4 + leaf_len + vplen;
1037 break;
1039 case LF_MEMBER_V1:
1040 leaf_len = numeric_leaf(&value, &type->member_v1.offset);
1041 p_name = (const struct p_string*)((const char*)&type->member_v1.offset + leaf_len);
1043 codeview_add_udt_element(ctp, symt, terminate_string(p_name), value,
1044 type->member_v1.type);
1046 ptr += 2 + 2 + 2 + leaf_len + (1 + p_name->namelen);
1047 break;
1049 case LF_MEMBER_V2:
1050 leaf_len = numeric_leaf(&value, &type->member_v2.offset);
1051 p_name = (const struct p_string*)((const unsigned char*)&type->member_v2.offset + leaf_len);
1053 codeview_add_udt_element(ctp, symt, terminate_string(p_name), value,
1054 type->member_v2.type);
1056 ptr += 2 + 2 + 4 + leaf_len + (1 + p_name->namelen);
1057 break;
1059 case LF_MEMBER_V3:
1060 leaf_len = numeric_leaf(&value, &type->member_v3.offset);
1061 c_name = (const char*)&type->member_v3.offset + leaf_len;
1063 codeview_add_udt_element(ctp, symt, c_name, value, type->member_v3.type);
1065 ptr += 2 + 2 + 4 + leaf_len + (strlen(c_name) + 1);
1066 break;
1068 case LF_STMEMBER_V1:
1069 /* FIXME: ignored for now */
1070 ptr += 2 + 2 + 2 + (1 + type->stmember_v1.p_name.namelen);
1071 break;
1073 case LF_STMEMBER_V2:
1074 /* FIXME: ignored for now */
1075 ptr += 2 + 4 + 2 + (1 + type->stmember_v2.p_name.namelen);
1076 break;
1078 case LF_STMEMBER_V3:
1079 /* FIXME: ignored for now */
1080 ptr += 2 + 4 + 2 + (strlen(type->stmember_v3.name) + 1);
1081 break;
1083 case LF_METHOD_V1:
1084 /* FIXME: ignored for now */
1085 ptr += 2 + 2 + 2 + (1 + type->method_v1.p_name.namelen);
1086 break;
1088 case LF_METHOD_V2:
1089 /* FIXME: ignored for now */
1090 ptr += 2 + 2 + 4 + (1 + type->method_v2.p_name.namelen);
1091 break;
1093 case LF_METHOD_V3:
1094 /* FIXME: ignored for now */
1095 ptr += 2 + 2 + 4 + (strlen(type->method_v3.name) + 1);
1096 break;
1098 case LF_NESTTYPE_V1:
1099 /* FIXME: ignored for now */
1100 ptr += 2 + 2 + (1 + type->nesttype_v1.p_name.namelen);
1101 break;
1103 case LF_NESTTYPE_V2:
1104 /* FIXME: ignored for now */
1105 ptr += 2 + 2 + 4 + (1 + type->nesttype_v2.p_name.namelen);
1106 break;
1108 case LF_NESTTYPE_V3:
1109 /* FIXME: ignored for now */
1110 ptr += 2 + 2 + 4 + (strlen(type->nesttype_v3.name) + 1);
1111 break;
1113 case LF_VFUNCTAB_V1:
1114 /* FIXME: ignored for now */
1115 ptr += 2 + 2;
1116 break;
1118 case LF_VFUNCTAB_V2:
1119 /* FIXME: ignored for now */
1120 ptr += 2 + 2 + 4;
1121 break;
1123 case LF_ONEMETHOD_V1:
1124 /* FIXME: ignored for now */
1125 switch ((type->onemethod_v1.attribute >> 2) & 7)
1127 case 4: case 6: /* (pure) introducing virtual method */
1128 ptr += 2 + 2 + 2 + 4 + (1 + type->onemethod_virt_v1.p_name.namelen);
1129 break;
1131 default:
1132 ptr += 2 + 2 + 2 + (1 + type->onemethod_v1.p_name.namelen);
1133 break;
1135 break;
1137 case LF_ONEMETHOD_V2:
1138 /* FIXME: ignored for now */
1139 switch ((type->onemethod_v2.attribute >> 2) & 7)
1141 case 4: case 6: /* (pure) introducing virtual method */
1142 ptr += 2 + 2 + 4 + 4 + (1 + type->onemethod_virt_v2.p_name.namelen);
1143 break;
1145 default:
1146 ptr += 2 + 2 + 4 + (1 + type->onemethod_v2.p_name.namelen);
1147 break;
1149 break;
1151 case LF_ONEMETHOD_V3:
1152 /* FIXME: ignored for now */
1153 switch ((type->onemethod_v3.attribute >> 2) & 7)
1155 case 4: case 6: /* (pure) introducing virtual method */
1156 ptr += 2 + 2 + 4 + 4 + (strlen(type->onemethod_virt_v3.name) + 1);
1157 break;
1159 default:
1160 ptr += 2 + 2 + 4 + (strlen(type->onemethod_v3.name) + 1);
1161 break;
1163 break;
1165 case LF_INDEX_V1:
1166 if (!codeview_add_type_struct_field_list(ctp, symt, type->index_v1.ref))
1167 return FALSE;
1168 ptr += 2 + 2;
1169 break;
1171 case LF_INDEX_V2:
1172 if (!codeview_add_type_struct_field_list(ctp, symt, type->index_v2.ref))
1173 return FALSE;
1174 ptr += 2 + 2 + 4;
1175 break;
1177 default:
1178 FIXME("Unsupported type %04x in STRUCT field list\n", type->generic.id);
1179 return FALSE;
1183 return TRUE;
1186 static struct symt* codeview_new_func_signature(struct codeview_type_parse* ctp,
1187 enum CV_call_e call_conv)
1189 struct symt_function_signature* sym;
1191 sym = symt_new_function_signature(ctp->module, NULL, call_conv);
1192 return &sym->symt;
1195 static void codeview_add_func_signature_args(struct codeview_type_parse* ctp,
1196 struct symt_function_signature* sym,
1197 unsigned ret_type,
1198 unsigned args_list)
1200 const union codeview_reftype* reftype;
1202 sym->rettype = codeview_fetch_type(ctp, ret_type);
1203 if (args_list && (reftype = codeview_jump_to_type(ctp, args_list)))
1205 unsigned int i;
1206 switch (reftype->generic.id)
1208 case LF_ARGLIST_V1:
1209 for (i = 0; i < reftype->arglist_v1.num; i++)
1210 symt_add_function_signature_parameter(ctp->module, sym,
1211 codeview_fetch_type(ctp, reftype->arglist_v1.args[i]));
1212 break;
1213 case LF_ARGLIST_V2:
1214 for (i = 0; i < reftype->arglist_v2.num; i++)
1215 symt_add_function_signature_parameter(ctp->module, sym,
1216 codeview_fetch_type(ctp, reftype->arglist_v2.args[i]));
1217 break;
1218 default:
1219 FIXME("Unexpected leaf %x for signature's pmt\n", reftype->generic.id);
1224 static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp,
1225 unsigned curr_type,
1226 const union codeview_type* type)
1228 struct symt* symt = NULL;
1229 int value, leaf_len;
1230 const struct p_string* p_name;
1231 const char* c_name;
1233 switch (type->generic.id)
1235 case LF_MODIFIER_V1:
1236 /* FIXME: we don't handle modifiers,
1237 * but read previous type on the curr_type
1239 WARN("Modifier on %x: %s%s%s%s\n",
1240 type->modifier_v1.type,
1241 type->modifier_v1.attribute & 0x01 ? "const " : "",
1242 type->modifier_v1.attribute & 0x02 ? "volatile " : "",
1243 type->modifier_v1.attribute & 0x04 ? "unaligned " : "",
1244 type->modifier_v1.attribute & ~0x07 ? "unknown " : "");
1245 symt = codeview_fetch_type(ctp, type->modifier_v1.type);
1246 break;
1247 case LF_MODIFIER_V2:
1248 /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
1249 WARN("Modifier on %x: %s%s%s%s\n",
1250 type->modifier_v2.type,
1251 type->modifier_v2.attribute & 0x01 ? "const " : "",
1252 type->modifier_v2.attribute & 0x02 ? "volatile " : "",
1253 type->modifier_v2.attribute & 0x04 ? "unaligned " : "",
1254 type->modifier_v2.attribute & ~0x07 ? "unknown " : "");
1255 symt = codeview_fetch_type(ctp, type->modifier_v2.type);
1256 break;
1258 case LF_POINTER_V1:
1259 symt = codeview_add_type_pointer(ctp, type->pointer_v1.datatype);
1260 break;
1261 case LF_POINTER_V2:
1262 symt = codeview_add_type_pointer(ctp, type->pointer_v2.datatype);
1263 break;
1265 case LF_ARRAY_V1:
1266 leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
1267 p_name = (const struct p_string*)((const unsigned char*)&type->array_v1.arrlen + leaf_len);
1268 symt = codeview_add_type_array(ctp, terminate_string(p_name),
1269 type->array_v1.elemtype,
1270 type->array_v1.idxtype, value);
1271 break;
1272 case LF_ARRAY_V2:
1273 leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
1274 p_name = (const struct p_string*)((const unsigned char*)&type->array_v2.arrlen + leaf_len);
1276 symt = codeview_add_type_array(ctp, terminate_string(p_name),
1277 type->array_v2.elemtype,
1278 type->array_v2.idxtype, value);
1279 break;
1280 case LF_ARRAY_V3:
1281 leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
1282 c_name = (const char*)&type->array_v3.arrlen + leaf_len;
1284 symt = codeview_add_type_array(ctp, c_name,
1285 type->array_v3.elemtype,
1286 type->array_v3.idxtype, value);
1287 break;
1289 case LF_STRUCTURE_V1:
1290 case LF_CLASS_V1:
1291 if (!type->struct_v1.property.is_forward_defn)
1292 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)codeview_get_type(curr_type, TRUE),
1293 type->struct_v1.fieldlist);
1294 break;
1296 case LF_STRUCTURE_V2:
1297 case LF_CLASS_V2:
1298 if (!type->struct_v2.property.is_forward_defn)
1299 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)codeview_get_type(curr_type, TRUE),
1300 type->struct_v2.fieldlist);
1301 break;
1303 case LF_STRUCTURE_V3:
1304 case LF_CLASS_V3:
1305 if (!type->struct_v3.property.is_forward_defn)
1306 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)codeview_get_type(curr_type, TRUE),
1307 type->struct_v3.fieldlist);
1308 break;
1310 case LF_UNION_V1:
1311 if (!type->union_v1.property.is_forward_defn)
1312 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)codeview_get_type(curr_type, TRUE),
1313 type->union_v1.fieldlist);
1314 break;
1316 case LF_UNION_V2:
1317 if (!type->union_v2.property.is_forward_defn)
1318 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)codeview_get_type(curr_type, TRUE),
1319 type->union_v2.fieldlist);
1320 break;
1322 case LF_UNION_V3:
1323 if (!type->union_v3.property.is_forward_defn)
1324 codeview_add_type_struct_field_list(ctp, (struct symt_udt*)codeview_get_type(curr_type, TRUE),
1325 type->union_v3.fieldlist);
1326 break;
1328 case LF_ENUM_V1:
1330 struct symt_enum* senum = (struct symt_enum*)codeview_get_type(curr_type, TRUE);
1331 senum->base_type = codeview_fetch_type(ctp, type->enumeration_v1.type);
1332 codeview_add_type_enum_field_list(ctp, senum, type->enumeration_v1.fieldlist);
1334 break;
1336 case LF_ENUM_V2:
1338 struct symt_enum* senum = (struct symt_enum*)codeview_get_type(curr_type, TRUE);
1339 senum->base_type = codeview_fetch_type(ctp, type->enumeration_v2.type);
1340 codeview_add_type_enum_field_list(ctp, senum, type->enumeration_v2.fieldlist);
1342 break;
1344 case LF_ENUM_V3:
1346 struct symt_enum* senum = (struct symt_enum*)codeview_get_type(curr_type, TRUE);
1347 senum->base_type = codeview_fetch_type(ctp, type->enumeration_v3.type);
1348 codeview_add_type_enum_field_list(ctp, senum, type->enumeration_v3.fieldlist);
1350 break;
1352 case LF_PROCEDURE_V1:
1353 symt = codeview_new_func_signature(ctp, type->procedure_v1.callconv);
1354 codeview_add_func_signature_args(ctp,
1355 (struct symt_function_signature*)symt,
1356 type->procedure_v1.rvtype,
1357 type->procedure_v1.arglist);
1358 break;
1359 case LF_PROCEDURE_V2:
1360 symt = codeview_new_func_signature(ctp,type->procedure_v2.callconv);
1361 codeview_add_func_signature_args(ctp,
1362 (struct symt_function_signature*)symt,
1363 type->procedure_v2.rvtype,
1364 type->procedure_v2.arglist);
1365 break;
1367 case LF_MFUNCTION_V1:
1368 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1369 * nor class information, this would just do for now
1371 symt = codeview_new_func_signature(ctp, type->mfunction_v1.callconv);
1372 codeview_add_func_signature_args(ctp,
1373 (struct symt_function_signature*)symt,
1374 type->mfunction_v1.rvtype,
1375 type->mfunction_v1.arglist);
1376 break;
1377 case LF_MFUNCTION_V2:
1378 /* FIXME: for C++, this is plain wrong, but as we don't use arg types
1379 * nor class information, this would just do for now
1381 symt = codeview_new_func_signature(ctp, type->mfunction_v2.callconv);
1382 codeview_add_func_signature_args(ctp,
1383 (struct symt_function_signature*)symt,
1384 type->mfunction_v2.rvtype,
1385 type->mfunction_v2.arglist);
1386 break;
1388 case LF_VTSHAPE_V1:
1389 /* this is an ugly hack... FIXME when we have C++ support */
1391 char buf[128];
1392 snprintf(buf, sizeof(buf), "__internal_vt_shape_%x\n", curr_type);
1393 symt = &symt_new_udt(ctp->module, buf, 0, UdtStruct)->symt;
1395 break;
1396 default:
1397 FIXME("Unsupported type-id leaf %x\n", type->generic.id);
1398 dump(type, 2 + type->generic.len);
1399 return NULL;
1401 return symt && codeview_add_type(curr_type, symt) ? symt : NULL;
1404 static struct symt* codeview_load_forwardable_type(struct codeview_type_parse* ctp,
1405 const union codeview_type* type)
1407 struct symt* symt;
1408 int value, leaf_len;
1409 const struct p_string* p_name;
1410 const char* c_name;
1412 switch (type->generic.id)
1414 case LF_STRUCTURE_V1:
1415 case LF_CLASS_V1:
1416 leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
1417 p_name = (const struct p_string*)((const unsigned char*)&type->struct_v1.structlen + leaf_len);
1418 symt = &symt_new_udt(ctp->module, terminate_string(p_name), value,
1419 type->generic.id == LF_CLASS_V1 ? UdtClass : UdtStruct)->symt;
1420 break;
1422 case LF_STRUCTURE_V2:
1423 case LF_CLASS_V2:
1424 leaf_len = numeric_leaf(&value, &type->struct_v2.structlen);
1425 p_name = (const struct p_string*)((const unsigned char*)&type->struct_v2.structlen + leaf_len);
1426 symt = &symt_new_udt(ctp->module, terminate_string(p_name), value,
1427 type->generic.id == LF_CLASS_V2 ? UdtClass : UdtStruct)->symt;
1428 break;
1430 case LF_STRUCTURE_V3:
1431 case LF_CLASS_V3:
1432 leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
1433 c_name = (const char*)&type->struct_v3.structlen + leaf_len;
1434 symt = &symt_new_udt(ctp->module, c_name, value,
1435 type->generic.id == LF_CLASS_V3 ? UdtClass : UdtStruct)->symt;
1436 break;
1438 case LF_UNION_V1:
1439 leaf_len = numeric_leaf(&value, &type->union_v1.un_len);
1440 p_name = (const struct p_string*)((const unsigned char*)&type->union_v1.un_len + leaf_len);
1441 symt = &symt_new_udt(ctp->module, terminate_string(p_name), value, UdtUnion)->symt;
1442 break;
1444 case LF_UNION_V2:
1445 leaf_len = numeric_leaf(&value, &type->union_v2.un_len);
1446 p_name = (const struct p_string*)((const unsigned char*)&type->union_v2.un_len + leaf_len);
1447 symt = &symt_new_udt(ctp->module, terminate_string(p_name), value, UdtUnion)->symt;
1448 break;
1450 case LF_UNION_V3:
1451 leaf_len = numeric_leaf(&value, &type->union_v3.un_len);
1452 c_name = (const char*)&type->union_v3.un_len + leaf_len;
1453 symt = &symt_new_udt(ctp->module, c_name, value, UdtUnion)->symt;
1454 break;
1456 case LF_ENUM_V1:
1457 symt = &symt_new_enum(ctp->module, terminate_string(&type->enumeration_v1.p_name), NULL)->symt;
1458 break;
1460 case LF_ENUM_V2:
1461 symt = &symt_new_enum(ctp->module, terminate_string(&type->enumeration_v2.p_name), NULL)->symt;
1462 break;
1464 case LF_ENUM_V3:
1465 symt = &symt_new_enum(ctp->module, type->enumeration_v3.name, NULL)->symt;
1466 break;
1468 default: symt = NULL;
1470 return symt;
1473 static inline BOOL codeview_is_top_level_type(const union codeview_type* type)
1475 /* type records we're interested in are the ones referenced by symbols
1476 * The known ranges are (X mark the ones we want):
1477 * X 0000-0016 for V1 types
1478 * 0200-020c for V1 types referenced by other types
1479 * 0400-040f for V1 types (complex lists & sets)
1480 * X 1000-100f for V2 types
1481 * 1200-120c for V2 types referenced by other types
1482 * 1400-140f for V1 types (complex lists & sets)
1483 * X 1500-150d for V3 types
1484 * 8000-8010 for numeric leafes
1486 return !(type->generic.id & 0x8600) || (type->generic.id & 0x0100);
1489 static BOOL codeview_parse_type_table(struct codeview_type_parse* ctp)
1491 unsigned int i, curr_type;
1492 const union codeview_type* type;
1494 cv_current_module->first_type_index = ctp->header.first_index;
1495 cv_current_module->last_type_index = ctp->header.last_index;
1496 cv_current_module->defined_types = calloc(ctp->header.last_index - ctp->header.first_index,
1497 sizeof(*cv_current_module->defined_types));
1499 /* pass I: + load implementation of forwardable types, but without their content
1500 * + merge forward declarations with their implementations (when the later exists)
1501 * + do it in the order generated from PDB hash table to preserve that order
1502 * (several versions coming from different compilations can exist in the PDB file,
1503 * and using PDB order ensures that we use the relevant one.
1504 * (needed for forward resolution and type lookup by name)
1505 * (dbghelp hash table inserts new elements at the end of bucket's list)
1506 * Note: for a given type, we must handle:
1507 * - only an implementation type record
1508 * - only a forward type record (eg using struct foo* without struct foo being defined)
1509 * - a forward type record and on an implementation type record: this is the most common, but
1510 * depending on hash values, we cannot tell which on will show up first
1512 for (i = 0; i < ctp->header.hash_num_buckets; i++)
1514 struct hash_link* hl;
1515 for (hl = ctp->hash[i]; hl; hl = hl->next)
1517 struct symt* symt;
1518 type = codeview_jump_to_type(ctp, hl->id);
1519 if (!codeview_is_top_level_type(type)) continue;
1520 if (codeview_type_is_forward(type))
1522 unsigned impl_type;
1523 /* make the forward declaration point to the implementation (if any) */
1524 if (codeview_resolve_forward_type(ctp, type, hl->id, &impl_type))
1526 /* impl already loaded? */
1527 if (!(symt = codeview_get_type(impl_type, TRUE)))
1529 /* no load it */
1530 if ((symt = codeview_load_forwardable_type(ctp, codeview_jump_to_type(ctp, impl_type))))
1531 codeview_add_type(impl_type, symt);
1532 else
1533 FIXME("forward def of %x => %x, unable to load impl\n", hl->id, impl_type);
1536 else
1537 /* forward type definition without implementation, create empty type */
1538 symt = codeview_load_forwardable_type(ctp, type);
1540 else
1542 /* if not already loaded (from previous forward declaration), load it */
1543 if (!(symt = codeview_get_type(hl->id, TRUE)))
1544 symt = codeview_load_forwardable_type(ctp, type);
1546 codeview_add_type(hl->id, symt);
1549 /* pass II: + non forwardable types: load them, but since they can be indirectly
1550 * loaded (from another type), but don't load them twice
1551 * + forwardable types: load their content
1553 for (curr_type = ctp->header.first_index; curr_type < ctp->header.last_index; curr_type++)
1555 type = codeview_jump_to_type(ctp, curr_type);
1556 if (codeview_is_top_level_type(type) &&
1557 (!codeview_get_type(curr_type, TRUE) || codeview_is_forwardable_type(type)))
1558 codeview_parse_one_type(ctp, curr_type, type);
1561 return TRUE;
1564 /*========================================================================
1565 * Process CodeView line number information.
1567 static ULONG_PTR codeview_get_address(const struct msc_debug_info* msc_dbg,
1568 unsigned seg, unsigned offset);
1570 static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const BYTE* linetab,
1571 int size, BOOL pascal_str)
1573 const BYTE* ptr = linetab;
1574 int nfile, nseg;
1575 int i, j;
1576 unsigned int k;
1577 const unsigned int* filetab;
1578 const unsigned int* lt_ptr;
1579 const unsigned short* linenos;
1580 const struct startend* start;
1581 unsigned source;
1582 ULONG_PTR addr, func_addr0;
1583 struct symt_function* func;
1584 const struct codeview_linetab_block* ltb;
1586 nfile = *(const short*)linetab;
1587 filetab = (const unsigned int*)(linetab + 2 * sizeof(short));
1589 for (i = 0; i < nfile; i++)
1591 ptr = linetab + filetab[i];
1592 nseg = *(const short*)ptr;
1593 lt_ptr = (const unsigned int*)(ptr + 2 * sizeof(short));
1594 start = (const struct startend*)(lt_ptr + nseg);
1597 * Now snarf the filename for all of the segments for this file.
1599 if (pascal_str)
1600 source = source_new(msc_dbg->module, NULL, terminate_string((const struct p_string*)(start + nseg)));
1601 else
1602 source = source_new(msc_dbg->module, NULL, (const char*)(start + nseg));
1604 for (j = 0; j < nseg; j++)
1606 ltb = (const struct codeview_linetab_block*)(linetab + *lt_ptr++);
1607 linenos = (const unsigned short*)&ltb->offsets[ltb->num_lines];
1608 func_addr0 = codeview_get_address(msc_dbg, ltb->seg, start[j].start);
1609 if (!func_addr0) continue;
1610 for (func = NULL, k = 0; k < ltb->num_lines; k++)
1612 /* now locate function (if any) */
1613 addr = func_addr0 + ltb->offsets[k] - start[j].start;
1614 /* unfortunately, we can have several functions in the same block, if there's no
1615 * gap between them... find the new function if needed
1617 if (!func || addr >= func->address + func->size)
1619 func = (struct symt_function*)symt_find_symbol_at(msc_dbg->module, addr);
1620 /* FIXME: at least labels support line numbers */
1621 if (!symt_check_tag(&func->symt, SymTagFunction) && !symt_check_tag(&func->symt, SymTagInlineSite))
1623 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1624 ltb->seg, ltb->offsets[k], addr, func ? func->symt.tag : -1);
1625 func = NULL;
1626 break;
1629 symt_add_func_line(msc_dbg->module, func, source, linenos[k], addr);
1635 static const char* pdb_get_string_table_entry(const PDB_STRING_TABLE* table, unsigned offset);
1637 static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const struct cv_module_snarf* cvmod)
1639 unsigned i;
1640 const void* hdr_last = (const char*)cvmod->dbgsubsect + cvmod->dbgsubsect_size;
1641 const struct CV_DebugSSubsectionHeader_t* hdr;
1642 const struct CV_DebugSSubsectionHeader_t* hdr_next;
1643 const struct CV_DebugSSubsectionHeader_t* hdr_files = NULL;
1644 const struct CV_DebugSLinesHeader_t* lines_hdr;
1645 const struct CV_DebugSLinesFileBlockHeader_t* files_hdr;
1646 const struct CV_Line_t* lines;
1647 const struct CV_Checksum_t* chksms;
1648 unsigned source;
1649 struct symt_function* func;
1651 /* locate DEBUG_S_FILECHKSMS (if any) */
1652 for (hdr = cvmod->dbgsubsect; CV_IS_INSIDE(hdr, hdr_last); hdr = CV_RECORD_GAP(hdr, hdr->cbLen))
1654 if (hdr->type == DEBUG_S_FILECHKSMS)
1656 hdr_files = hdr;
1657 break;
1660 if (!hdr_files)
1662 TRACE("No DEBUG_S_FILECHKSMS found\n");
1663 return;
1666 for (hdr = cvmod->dbgsubsect; CV_IS_INSIDE(hdr, hdr_last); hdr = hdr_next)
1668 hdr_next = CV_RECORD_GAP(hdr, hdr->cbLen);
1669 if (!(hdr->type & DEBUG_S_IGNORE))
1671 ULONG_PTR lineblk_base;
1672 /* FIXME: should also check that whole lines_blk fits in linetab + size */
1673 switch (hdr->type)
1675 case DEBUG_S_LINES:
1676 lines_hdr = CV_RECORD_AFTER(hdr);
1677 files_hdr = CV_RECORD_AFTER(lines_hdr);
1678 /* Skip blocks that are too small - Intel C Compiler generates these. */
1679 if (!CV_IS_INSIDE(files_hdr, hdr_next)) break;
1680 TRACE("block from %04x:%08x #%x\n",
1681 lines_hdr->segCon, lines_hdr->offCon, lines_hdr->cbCon);
1682 chksms = CV_RECORD_GAP(hdr_files, files_hdr->offFile);
1683 if (!CV_IS_INSIDE(chksms, CV_RECORD_GAP(hdr_files, hdr_files->cbLen)))
1685 WARN("Corrupt PDB file: offset in CHKSMS subsection is invalid\n");
1686 break;
1688 source = source_new(msc_dbg->module, NULL, pdb_get_string_table_entry(cvmod->strimage, chksms->strOffset));
1689 lineblk_base = codeview_get_address(msc_dbg, lines_hdr->segCon, lines_hdr->offCon);
1690 lines = CV_RECORD_AFTER(files_hdr);
1691 for (i = 0; i < files_hdr->nLines; i++)
1693 func = (struct symt_function*)symt_find_symbol_at(msc_dbg->module, lineblk_base + lines[i].offset);
1694 /* FIXME: at least labels support line numbers */
1695 if (!symt_check_tag(&func->symt, SymTagFunction) && !symt_check_tag(&func->symt, SymTagInlineSite))
1697 WARN("--not a func at %04x:%08x %Ix tag=%d\n",
1698 lines_hdr->segCon, lines_hdr->offCon + lines[i].offset, lineblk_base + lines[i].offset, func ? func->symt.tag : -1);
1699 continue;
1701 symt_add_func_line(msc_dbg->module, func, source,
1702 lines[i].linenumStart, lineblk_base + lines[i].offset);
1704 break;
1705 case DEBUG_S_FILECHKSMS: /* skip */
1706 break;
1707 default:
1708 break;
1711 hdr = hdr_next;
1715 /*========================================================================
1716 * Process CodeView symbol information.
1719 static unsigned int codeview_map_offset(const struct msc_debug_info* msc_dbg,
1720 unsigned int offset)
1722 int nomap = msc_dbg->nomap;
1723 const OMAP* omapp = msc_dbg->omapp;
1724 int i;
1726 if (!nomap || !omapp) return offset;
1728 /* FIXME: use binary search */
1729 for (i = 0; i < nomap - 1; i++)
1730 if (omapp[i].rva <= offset && omapp[i+1].rva > offset)
1731 return !omapp[i].rvaTo ? 0 : omapp[i].rvaTo + (offset - omapp[i].rva);
1733 return 0;
1736 static ULONG_PTR codeview_get_address(const struct msc_debug_info* msc_dbg,
1737 unsigned seg, unsigned offset)
1739 int nsect = msc_dbg->nsect;
1740 const IMAGE_SECTION_HEADER* sectp = msc_dbg->sectp;
1742 if (!seg || seg > nsect) return 0;
1743 return msc_dbg->module->module.BaseOfImage +
1744 codeview_map_offset(msc_dbg, sectp[seg-1].VirtualAddress + offset);
1747 static BOOL func_has_local(struct symt_function* func, const char* name)
1749 int i;
1751 for (i = 0; i < func->vchildren.num_elts; ++i)
1753 struct symt* p = *(struct symt**)vector_at(&func->vchildren, i);
1754 if (symt_check_tag(p, SymTagData) && !strcmp(((struct symt_data*)p)->hash_elt.name, name))
1755 return TRUE;
1757 return FALSE;
1760 static const union codeview_symbol* get_next_sym(const union codeview_symbol* sym)
1762 return (const union codeview_symbol*)((const char*)sym + sym->generic.len + 2);
1765 static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg,
1766 struct symt_compiland* compiland,
1767 struct symt_function* func,
1768 struct symt_block* block,
1769 const char* name,
1770 unsigned segment, unsigned offset,
1771 unsigned symtype, BOOL is_local, BOOL in_tls, BOOL dontcheck)
1773 if (name && *name)
1775 struct location loc;
1777 loc.kind = in_tls ? loc_tlsrel : loc_absolute;
1778 loc.reg = 0;
1779 loc.offset = in_tls ? offset : codeview_get_address(msc_dbg, segment, offset);
1780 if (func)
1782 if (!is_local || in_tls) WARN("Unsupported construct\n");
1783 symt_add_func_local(msc_dbg->module, func, DataIsStaticLocal, &loc, block,
1784 codeview_get_type(symtype, FALSE), name);
1785 return;
1787 if (!dontcheck && !in_tls)
1789 /* Check that we don't add twice the same variable */
1790 struct hash_table_iter hti;
1791 void* ptr;
1792 struct symt_ht* sym;
1794 hash_table_iter_init(&msc_dbg->module->ht_symbols, &hti, name);
1795 while ((ptr = hash_table_iter_up(&hti)))
1797 sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
1798 if (symt_check_tag(&sym->symt, SymTagData) && !strcmp(sym->hash_elt.name, name))
1800 struct symt_data* symdata = (struct symt_data*)&sym->symt;
1801 if (symdata->kind == (is_local ? DataIsFileStatic : DataIsGlobal) &&
1802 symdata->u.var.kind == loc.kind &&
1803 symdata->u.var.offset == loc.offset &&
1804 symdata->container == &compiland->symt)
1806 /* We don't compare types yet... Unfortunately, they are not
1807 * always the same typeid... it'd require full type equivalence
1808 * (eg: we've seen 'int* foo' <> 'int[4] foo')
1810 return;
1815 if (is_local ^ (compiland != NULL)) FIXME("Unsupported construct\n");
1816 symt_new_global_variable(msc_dbg->module, compiland, name, is_local, loc, 0,
1817 codeview_get_type(symtype, FALSE));
1821 struct cv_local_info
1823 unsigned short kind; /* the S_DEFRANGE* */
1824 unsigned short ngaps; /* number of gaps */
1825 unsigned short reg;
1826 unsigned short rangelen; /* after start */
1827 short offset;
1828 DWORD_PTR start;
1829 struct cv_addr_gap gaps[0];
1832 static const struct cv_addr_gap* codeview_get_gaps(const union codeview_symbol* symrange)
1834 const struct cv_addr_gap* gap;
1835 switch (symrange->generic.id)
1837 case S_DEFRANGE: gap = symrange->defrange_v3.gaps; break;
1838 case S_DEFRANGE_SUBFIELD: gap = symrange->defrange_subfield_v3.gaps; break;
1839 case S_DEFRANGE_REGISTER: gap = symrange->defrange_register_v3.gaps; break;
1840 case S_DEFRANGE_FRAMEPOINTER_REL: gap = symrange->defrange_frameptrrel_v3.gaps; break;
1841 case S_DEFRANGE_SUBFIELD_REGISTER: gap = symrange->defrange_subfield_register_v3.gaps; break;
1842 case S_DEFRANGE_REGISTER_REL: gap = symrange->defrange_registerrel_v3.gaps; break;
1843 /* no gaps for that one */
1844 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
1845 default: return NULL;
1847 return gap != (const struct cv_addr_gap*)get_next_sym(symrange) ? gap : NULL;
1850 static void codeview_xform_range(const struct msc_debug_info* msc_dbg,
1851 struct cv_local_info* locinfo,
1852 const struct cv_addr_range* adrange)
1854 locinfo->start = codeview_get_address(msc_dbg, adrange->isectStart, adrange->offStart);
1855 locinfo->rangelen = adrange->cbRange;
1858 static unsigned codeview_defrange_length(const union codeview_symbol* sym)
1860 const union codeview_symbol* first_symrange = get_next_sym(sym);
1861 const union codeview_symbol* symrange;
1863 for (symrange = first_symrange;
1864 symrange->generic.id >= S_DEFRANGE && symrange->generic.id <= S_DEFRANGE_REGISTER_REL;
1865 symrange = get_next_sym(symrange)) {}
1866 return (const char*)symrange - (const char*)first_symrange;
1869 static unsigned codeview_transform_defrange(const struct msc_debug_info* msc_dbg,
1870 struct symt_function* curr_func,
1871 const union codeview_symbol* sym,
1872 struct location* loc)
1874 const union codeview_symbol* first_symrange = get_next_sym(sym);
1875 const union codeview_symbol* symrange;
1876 const struct cv_addr_gap* gap;
1877 unsigned len, alloc = sizeof(DWORD); /* for terminating kind = 0 */
1878 unsigned char* ptr;
1880 /* we need to transform the cv_addr_range into cv_local_info */
1881 for (symrange = first_symrange;
1882 symrange->generic.id >= S_DEFRANGE && symrange->generic.id <= S_DEFRANGE_REGISTER_REL;
1883 symrange = get_next_sym(symrange))
1885 gap = codeview_get_gaps(symrange);
1886 alloc += sizeof(struct cv_local_info) +
1887 (gap ? (const char*)get_next_sym(symrange) - (const char*)gap : 0);
1889 /* total length of all S_DEFRANGE* records (in bytes) following S_LOCAL */
1890 len = (const char*)symrange - (const char*)first_symrange;
1892 ptr = pool_alloc(&msc_dbg->module->pool, alloc);
1893 if (ptr)
1895 struct cv_local_info* locinfo = (struct cv_local_info*)ptr;
1897 loc->kind = loc_cv_local_range;
1898 loc->offset = (DWORD_PTR)ptr;
1899 /* transform the cv_addr_range into cv_local_info */
1900 for (symrange = first_symrange;
1901 symrange->generic.id >= S_DEFRANGE && symrange->generic.id <= S_DEFRANGE_REGISTER_REL;
1902 symrange = get_next_sym(symrange))
1904 locinfo->kind = symrange->generic.id;
1905 switch (symrange->generic.id)
1907 case S_DEFRANGE:
1908 codeview_xform_range(msc_dbg, locinfo, &symrange->defrange_v3.range);
1909 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1910 break;
1911 case S_DEFRANGE_SUBFIELD:
1912 codeview_xform_range(msc_dbg, locinfo, &symrange->defrange_subfield_v3.range);
1913 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
1914 break;
1915 case S_DEFRANGE_REGISTER:
1916 locinfo->reg = symrange->defrange_register_v3.reg;
1917 codeview_xform_range(msc_dbg, locinfo, &symrange->defrange_register_v3.range);
1918 break;
1919 case S_DEFRANGE_FRAMEPOINTER_REL:
1920 locinfo->offset = symrange->defrange_frameptrrel_v3.offFramePointer;
1921 codeview_xform_range(msc_dbg, locinfo, &symrange->defrange_frameptrrel_v3.range);
1922 break;
1923 case S_DEFRANGE_SUBFIELD_REGISTER:
1924 locinfo->reg = symrange->defrange_subfield_register_v3.reg;
1925 locinfo->offset = symrange->defrange_subfield_register_v3.offParent;
1926 codeview_xform_range(msc_dbg, locinfo, &symrange->defrange_subfield_register_v3.range);
1927 break;
1928 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
1929 locinfo->offset = symrange->defrange_frameptr_relfullscope_v3.offFramePointer;
1930 locinfo->start = curr_func->address;
1931 locinfo->rangelen = curr_func->size;
1932 break;
1933 case S_DEFRANGE_REGISTER_REL:
1934 locinfo->reg = symrange->defrange_registerrel_v3.baseReg;
1935 locinfo->offset = symrange->defrange_registerrel_v3.offBasePointer;
1936 codeview_xform_range(msc_dbg, locinfo, &symrange->defrange_registerrel_v3.range);
1937 break;
1938 default:
1939 assert(0);
1941 gap = codeview_get_gaps(symrange);
1942 if (gap)
1944 unsigned gaplen = (const char*)get_next_sym(symrange) - (const char*)gap;
1945 locinfo->ngaps = gaplen / sizeof(*gap);
1946 memcpy(locinfo->gaps, gap, gaplen);
1947 locinfo = (struct cv_local_info*)((char*)(locinfo + 1) + gaplen);
1949 else
1951 locinfo->ngaps = 0;
1952 locinfo++;
1955 *(DWORD*)locinfo = 0; /* store terminating kind == 0 */
1957 else
1959 loc->kind = loc_error;
1960 loc->reg = loc_err_internal;
1962 return len;
1965 static unsigned codeview_binannot_uncompress(const unsigned char** pptr)
1967 unsigned res = (unsigned)(-1);
1968 const unsigned char* ptr = *pptr;
1970 if ((*ptr & 0x80) == 0x00)
1971 res = (unsigned)(*ptr++);
1972 else if ((*ptr & 0xC0) == 0x80)
1974 res = (unsigned)((*ptr++ & 0x3f) << 8);
1975 res |= *ptr++;
1977 else if ((*ptr & 0xE0) == 0xC0)
1979 res = (*ptr++ & 0x1f) << 24;
1980 res |= *ptr++ << 16;
1981 res |= *ptr++ << 8;
1982 res |= *ptr++;
1984 else res = (unsigned)(-1);
1985 *pptr = ptr;
1986 return res;
1989 struct cv_binannot
1991 const unsigned char* annot; /* current pointer */
1992 const unsigned char* last_annot; /* end of binary annotation stream (first byte after) */
1993 unsigned opcode; /* last decoded opcode */
1994 unsigned arg1, arg2;
1997 static BOOL codeview_advance_binannot(struct cv_binannot* cvba)
1999 if (cvba->annot >= cvba->last_annot) return FALSE;
2000 cvba->opcode = codeview_binannot_uncompress(&cvba->annot);
2001 if (cvba->opcode <= BA_OP_Invalid || cvba->opcode > BA_OP_ChangeColumnEnd) return FALSE;
2002 if (cvba->annot >= cvba->last_annot) return FALSE;
2003 cvba->arg1 = codeview_binannot_uncompress(&cvba->annot);
2004 if (cvba->opcode == BA_OP_ChangeCodeOffsetAndLineOffset)
2006 cvba->arg2 = cvba->arg1 >> 4;
2007 cvba->arg1 &= 0x0F;
2009 else if (cvba->opcode == BA_OP_ChangeCodeLengthAndCodeOffset)
2011 if (cvba->annot >= cvba->last_annot) return FALSE;
2012 cvba->arg2 = codeview_binannot_uncompress(&cvba->annot);
2014 else cvba->arg2 = 0;
2015 return TRUE;
2018 static inline int binannot_getsigned(unsigned i)
2020 return (i & 1) ? -(int)(i >> 1) : (int)(i >> 1);
2023 static BOOL cv_dbgsubsect_find_inlinee(const struct msc_debug_info* msc_dbg,
2024 unsigned inlineeid,
2025 const struct cv_module_snarf* cvmod,
2026 const struct CV_DebugSSubsectionHeader_t* hdr_files,
2027 unsigned* srcfile, unsigned* srcline)
2029 const struct CV_DebugSSubsectionHeader_t* hdr;
2030 const struct CV_DebugSSubsectionHeader_t* next_hdr;
2031 const struct CV_InlineeSourceLine_t* inlsrc;
2032 const struct CV_InlineeSourceLineEx_t* inlsrcex;
2033 const struct CV_Checksum_t* chksms;
2035 for (hdr = cvmod->dbgsubsect; CV_IS_INSIDE(hdr, cvmod->dbgsubsect + cvmod->dbgsubsect_size); hdr = next_hdr)
2037 next_hdr = CV_RECORD_GAP(hdr, hdr->cbLen);
2038 if (hdr->type != DEBUG_S_INLINEELINES) continue;
2039 /* subsection starts with a DWORD signature */
2040 switch (*(DWORD*)CV_RECORD_AFTER(hdr))
2042 case CV_INLINEE_SOURCE_LINE_SIGNATURE:
2043 inlsrc = CV_RECORD_GAP(hdr, sizeof(DWORD));
2044 while (CV_IS_INSIDE(inlsrc, next_hdr))
2046 if (inlsrc->inlinee == inlineeid)
2048 chksms = CV_RECORD_GAP(hdr_files, inlsrc->fileId);
2049 if (!CV_IS_INSIDE(chksms, CV_RECORD_GAP(hdr_files, hdr_files->cbLen))) return FALSE;
2050 *srcfile = source_new(msc_dbg->module, NULL, pdb_get_string_table_entry(cvmod->strimage, chksms->strOffset));
2051 *srcline = inlsrc->sourceLineNum;
2052 return TRUE;
2054 ++inlsrc;
2056 break;
2057 case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX:
2058 inlsrcex = CV_RECORD_GAP(hdr, sizeof(DWORD));
2059 while (CV_IS_INSIDE(inlsrcex, next_hdr))
2061 if (inlsrcex->inlinee == inlineeid)
2063 chksms = CV_RECORD_GAP(hdr_files, inlsrcex->fileId);
2064 if (!CV_IS_INSIDE(chksms, CV_RECORD_GAP(hdr_files, hdr_files->cbLen))) return FALSE;
2065 *srcfile = source_new(msc_dbg->module, NULL, pdb_get_string_table_entry(cvmod->strimage, chksms->strOffset));
2066 *srcline = inlsrcex->sourceLineNum;
2067 return TRUE;
2069 inlsrcex = CV_RECORD_GAP(inlsrcex, inlsrcex->countOfExtraFiles * sizeof(inlsrcex->extraFileId[0]));
2071 break;
2072 default:
2073 FIXME("Unknown signature %lx in INLINEELINES subsection\n", *(DWORD*)CV_RECORD_AFTER(hdr));
2074 break;
2077 return FALSE;
2080 static inline void inline_site_update_last_range(struct symt_inlinesite* inlined, ULONG_PTR hi)
2082 unsigned num = inlined->vranges.num_elts;
2083 if (num)
2085 struct addr_range* range = vector_at(&inlined->vranges, num - 1);
2086 /* only change range if it has no span (code start without code end) */
2087 if (range->low == range->high)
2088 range->high = hi;
2092 static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debug_info* msc_dbg,
2093 const struct cv_module_snarf* cvmod,
2094 struct symt_function* top_func,
2095 struct symt* container,
2096 cv_itemid_t inlinee,
2097 const unsigned char* annot,
2098 const unsigned char* last_annot)
2100 const struct CV_DebugSSubsectionHeader_t* hdr_files = NULL;
2101 const union codeview_type* cvt;
2102 struct symt_inlinesite* inlined;
2103 struct cv_binannot cvba;
2104 BOOL srcok, found = FALSE;
2105 unsigned offset, line, srcfile;
2106 const struct CV_Checksum_t* chksms;
2108 if (!cvmod->ipi_ctp || !(cvt = codeview_jump_to_type(cvmod->ipi_ctp, inlinee)))
2110 FIXME("Couldn't find type %x in IPI stream\n", inlinee);
2111 return NULL;
2114 /* grasp first code offset in binary annotation to compute inline site start address */
2115 cvba.annot = annot;
2116 cvba.last_annot = last_annot;
2117 while (codeview_advance_binannot(&cvba))
2118 if (cvba.opcode == BA_OP_CodeOffset ||
2119 cvba.opcode == BA_OP_ChangeCodeOffset ||
2120 cvba.opcode == BA_OP_ChangeCodeOffsetAndLineOffset)
2122 offset = cvba.arg1;
2123 found = TRUE;
2124 break;
2126 else if (cvba.opcode == BA_OP_ChangeCodeLengthAndCodeOffset)
2128 offset = cvba.arg2;
2129 found = TRUE;
2130 break;
2133 if (!found)
2135 WARN("Couldn't find start address of inlined\n");
2136 return NULL;
2139 switch (cvt->generic.id)
2141 case LF_FUNC_ID:
2142 inlined = symt_new_inlinesite(msc_dbg->module, top_func, container,
2143 cvt->func_id_v3.name, top_func->address + offset,
2144 codeview_get_type(cvt->func_id_v3.type, FALSE));
2145 break;
2146 case LF_MFUNC_ID:
2147 /* FIXME we just declare a function, not a method */
2148 inlined = symt_new_inlinesite(msc_dbg->module, top_func, container,
2149 cvt->mfunc_id_v3.name, top_func->address + offset,
2150 codeview_get_type(cvt->mfunc_id_v3.type, FALSE));
2151 break;
2152 default:
2153 FIXME("unsupported inlinee kind %x\n", cvt->generic.id);
2154 return NULL;
2157 for (hdr_files = cvmod->dbgsubsect;
2158 CV_IS_INSIDE(hdr_files, cvmod->dbgsubsect + cvmod->dbgsubsect_size);
2159 hdr_files = CV_RECORD_GAP(hdr_files, hdr_files->cbLen))
2161 if (hdr_files->type == DEBUG_S_FILECHKSMS)
2162 break;
2164 if (!hdr_files) return FALSE;
2165 srcok = cv_dbgsubsect_find_inlinee(msc_dbg, inlinee, cvmod, hdr_files, &srcfile, &line);
2167 if (!srcok)
2168 srcfile = line = 0;
2170 /* rescan all annotations and store ranges & line information */
2171 offset = 0;
2172 cvba.annot = annot;
2173 cvba.last_annot = last_annot;
2175 while (codeview_advance_binannot(&cvba))
2177 switch (cvba.opcode)
2179 case BA_OP_CodeOffset:
2180 offset = cvba.arg1;
2181 break;
2182 case BA_OP_ChangeCodeOffset:
2183 offset += cvba.arg1;
2184 inline_site_update_last_range(inlined, top_func->address + offset);
2185 if (srcok)
2186 symt_add_func_line(msc_dbg->module, &inlined->func, srcfile, line, top_func->address + offset);
2187 symt_add_inlinesite_range(msc_dbg->module, inlined, top_func->address + offset, top_func->address + offset);
2188 break;
2189 case BA_OP_ChangeCodeLength:
2190 /* this op doesn't seem widely used... */
2191 if (inlined->vranges.num_elts)
2193 struct addr_range* range = vector_at(&inlined->vranges, inlined->vranges.num_elts - 1);
2194 inline_site_update_last_range(inlined, range->low + cvba.arg1);
2196 break;
2197 case BA_OP_ChangeFile:
2198 chksms = CV_RECORD_GAP(hdr_files, cvba.arg1);
2199 if (CV_IS_INSIDE(chksms, CV_RECORD_GAP(hdr_files, hdr_files->cbLen)))
2200 srcfile = source_new(msc_dbg->module, NULL, pdb_get_string_table_entry(cvmod->strimage, chksms->strOffset));
2201 break;
2202 case BA_OP_ChangeLineOffset:
2203 line += binannot_getsigned(cvba.arg1);
2204 break;
2205 case BA_OP_ChangeCodeOffsetAndLineOffset:
2206 line += binannot_getsigned(cvba.arg2);
2207 offset += cvba.arg1;
2208 inline_site_update_last_range(inlined, top_func->address + offset);
2209 if (srcok)
2210 symt_add_func_line(msc_dbg->module, &inlined->func, srcfile, line, top_func->address + offset);
2211 symt_add_inlinesite_range(msc_dbg->module, inlined, top_func->address + offset, top_func->address + offset);
2212 break;
2213 case BA_OP_ChangeCodeLengthAndCodeOffset:
2214 offset += cvba.arg2;
2215 inline_site_update_last_range(inlined, top_func->address + offset);
2216 if (srcok)
2217 symt_add_func_line(msc_dbg->module, &inlined->func, srcfile, line, top_func->address + offset);
2218 symt_add_inlinesite_range(msc_dbg->module, inlined, top_func->address + offset, top_func->address + offset + cvba.arg1);
2219 break;
2220 default:
2221 WARN("Unsupported op %d\n", cvba.opcode);
2222 break;
2225 if (inlined->vranges.num_elts)
2227 struct addr_range* range = vector_at(&inlined->vranges, inlined->vranges.num_elts - 1);
2228 if (range->low == range->high) WARN("pending empty range at end of %s inside %s\n",
2229 inlined->func.hash_elt.name,
2230 top_func->hash_elt.name);
2232 return inlined;
2235 static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg,
2236 const BYTE* root, unsigned offset, unsigned size,
2237 const struct cv_module_snarf* cvmod)
2239 struct symt_function* top_func = NULL;
2240 struct symt_function* curr_func = NULL;
2241 int i, length;
2242 struct symt_block* block = NULL;
2243 struct symt* symt;
2244 struct symt_compiland* compiland = NULL;
2245 struct location loc;
2248 * Loop over the different types of records and whenever we
2249 * find something we are interested in, record it and move on.
2251 for (i = offset; i < size; i += length)
2253 const union codeview_symbol* sym = (const union codeview_symbol*)(root + i);
2254 length = sym->generic.len + 2;
2255 if (i + length > size) break;
2256 if (!sym->generic.id || length < 4) break;
2257 if (length & 3) FIXME("unpadded len %u\n", length);
2259 switch (sym->generic.id)
2262 * Global and local data symbols. We don't associate these
2263 * with any given source file.
2265 case S_GDATA32_16t:
2266 case S_LDATA32_16t:
2267 codeview_add_variable(msc_dbg, compiland, curr_func, block, terminate_string(&sym->data_v1.p_name),
2268 sym->data_v1.segment, sym->data_v1.offset, sym->data_v1.symtype,
2269 sym->generic.id == S_LDATA32_16t, FALSE, TRUE);
2270 break;
2271 case S_GDATA32_ST:
2272 case S_LDATA32_ST:
2273 codeview_add_variable(msc_dbg, compiland, curr_func, block, terminate_string(&sym->data_v2.p_name),
2274 sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype,
2275 sym->generic.id == S_LDATA32_ST, FALSE, TRUE);
2276 break;
2277 case S_GDATA32:
2278 case S_LDATA32:
2279 codeview_add_variable(msc_dbg, compiland, curr_func, block, sym->data_v3.name,
2280 sym->data_v3.segment, sym->data_v3.offset, sym->data_v3.symtype,
2281 sym->generic.id == S_LDATA32, FALSE, TRUE);
2282 break;
2284 /* variables with thread storage */
2285 case S_GTHREAD32_16t:
2286 case S_LTHREAD32_16t:
2287 codeview_add_variable(msc_dbg, compiland, curr_func, block, terminate_string(&sym->thread_v1.p_name),
2288 sym->thread_v1.segment, sym->thread_v1.offset, sym->thread_v1.symtype,
2289 sym->generic.id == S_LTHREAD32_16t, TRUE, TRUE);
2290 break;
2291 case S_GTHREAD32_ST:
2292 case S_LTHREAD32_ST:
2293 codeview_add_variable(msc_dbg, compiland, curr_func, block, terminate_string(&sym->thread_v2.p_name),
2294 sym->thread_v2.segment, sym->thread_v2.offset, sym->thread_v2.symtype,
2295 sym->generic.id == S_LTHREAD32_ST, TRUE, TRUE);
2296 break;
2297 case S_GTHREAD32:
2298 case S_LTHREAD32:
2299 codeview_add_variable(msc_dbg, compiland, curr_func, block, sym->thread_v3.name,
2300 sym->thread_v3.segment, sym->thread_v3.offset, sym->thread_v3.symtype,
2301 sym->generic.id == S_LTHREAD32, TRUE, TRUE);
2302 break;
2304 /* Public symbols */
2305 case S_PUB32_16t:
2306 case S_PUB32_ST:
2307 case S_PUB32:
2308 case S_PROCREF:
2309 case S_LPROCREF:
2310 /* will be handled later on in codeview_snarf_public */
2311 break;
2314 * Sort of like a global function, but it just points
2315 * to a thunk, which is a stupid name for what amounts to
2316 * a PLT slot in the normal jargon that everyone else uses.
2318 case S_THUNK32_ST:
2319 symt_new_thunk(msc_dbg->module, compiland,
2320 terminate_string(&sym->thunk_v1.p_name), sym->thunk_v1.thtype,
2321 codeview_get_address(msc_dbg, sym->thunk_v1.segment, sym->thunk_v1.offset),
2322 sym->thunk_v1.thunk_len);
2323 break;
2324 case S_THUNK32:
2325 symt_new_thunk(msc_dbg->module, compiland,
2326 sym->thunk_v3.name, sym->thunk_v3.thtype,
2327 codeview_get_address(msc_dbg, sym->thunk_v3.segment, sym->thunk_v3.offset),
2328 sym->thunk_v3.thunk_len);
2329 break;
2332 * Global and static functions.
2334 case S_GPROC32_16t:
2335 case S_LPROC32_16t:
2336 if (top_func) FIXME("nested function\n");
2337 top_func = symt_new_function(msc_dbg->module, compiland,
2338 terminate_string(&sym->proc_v1.p_name),
2339 codeview_get_address(msc_dbg, sym->proc_v1.segment, sym->proc_v1.offset),
2340 sym->proc_v1.proc_len,
2341 codeview_get_type(sym->proc_v1.proctype, FALSE));
2342 curr_func = top_func;
2343 loc.kind = loc_absolute;
2344 loc.offset = sym->proc_v1.debug_start;
2345 symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, &loc, NULL);
2346 loc.offset = sym->proc_v1.debug_end;
2347 symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, &loc, NULL);
2348 break;
2349 case S_GPROC32_ST:
2350 case S_LPROC32_ST:
2351 if (top_func) FIXME("nested function\n");
2352 top_func = symt_new_function(msc_dbg->module, compiland,
2353 terminate_string(&sym->proc_v2.p_name),
2354 codeview_get_address(msc_dbg, sym->proc_v2.segment, sym->proc_v2.offset),
2355 sym->proc_v2.proc_len,
2356 codeview_get_type(sym->proc_v2.proctype, FALSE));
2357 curr_func = top_func;
2358 loc.kind = loc_absolute;
2359 loc.offset = sym->proc_v2.debug_start;
2360 symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, &loc, NULL);
2361 loc.offset = sym->proc_v2.debug_end;
2362 symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, &loc, NULL);
2363 break;
2364 case S_GPROC32:
2365 case S_LPROC32:
2366 if (top_func) FIXME("nested function\n");
2367 top_func = symt_new_function(msc_dbg->module, compiland,
2368 sym->proc_v3.name,
2369 codeview_get_address(msc_dbg, sym->proc_v3.segment, sym->proc_v3.offset),
2370 sym->proc_v3.proc_len,
2371 codeview_get_type(sym->proc_v3.proctype, FALSE));
2372 curr_func = top_func;
2373 loc.kind = loc_absolute;
2374 loc.offset = sym->proc_v3.debug_start;
2375 symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, &loc, NULL);
2376 loc.offset = sym->proc_v3.debug_end;
2377 symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, &loc, NULL);
2378 break;
2380 * Function parameters and stack variables.
2382 case S_BPREL32_16t:
2383 loc.kind = loc_regrel;
2384 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2385 loc.reg = CV_REG_EBP;
2386 loc.offset = sym->stack_v1.offset;
2387 symt_add_func_local(msc_dbg->module, curr_func,
2388 sym->stack_v1.offset > 0 ? DataIsParam : DataIsLocal,
2389 &loc, block,
2390 codeview_get_type(sym->stack_v1.symtype, FALSE),
2391 terminate_string(&sym->stack_v1.p_name));
2392 break;
2393 case S_BPREL32_ST:
2394 loc.kind = loc_regrel;
2395 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2396 loc.reg = CV_REG_EBP;
2397 loc.offset = sym->stack_v2.offset;
2398 symt_add_func_local(msc_dbg->module, curr_func,
2399 sym->stack_v2.offset > 0 ? DataIsParam : DataIsLocal,
2400 &loc, block,
2401 codeview_get_type(sym->stack_v2.symtype, FALSE),
2402 terminate_string(&sym->stack_v2.p_name));
2403 break;
2404 case S_BPREL32:
2405 /* S_BPREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2406 if (func_has_local(curr_func, sym->stack_v3.name)) break;
2407 loc.kind = loc_regrel;
2408 /* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
2409 loc.reg = CV_REG_EBP;
2410 loc.offset = sym->stack_v3.offset;
2411 symt_add_func_local(msc_dbg->module, curr_func,
2412 sym->stack_v3.offset > 0 ? DataIsParam : DataIsLocal,
2413 &loc, block,
2414 codeview_get_type(sym->stack_v3.symtype, FALSE),
2415 sym->stack_v3.name);
2416 break;
2417 case S_REGREL32:
2418 /* S_REGREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
2419 if (func_has_local(curr_func, sym->regrel_v3.name)) break;
2420 loc.kind = loc_regrel;
2421 loc.reg = sym->regrel_v3.reg;
2422 loc.offset = sym->regrel_v3.offset;
2423 symt_add_func_local(msc_dbg->module, curr_func,
2424 /* FIXME this is wrong !!! */
2425 sym->regrel_v3.offset > 0 ? DataIsParam : DataIsLocal,
2426 &loc, block,
2427 codeview_get_type(sym->regrel_v3.symtype, FALSE),
2428 sym->regrel_v3.name);
2429 break;
2431 case S_REGISTER_16t:
2432 loc.kind = loc_register;
2433 loc.reg = sym->register_v1.reg;
2434 loc.offset = 0;
2435 symt_add_func_local(msc_dbg->module, curr_func,
2436 DataIsLocal, &loc,
2437 block, codeview_get_type(sym->register_v1.type, FALSE),
2438 terminate_string(&sym->register_v1.p_name));
2439 break;
2440 case S_REGISTER_ST:
2441 loc.kind = loc_register;
2442 loc.reg = sym->register_v2.reg;
2443 loc.offset = 0;
2444 symt_add_func_local(msc_dbg->module, curr_func,
2445 DataIsLocal, &loc,
2446 block, codeview_get_type(sym->register_v2.type, FALSE),
2447 terminate_string(&sym->register_v2.p_name));
2448 break;
2449 case S_REGISTER:
2450 /* S_REGISTER can be present after S_LOCAL; prefer S_LOCAL when present */
2451 if (func_has_local(curr_func, sym->register_v3.name)) break;
2452 loc.kind = loc_register;
2453 loc.reg = sym->register_v3.reg;
2454 loc.offset = 0;
2455 symt_add_func_local(msc_dbg->module, curr_func,
2456 DataIsLocal, &loc,
2457 block, codeview_get_type(sym->register_v3.type, FALSE),
2458 sym->register_v3.name);
2459 break;
2461 case S_BLOCK32_ST:
2462 block = symt_open_func_block(msc_dbg->module, curr_func, block, 1);
2463 block->ranges[0].low = codeview_get_address(msc_dbg, sym->block_v1.segment, sym->block_v1.offset);
2464 block->ranges[0].high = block->ranges[0].low + sym->block_v1.length;
2465 break;
2466 case S_BLOCK32:
2467 block = symt_open_func_block(msc_dbg->module, curr_func, block, 1);
2468 block->ranges[0].low = codeview_get_address(msc_dbg, sym->block_v3.segment, sym->block_v3.offset);
2469 block->ranges[0].high = block->ranges[0].low + sym->block_v3.length;
2470 break;
2472 case S_END:
2473 if (block)
2475 block = symt_close_func_block(msc_dbg->module, curr_func, block);
2477 else if (top_func)
2479 if (curr_func != top_func) FIXME("shouldn't close a top function with an opened inlined function\n");
2480 top_func = curr_func = NULL;
2482 break;
2484 case S_COMPILE:
2485 TRACE("S-Compile-V1 machine:%x language:%x %s\n",
2486 sym->compile_v1.machine, sym->compile_v1.flags.language, terminate_string(&sym->compile_v1.p_name));
2487 break;
2489 case S_COMPILE2_ST:
2490 TRACE("S-Compile-V2 machine:%x language:%x %s\n",
2491 sym->compile2_v2.machine, sym->compile2_v2.flags.iLanguage, terminate_string(&sym->compile2_v2.p_name));
2492 break;
2494 case S_COMPILE2:
2495 TRACE("S-Compile-V3 machine:%x language:%x %s\n", sym->compile2_v3.machine, sym->compile2_v3.flags.iLanguage, sym->compile2_v3.name);
2496 break;
2498 case S_COMPILE3:
2499 TRACE("S-Compile3-V3 machine:%x language:%x %s\n", sym->compile3_v3.machine, sym->compile3_v3.flags.iLanguage, sym->compile3_v3.name);
2500 break;
2502 case S_ENVBLOCK:
2503 break;
2505 case S_OBJNAME:
2506 TRACE("S-ObjName-V3 %s\n", sym->objname_v3.name);
2507 compiland = symt_new_compiland(msc_dbg->module,
2508 source_new(msc_dbg->module, NULL,
2509 sym->objname_v3.name));
2510 break;
2512 case S_OBJNAME_ST:
2513 TRACE("S-ObjName-V1 %s\n", terminate_string(&sym->objname_v1.p_name));
2514 compiland = symt_new_compiland(msc_dbg->module,
2515 source_new(msc_dbg->module, NULL,
2516 terminate_string(&sym->objname_v1.p_name)));
2517 break;
2519 case S_LABEL32_ST:
2520 if (curr_func)
2522 loc.kind = loc_absolute;
2523 loc.offset = codeview_get_address(msc_dbg, sym->label_v1.segment, sym->label_v1.offset) - curr_func->address;
2524 symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel, &loc,
2525 terminate_string(&sym->label_v1.p_name));
2527 else symt_new_label(msc_dbg->module, compiland,
2528 terminate_string(&sym->label_v1.p_name),
2529 codeview_get_address(msc_dbg, sym->label_v1.segment, sym->label_v1.offset));
2530 break;
2531 case S_LABEL32:
2532 if (curr_func)
2534 loc.kind = loc_absolute;
2535 loc.offset = codeview_get_address(msc_dbg, sym->label_v3.segment, sym->label_v3.offset) - curr_func->address;
2536 symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel,
2537 &loc, sym->label_v3.name);
2539 else symt_new_label(msc_dbg->module, compiland, sym->label_v3.name,
2540 codeview_get_address(msc_dbg, sym->label_v3.segment, sym->label_v3.offset));
2541 break;
2543 case S_CONSTANT_16t:
2545 int vlen;
2546 const struct p_string* name;
2547 struct symt* se;
2548 VARIANT v;
2550 vlen = leaf_as_variant(&v, &sym->constant_v1.cvalue);
2551 name = (const struct p_string*)((const char*)&sym->constant_v1.cvalue + vlen);
2552 se = codeview_get_type(sym->constant_v1.type, FALSE);
2554 TRACE("S-Constant-V1 %u %s %x\n",
2555 v.n1.n2.n3.intVal, terminate_string(name), sym->constant_v1.type);
2556 symt_new_constant(msc_dbg->module, compiland, terminate_string(name),
2557 se, &v);
2559 break;
2560 case S_CONSTANT_ST:
2562 int vlen;
2563 const struct p_string* name;
2564 struct symt* se;
2565 VARIANT v;
2567 vlen = leaf_as_variant(&v, &sym->constant_v2.cvalue);
2568 name = (const struct p_string*)((const char*)&sym->constant_v2.cvalue + vlen);
2569 se = codeview_get_type(sym->constant_v2.type, FALSE);
2571 TRACE("S-Constant-V2 %u %s %x\n",
2572 v.n1.n2.n3.intVal, terminate_string(name), sym->constant_v2.type);
2573 symt_new_constant(msc_dbg->module, compiland, terminate_string(name),
2574 se, &v);
2576 break;
2577 case S_CONSTANT:
2579 int vlen;
2580 const char* name;
2581 struct symt* se;
2582 VARIANT v;
2584 vlen = leaf_as_variant(&v, &sym->constant_v3.cvalue);
2585 name = (const char*)&sym->constant_v3.cvalue + vlen;
2586 se = codeview_get_type(sym->constant_v3.type, FALSE);
2588 TRACE("S-Constant-V3 %u %s %x\n",
2589 v.n1.n2.n3.intVal, name, sym->constant_v3.type);
2590 /* FIXME: we should add this as a constant value */
2591 symt_new_constant(msc_dbg->module, compiland, name, se, &v);
2593 break;
2595 case S_UDT_16t:
2596 if (sym->udt_v1.type)
2598 if ((symt = codeview_get_type(sym->udt_v1.type, FALSE)))
2599 symt_new_typedef(msc_dbg->module, symt,
2600 terminate_string(&sym->udt_v1.p_name));
2601 else
2602 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2603 terminate_string(&sym->udt_v1.p_name), sym->udt_v1.type);
2605 break;
2606 case S_UDT_ST:
2607 if (sym->udt_v2.type)
2609 if ((symt = codeview_get_type(sym->udt_v2.type, FALSE)))
2610 symt_new_typedef(msc_dbg->module, symt,
2611 terminate_string(&sym->udt_v2.p_name));
2612 else
2613 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2614 terminate_string(&sym->udt_v2.p_name), sym->udt_v2.type);
2616 break;
2617 case S_UDT:
2618 if (sym->udt_v3.type)
2620 if ((symt = codeview_get_type(sym->udt_v3.type, FALSE)))
2621 symt_new_typedef(msc_dbg->module, symt, sym->udt_v3.name);
2622 else
2623 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2624 sym->udt_v3.name, sym->udt_v3.type);
2626 break;
2627 case S_LOCAL:
2628 /* FIXME: don't store global/static variables accessed through registers... we don't support that
2629 * in locals... anyway, global data record should be present as well (so the variable will be available
2630 * through the global definition, but potentially not updated)
2632 if (!sym->local_v3.varflags.enreg_global && !sym->local_v3.varflags.enreg_static)
2634 length += codeview_transform_defrange(msc_dbg, curr_func, sym, &loc);
2635 symt_add_func_local(msc_dbg->module, curr_func,
2636 sym->local_v3.varflags.is_param ? DataIsParam : DataIsLocal,
2637 &loc, block,
2638 codeview_get_type(sym->local_v3.symtype, FALSE),
2639 sym->local_v3.name);
2641 else
2642 length += codeview_defrange_length(sym);
2643 break;
2644 case S_INLINESITE:
2646 struct symt_inlinesite* inlined = codeview_create_inline_site(msc_dbg, cvmod, top_func,
2647 block ? &block->symt : &curr_func->symt,
2648 sym->inline_site_v3.inlinee,
2649 sym->inline_site_v3.binaryAnnotations,
2650 (const unsigned char*)sym + length);
2651 if (inlined)
2653 curr_func = (struct symt_function*)inlined;
2654 block = NULL;
2656 else
2658 /* skip all records until paired S_INLINESITE_END */
2659 sym = (const union codeview_symbol*)(root + sym->inline_site_v3.pEnd);
2660 if (sym->generic.id != S_INLINESITE_END) FIXME("complete wreckage\n");
2661 length = sym->inline_site_v3.pEnd - i + sym->generic.len;
2664 break;
2665 case S_INLINESITE2:
2667 struct symt_inlinesite* inlined = codeview_create_inline_site(msc_dbg, cvmod, top_func,
2668 block ? &block->symt : &curr_func->symt,
2669 sym->inline_site2_v3.inlinee,
2670 sym->inline_site2_v3.binaryAnnotations,
2671 (const unsigned char*)sym + length);
2672 if (inlined)
2674 curr_func = (struct symt_function*)inlined;
2675 block = NULL;
2677 else
2679 /* skip all records until paired S_INLINESITE_END */
2680 sym = (const union codeview_symbol*)(root + sym->inline_site2_v3.pEnd);
2681 if (sym->generic.id != S_INLINESITE_END) FIXME("complete wreckage\n");
2682 length = sym->inline_site_v3.pEnd - i + sym->generic.len;
2685 break;
2687 case S_INLINESITE_END:
2688 block = symt_check_tag(curr_func->container, SymTagBlock) ?
2689 (struct symt_block*)curr_func->container : NULL;
2690 curr_func = (struct symt_function*)symt_get_upper_inlined((struct symt_inlinesite*)curr_func);
2691 break;
2694 * These are special, in that they are always followed by an
2695 * additional length-prefixed string which is *not* included
2696 * into the symbol length count. We need to skip it.
2698 case S_PROCREF_ST:
2699 case S_DATAREF_ST:
2700 case S_LPROCREF_ST:
2702 const char* name;
2704 name = (const char*)sym + length;
2705 length += (*name + 1 + 3) & ~3;
2706 break;
2709 case S_SSEARCH:
2710 TRACE("Start search: seg=0x%x at offset 0x%08x\n",
2711 sym->ssearch_v1.segment, sym->ssearch_v1.offset);
2712 break;
2714 case S_ALIGN:
2715 TRACE("S-Align V1\n");
2716 break;
2717 case S_HEAPALLOCSITE:
2718 TRACE("S-heap site V3: offset=0x%08x at sect_idx 0x%04x, inst_len 0x%08x, index 0x%08x\n",
2719 sym->heap_alloc_site_v3.offset, sym->heap_alloc_site_v3.sect_idx,
2720 sym->heap_alloc_site_v3.inst_len, sym->heap_alloc_site_v3.index);
2721 break;
2723 case S_SEPCODE:
2724 if (!top_func)
2726 ULONG_PTR parent_addr = codeview_get_address(msc_dbg, sym->sepcode_v3.sectParent, sym->sepcode_v3.offParent);
2727 struct symt_ht* parent = symt_find_symbol_at(msc_dbg->module, parent_addr);
2728 if (symt_check_tag(&parent->symt, SymTagFunction))
2730 struct symt_function* pfunc = (struct symt_function*)parent;
2731 top_func = symt_new_function(msc_dbg->module, compiland, pfunc->hash_elt.name,
2732 codeview_get_address(msc_dbg, sym->sepcode_v3.sect, sym->sepcode_v3.off),
2733 sym->sepcode_v3.length, pfunc->type);
2734 curr_func = top_func;
2736 else
2737 WARN("Couldn't find function referenced by S_SEPCODE at %04x:%08x\n",
2738 sym->sepcode_v3.sectParent, sym->sepcode_v3.offParent);
2740 else
2741 FIXME("S_SEPCODE inside top-level function %s\n", top_func->hash_elt.name);
2742 break;
2744 /* the symbols we can safely ignore for now */
2745 case S_TRAMPOLINE:
2746 case S_FRAMEPROC:
2747 case S_FRAMECOOKIE:
2748 case S_SECTION:
2749 case S_COFFGROUP:
2750 case S_EXPORT:
2751 case S_CALLSITEINFO:
2752 /* even if S_LOCAL groks all the S_DEFRANGE* records following itself,
2753 * those kinds of records can also be present after a S_FILESTATIC record
2754 * so silence them until (at least) S_FILESTATIC is supported
2756 case S_DEFRANGE_REGISTER:
2757 case S_DEFRANGE_FRAMEPOINTER_REL:
2758 case S_DEFRANGE_SUBFIELD_REGISTER:
2759 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
2760 case S_DEFRANGE_REGISTER_REL:
2761 case S_BUILDINFO:
2762 case S_FILESTATIC:
2763 case S_CALLEES:
2764 case S_CALLERS:
2765 case S_UNAMESPACE:
2766 case S_INLINEES:
2767 case S_POGODATA:
2768 TRACE("Unsupported symbol id %x\n", sym->generic.id);
2769 break;
2771 default:
2772 FIXME("Unsupported symbol id %x\n", sym->generic.id);
2773 dump(sym, 2 + sym->generic.len);
2774 break;
2777 if (cvmod) codeview_snarf_linetab2(msc_dbg, cvmod);
2778 return TRUE;
2781 static BOOL codeview_is_inside(const struct cv_local_info* locinfo, const struct symt_function* func, DWORD_PTR ip)
2783 unsigned i;
2784 /* ip must be in local_info range, but not in any of its gaps */
2785 if (ip < locinfo->start || ip >= locinfo->start + locinfo->rangelen) return FALSE;
2786 for (i = 0; i < locinfo->ngaps; ++i)
2787 if (func->address + locinfo->gaps[i].gapStartOffset <= ip &&
2788 ip < func->address + locinfo->gaps[i].gapStartOffset + locinfo->gaps[i].cbRange)
2789 return FALSE;
2790 return TRUE;
2793 static void pdb_location_compute(struct process* pcs,
2794 const struct module_format* modfmt,
2795 const struct symt_function* func,
2796 struct location* loc)
2798 const struct cv_local_info* locinfo;
2800 switch (loc->kind)
2802 case loc_cv_local_range:
2803 for (locinfo = (const struct cv_local_info*)loc->offset;
2804 locinfo->kind != 0;
2805 locinfo = (const struct cv_local_info*)((const char*)(locinfo + 1) + locinfo->ngaps * sizeof(locinfo->gaps[0])))
2807 if (!codeview_is_inside(locinfo, func, pcs->localscope_pc)) continue;
2808 switch (locinfo->kind)
2810 case S_DEFRANGE:
2811 case S_DEFRANGE_SUBFIELD:
2812 default:
2813 FIXME("Unsupported defrange %d\n", locinfo->kind);
2814 loc->kind = loc_error;
2815 loc->reg = loc_err_internal;
2816 return;
2817 case S_DEFRANGE_SUBFIELD_REGISTER:
2818 FIXME("sub-field part not handled\n");
2819 /* fall through */
2820 case S_DEFRANGE_REGISTER:
2821 loc->kind = loc_register;
2822 loc->reg = locinfo->reg;
2823 return;
2824 case S_DEFRANGE_REGISTER_REL:
2825 loc->kind = loc_regrel;
2826 loc->reg = locinfo->reg;
2827 loc->offset = locinfo->offset;
2828 return;
2829 case S_DEFRANGE_FRAMEPOINTER_REL:
2830 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
2831 loc->kind = loc_regrel;
2832 loc->reg = dbghelp_current_cpu->frame_regno;
2833 loc->offset = locinfo->offset;
2834 return;
2837 break;
2838 default: break;
2840 loc->kind = loc_error;
2841 loc->reg = loc_err_internal;
2844 static void* pdb_read_file(const struct pdb_file_info* pdb_file, DWORD file_nr);
2845 static unsigned pdb_get_file_size(const struct pdb_file_info* pdb_file, DWORD file_nr);
2847 static BOOL codeview_snarf_sym_hashtable(const struct msc_debug_info* msc_dbg, const BYTE* symroot, DWORD symsize,
2848 const BYTE* hashroot, DWORD hashsize,
2849 BOOL (*feed)(const struct msc_debug_info* msc_dbg, const union codeview_symbol*))
2851 const DBI_HASH_HEADER* hash_hdr = (const DBI_HASH_HEADER*)hashroot;
2852 unsigned num_hash_records, i;
2853 const DBI_HASH_RECORD* hr;
2855 if (hashsize < sizeof(DBI_HASH_HEADER) ||
2856 hash_hdr->signature != 0xFFFFFFFF ||
2857 hash_hdr->version != 0xeffe0000 + 19990810 ||
2858 (hash_hdr->size_hash_records % sizeof(DBI_HASH_RECORD)) != 0 ||
2859 sizeof(DBI_HASH_HEADER) + hash_hdr->size_hash_records + DBI_BITMAP_HASH_SIZE > hashsize ||
2860 (hashsize - (sizeof(DBI_HASH_HEADER) + hash_hdr->size_hash_records + DBI_BITMAP_HASH_SIZE)) % sizeof(unsigned))
2862 FIXME("Incorrect hash structure\n");
2863 return FALSE;
2866 hr = (DBI_HASH_RECORD*)(hash_hdr + 1);
2867 num_hash_records = hash_hdr->size_hash_records / sizeof(DBI_HASH_RECORD);
2869 /* Only iterate over the records listed in the hash table.
2870 * We assume that records present in stream, but not listed in hash table, are
2871 * invalid (and thus not loaded).
2873 for (i = 0; i < num_hash_records; i++)
2875 if (hr[i].offset && hr[i].offset < symsize)
2877 const union codeview_symbol* sym = (const union codeview_symbol*)(symroot + hr[i].offset - 1);
2878 (*feed)(msc_dbg, sym);
2881 return TRUE;
2884 static BOOL pdb_global_feed_types(const struct msc_debug_info* msc_dbg, const union codeview_symbol* sym)
2886 struct symt* symt;
2887 switch (sym->generic.id)
2889 case S_UDT_16t:
2890 if (sym->udt_v1.type)
2892 if ((symt = codeview_get_type(sym->udt_v1.type, FALSE)))
2893 symt_new_typedef(msc_dbg->module, symt,
2894 terminate_string(&sym->udt_v1.p_name));
2895 else
2896 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2897 terminate_string(&sym->udt_v1.p_name), sym->udt_v1.type);
2899 break;
2900 case S_UDT_ST:
2901 if (sym->udt_v2.type)
2903 if ((symt = codeview_get_type(sym->udt_v2.type, FALSE)))
2904 symt_new_typedef(msc_dbg->module, symt,
2905 terminate_string(&sym->udt_v2.p_name));
2906 else
2907 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2908 terminate_string(&sym->udt_v2.p_name), sym->udt_v2.type);
2910 break;
2911 case S_UDT:
2912 if (sym->udt_v3.type)
2914 if ((symt = codeview_get_type(sym->udt_v3.type, FALSE)))
2915 symt_new_typedef(msc_dbg->module, symt, sym->udt_v3.name);
2916 else
2917 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2918 sym->udt_v3.name, sym->udt_v3.type);
2920 break;
2921 default: return FALSE;
2923 return TRUE;
2926 static BOOL pdb_global_feed_variables(const struct msc_debug_info* msc_dbg, const union codeview_symbol* sym)
2928 /* The only interest here is to add global variables that haven't been seen
2929 * in module (=compilation unit) stream.
2930 * So we don't care about 'local' symbols since we cannot tell their compiland.
2932 switch (sym->generic.id)
2934 case S_GDATA32_16t:
2935 codeview_add_variable(msc_dbg, NULL, NULL, NULL, terminate_string(&sym->data_v1.p_name),
2936 sym->data_v1.segment, sym->data_v1.offset, sym->data_v1.symtype,
2937 FALSE, FALSE, FALSE);
2938 break;
2939 case S_GDATA32_ST:
2940 codeview_add_variable(msc_dbg, NULL, NULL, NULL, terminate_string(&sym->data_v2.p_name),
2941 sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype,
2942 FALSE, FALSE, FALSE);
2943 break;
2944 case S_GDATA32:
2945 codeview_add_variable(msc_dbg, NULL, NULL, NULL, sym->data_v3.name,
2946 sym->data_v3.segment, sym->data_v3.offset, sym->data_v3.symtype,
2947 FALSE, FALSE, FALSE);
2948 break;
2949 /* variables with thread storage */
2950 case S_GTHREAD32_16t:
2951 codeview_add_variable(msc_dbg, NULL, NULL, NULL, terminate_string(&sym->thread_v1.p_name),
2952 sym->thread_v1.segment, sym->thread_v1.offset, sym->thread_v1.symtype,
2953 FALSE, TRUE, FALSE);
2954 break;
2955 case S_GTHREAD32_ST:
2956 codeview_add_variable(msc_dbg, NULL, NULL, NULL, terminate_string(&sym->thread_v2.p_name),
2957 sym->thread_v2.segment, sym->thread_v2.offset, sym->thread_v2.symtype,
2958 FALSE, TRUE, FALSE);
2959 break;
2960 case S_GTHREAD32:
2961 codeview_add_variable(msc_dbg, NULL, NULL, NULL, sym->thread_v3.name,
2962 sym->thread_v3.segment, sym->thread_v3.offset, sym->thread_v3.symtype,
2963 FALSE, TRUE, FALSE);
2964 break;
2965 default: return FALSE;
2967 return TRUE;
2970 static BOOL pdb_global_feed_public(const struct msc_debug_info* msc_dbg, const union codeview_symbol* sym)
2972 switch (sym->generic.id)
2974 case S_PUB32_16t:
2975 symt_new_public(msc_dbg->module, NULL,
2976 terminate_string(&sym->public_v1.p_name),
2977 sym->public_v1.pubsymflags == SYMTYPE_FUNCTION,
2978 codeview_get_address(msc_dbg, sym->public_v1.segment, sym->public_v1.offset), 1);
2979 break;
2980 case S_PUB32_ST:
2981 symt_new_public(msc_dbg->module, NULL,
2982 terminate_string(&sym->public_v2.p_name),
2983 sym->public_v2.pubsymflags == SYMTYPE_FUNCTION,
2984 codeview_get_address(msc_dbg, sym->public_v2.segment, sym->public_v2.offset), 1);
2985 break;
2986 case S_PUB32:
2987 symt_new_public(msc_dbg->module, NULL,
2988 sym->public_v3.name,
2989 sym->public_v3.pubsymflags == SYMTYPE_FUNCTION,
2990 codeview_get_address(msc_dbg, sym->public_v3.segment, sym->public_v3.offset), 1);
2991 break;
2992 default: return FALSE;
2994 return TRUE;
2997 /*========================================================================
2998 * Process PDB file.
3001 static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list,
3002 int size)
3004 int i, num_blocks;
3005 BYTE* buffer;
3007 if (!size) return NULL;
3009 num_blocks = (size + pdb->block_size - 1) / pdb->block_size;
3010 buffer = HeapAlloc(GetProcessHeap(), 0, num_blocks * pdb->block_size);
3012 for (i = 0; i < num_blocks; i++)
3013 memcpy(buffer + i * pdb->block_size,
3014 (const char*)pdb + block_list[i] * pdb->block_size, pdb->block_size);
3016 return buffer;
3019 static void* pdb_ds_read(const struct PDB_DS_HEADER* pdb, const UINT *block_list,
3020 int size)
3022 int i, num_blocks;
3023 BYTE* buffer;
3025 if (!size) return NULL;
3027 num_blocks = (size + pdb->block_size - 1) / pdb->block_size;
3028 buffer = HeapAlloc(GetProcessHeap(), 0, num_blocks * pdb->block_size);
3030 for (i = 0; i < num_blocks; i++)
3031 memcpy(buffer + i * pdb->block_size,
3032 (const char*)pdb + block_list[i] * pdb->block_size, pdb->block_size);
3034 return buffer;
3037 static void* pdb_read_jg_file(const struct PDB_JG_HEADER* pdb,
3038 const struct PDB_JG_TOC* toc, DWORD file_nr)
3040 const WORD* block_list;
3041 DWORD i;
3043 if (!toc || file_nr >= toc->num_files) return NULL;
3045 block_list = (const WORD*) &toc->file[toc->num_files];
3046 for (i = 0; i < file_nr; i++)
3047 block_list += (toc->file[i].size + pdb->block_size - 1) / pdb->block_size;
3049 return pdb_jg_read(pdb, block_list, toc->file[file_nr].size);
3052 static void* pdb_read_ds_file(const struct PDB_DS_HEADER* pdb,
3053 const struct PDB_DS_TOC* toc, DWORD file_nr)
3055 const UINT *block_list;
3056 DWORD i;
3058 if (!toc || file_nr >= toc->num_files) return NULL;
3059 if (toc->file_size[file_nr] == 0 || toc->file_size[file_nr] == 0xFFFFFFFF) return NULL;
3061 block_list = &toc->file_size[toc->num_files];
3062 for (i = 0; i < file_nr; i++)
3063 block_list += (toc->file_size[i] + pdb->block_size - 1) / pdb->block_size;
3065 return pdb_ds_read(pdb, block_list, toc->file_size[file_nr]);
3068 static void* pdb_read_file(const struct pdb_file_info* pdb_file,
3069 DWORD file_nr)
3071 switch (pdb_file->kind)
3073 case PDB_JG:
3074 return pdb_read_jg_file((const struct PDB_JG_HEADER*)pdb_file->image,
3075 pdb_file->u.jg.toc, file_nr);
3076 case PDB_DS:
3077 return pdb_read_ds_file((const struct PDB_DS_HEADER*)pdb_file->image,
3078 pdb_file->u.ds.toc, file_nr);
3080 return NULL;
3083 static unsigned pdb_get_file_size(const struct pdb_file_info* pdb_file, DWORD file_nr)
3085 switch (pdb_file->kind)
3087 case PDB_JG: return pdb_file->u.jg.toc->file[file_nr].size;
3088 case PDB_DS: return pdb_file->u.ds.toc->file_size[file_nr];
3090 return 0;
3093 static void pdb_free(void* buffer)
3095 HeapFree(GetProcessHeap(), 0, buffer);
3098 static void pdb_free_file(struct pdb_file_info* pdb_file)
3100 switch (pdb_file->kind)
3102 case PDB_JG:
3103 pdb_free(pdb_file->u.jg.toc);
3104 pdb_file->u.jg.toc = NULL;
3105 break;
3106 case PDB_DS:
3107 pdb_free(pdb_file->u.ds.toc);
3108 pdb_file->u.ds.toc = NULL;
3109 break;
3111 HeapFree(GetProcessHeap(), 0, pdb_file->stream_dict);
3114 static BOOL pdb_load_stream_name_table(struct pdb_file_info* pdb_file, const char* str, unsigned cb)
3116 DWORD* pdw;
3117 DWORD* ok_bits;
3118 DWORD count, numok;
3119 unsigned i, j;
3120 char* cpstr;
3122 pdw = (DWORD*)(str + cb);
3123 numok = *pdw++;
3124 count = *pdw++;
3126 pdb_file->stream_dict = HeapAlloc(GetProcessHeap(), 0, (numok + 1) * sizeof(struct pdb_stream_name) + cb);
3127 if (!pdb_file->stream_dict) return FALSE;
3128 cpstr = (char*)(pdb_file->stream_dict + numok + 1);
3129 memcpy(cpstr, str, cb);
3131 /* bitfield: first dword is len (in dword), then data */
3132 ok_bits = pdw;
3133 pdw += *ok_bits++ + 1;
3134 if (*pdw++ != 0)
3136 FIXME("unexpected value\n");
3137 return FALSE;
3140 for (i = j = 0; i < count; i++)
3142 if (ok_bits[i / 32] & (1 << (i % 32)))
3144 if (j >= numok) break;
3145 pdb_file->stream_dict[j].name = &cpstr[*pdw++];
3146 pdb_file->stream_dict[j].index = *pdw++;
3147 j++;
3150 /* add sentinel */
3151 pdb_file->stream_dict[numok].name = NULL;
3152 pdb_file->fpoext_stream = -1;
3153 return TRUE;
3156 static unsigned pdb_get_stream_by_name(const struct pdb_file_info* pdb_file, const char* name)
3158 struct pdb_stream_name* psn;
3160 for (psn = pdb_file->stream_dict; psn && psn->name; psn++)
3162 if (!strcmp(psn->name, name)) return psn->index;
3164 return -1;
3167 static PDB_STRING_TABLE* pdb_read_strings(const struct pdb_file_info* pdb_file)
3169 unsigned idx;
3170 PDB_STRING_TABLE *ret;
3172 idx = pdb_get_stream_by_name(pdb_file, "/names");
3173 if (idx != -1)
3175 ret = pdb_read_file( pdb_file, idx );
3176 if (ret && ret->magic == 0xeffeeffe &&
3177 sizeof(*ret) + ret->length <= pdb_get_file_size(pdb_file, idx)) return ret;
3178 pdb_free( ret );
3180 WARN("string table not found\n");
3181 return NULL;
3184 static const char* pdb_get_string_table_entry(const PDB_STRING_TABLE* table, unsigned offset)
3186 return (!table || offset >= table->length) ? NULL : (const char*)(table + 1) + offset;
3189 static void pdb_module_remove(struct process* pcsn, struct module_format* modfmt)
3191 unsigned i;
3193 for (i = 0; i < modfmt->u.pdb_info->used_subfiles; i++)
3195 pdb_free_file(&modfmt->u.pdb_info->pdb_files[i]);
3196 if (modfmt->u.pdb_info->pdb_files[i].image)
3197 UnmapViewOfFile(modfmt->u.pdb_info->pdb_files[i].image);
3198 if (modfmt->u.pdb_info->pdb_files[i].hMap)
3199 CloseHandle(modfmt->u.pdb_info->pdb_files[i].hMap);
3201 HeapFree(GetProcessHeap(), 0, modfmt);
3204 static BOOL pdb_convert_types_header(PDB_TYPES* types, const BYTE* image)
3206 if (!image) return FALSE;
3208 if (*(const DWORD*)image < 19960000) /* FIXME: correct version? */
3210 /* Old version of the types record header */
3211 const PDB_TYPES_OLD* old = (const PDB_TYPES_OLD*)image;
3212 memset(types, 0, sizeof(PDB_TYPES));
3213 types->version = old->version;
3214 types->type_offset = sizeof(PDB_TYPES_OLD);
3215 types->type_size = old->type_size;
3216 types->first_index = old->first_index;
3217 types->last_index = old->last_index;
3218 types->hash_file = old->hash_file;
3220 else
3222 /* New version of the types record header */
3223 *types = *(const PDB_TYPES*)image;
3225 return TRUE;
3228 static void pdb_convert_symbols_header(PDB_SYMBOLS* symbols,
3229 int* header_size, const BYTE* image)
3231 memset(symbols, 0, sizeof(PDB_SYMBOLS));
3232 if (!image) return;
3234 if (*(const DWORD*)image != 0xffffffff)
3236 /* Old version of the symbols record header */
3237 const PDB_SYMBOLS_OLD* old = (const PDB_SYMBOLS_OLD*)image;
3238 symbols->version = 0;
3239 symbols->module_size = old->module_size;
3240 symbols->offset_size = old->offset_size;
3241 symbols->hash_size = old->hash_size;
3242 symbols->srcmodule_size = old->srcmodule_size;
3243 symbols->pdbimport_size = 0;
3244 symbols->global_hash_file= old->global_hash_file;
3245 symbols->public_file = old->public_file;
3246 symbols->gsym_file = old->gsym_file;
3248 *header_size = sizeof(PDB_SYMBOLS_OLD);
3250 else
3252 /* New version of the symbols record header */
3253 *symbols = *(const PDB_SYMBOLS*)image;
3254 *header_size = sizeof(PDB_SYMBOLS);
3258 static void pdb_convert_symbol_file(const PDB_SYMBOLS* symbols,
3259 PDB_SYMBOL_FILE_EX* sfile,
3260 unsigned* size, const void* image)
3263 if (symbols->version < 19970000)
3265 const PDB_SYMBOL_FILE *sym_file = image;
3266 memset(sfile, 0, sizeof(*sfile));
3267 sfile->file = sym_file->file;
3268 sfile->range.index = sym_file->range.index;
3269 sfile->symbol_size = sym_file->symbol_size;
3270 sfile->lineno_size = sym_file->lineno_size;
3271 sfile->lineno2_size = sym_file->lineno2_size;
3272 *size = sizeof(PDB_SYMBOL_FILE) - 1;
3274 else
3276 memcpy(sfile, image, sizeof(PDB_SYMBOL_FILE_EX));
3277 *size = sizeof(PDB_SYMBOL_FILE_EX) - 1;
3281 static HANDLE map_pdb_file(const struct process* pcs,
3282 const struct pdb_lookup* lookup,
3283 struct module* module)
3285 HANDLE hFile, hMap = NULL;
3286 WCHAR dbg_file_path[MAX_PATH];
3287 BOOL ret = FALSE;
3289 switch (lookup->kind)
3291 case PDB_JG:
3292 ret = path_find_symbol_file(pcs, module, lookup->filename, DMT_PDB, NULL, lookup->timestamp,
3293 lookup->age, dbg_file_path, &module->module.PdbUnmatched);
3294 break;
3295 case PDB_DS:
3296 ret = path_find_symbol_file(pcs, module, lookup->filename, DMT_PDB, &lookup->guid, 0,
3297 lookup->age, dbg_file_path, &module->module.PdbUnmatched);
3298 break;
3300 if (!ret)
3302 WARN("\tCouldn't find %s\n", lookup->filename);
3303 return NULL;
3305 if ((hFile = CreateFileW(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL,
3306 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
3308 hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
3309 CloseHandle(hFile);
3311 return hMap;
3314 static void pdb_dispose_type_parse(struct codeview_type_parse* ctp)
3316 pdb_free(ctp->hash_stream);
3317 free((DWORD*)ctp->offset);
3318 free((DWORD*)ctp->hash);
3319 free((DWORD*)ctp->alloc_hash);
3322 static BOOL pdb_bitfield_is_bit_set(const unsigned* dw, unsigned len, unsigned i)
3324 if (i >= len * sizeof(unsigned) * 8) return FALSE;
3325 return (dw[i >> 5] & (1u << (i & 31u))) != 0;
3328 static BOOL pdb_init_type_parse(const struct msc_debug_info* msc_dbg,
3329 const struct pdb_file_info* pdb_file,
3330 struct codeview_type_parse* ctp,
3331 BYTE* image)
3333 const BYTE* ptr;
3334 DWORD* offset;
3335 int i;
3337 ctp->hash_stream = NULL;
3338 ctp->offset = NULL;
3339 ctp->hash = NULL;
3340 ctp->alloc_hash = NULL;
3341 if (!pdb_convert_types_header(&ctp->header, image))
3342 return FALSE;
3344 /* Check for unknown versions */
3345 switch (ctp->header.version)
3347 case 19950410: /* VC 4.0 */
3348 case 19951122:
3349 case 19961031: /* VC 5.0 / 6.0 */
3350 case 19990903: /* VC 7.0 */
3351 case 20040203: /* VC 8.0 */
3352 break;
3353 default:
3354 ERR("-Unknown type info version %d\n", ctp->header.version);
3355 return FALSE;
3357 if (ctp->header.hash_size != 2 && ctp->header.hash_size != 4)
3359 ERR("-Unsupported hash of size %u\n", ctp->header.hash_size);
3360 return FALSE;
3362 ctp->hash_stream = pdb_read_file(pdb_file, ctp->header.hash_file);
3363 /* FIXME always present? if not reconstruct ?*/
3364 if (!ctp->hash_stream)
3366 ERR("-Missing hash table in PDB file\n");
3367 return FALSE;
3370 ctp->module = msc_dbg->module;
3371 /* Reconstruct the types offset table
3372 * Note: the hash subfile of the PDB_TYPES only contains a partial table
3373 * (not all the indexes are present, so it requires first a binary search in partial table,
3374 * followed by a linear search...)
3376 offset = malloc(sizeof(DWORD) * (ctp->header.last_index - ctp->header.first_index));
3377 if (!offset) goto oom;
3378 ctp->table = ptr = image + ctp->header.type_offset;
3379 for (i = ctp->header.first_index; i < ctp->header.last_index; i++)
3381 offset[i - ctp->header.first_index] = ptr - ctp->table;
3382 ptr += ((const union codeview_type*)ptr)->generic.len + 2;
3384 ctp->offset = offset;
3385 ctp->hash = calloc(ctp->header.hash_num_buckets, sizeof(struct hash_link*));
3386 if (!ctp->hash) goto oom;
3387 ctp->alloc_hash = calloc(ctp->header.last_index - ctp->header.first_index, sizeof(struct hash_link));
3388 if (!ctp->alloc_hash) goto oom;
3389 for (i = ctp->header.first_index; i < ctp->header.last_index; i++)
3391 unsigned hash_i = pdb_read_hash_value(ctp, i);
3392 ctp->alloc_hash[i - ctp->header.first_index].id = i;
3393 ctp->alloc_hash[i - ctp->header.first_index].next = ctp->hash[hash_i];
3394 ctp->hash[hash_i] = &ctp->alloc_hash[i - ctp->header.first_index];
3396 /* parse the remap table
3397 * => move listed type_id at first position of their hash buckets so that we force remap to them
3399 if (ctp->header.type_remap_len)
3401 const unsigned* remap = (const unsigned*)((const BYTE*)ctp->hash_stream + ctp->header.type_remap_offset);
3402 unsigned i, capa, count_present;
3403 const unsigned* present_bitset;
3404 remap++; /* no need of num */
3405 capa = *remap++;
3406 count_present = *remap++;
3407 present_bitset = remap;
3408 remap += count_present;
3409 remap += *remap + 1; /* skip deleted bit set */
3410 for (i = 0; i < capa; ++i)
3412 if (pdb_bitfield_is_bit_set(present_bitset, count_present, i))
3414 unsigned hash_i;
3415 struct hash_link** phl;
3416 /* remap[0] is an offset for a string in /string stream, followed by type_id to force */
3417 hash_i = pdb_read_hash_value(ctp, remap[1]);
3418 for (phl = &ctp->hash[hash_i]; *phl; phl = &(*phl)->next)
3419 if ((*phl)->id == remap[1])
3421 struct hash_link* hl = *phl;
3422 /* move hl node at first position of its hash bucket */
3423 *phl = hl->next;
3424 hl->next = ctp->hash[hash_i];
3425 ctp->hash[hash_i] = hl;
3426 break;
3428 remap += 2;
3432 return TRUE;
3433 oom:
3434 pdb_dispose_type_parse(ctp);
3435 return FALSE;
3438 static void pdb_process_types(const struct msc_debug_info* msc_dbg,
3439 const struct pdb_file_info* pdb_file)
3441 struct codeview_type_parse ctp;
3442 BYTE* types_image = pdb_read_file(pdb_file, 2);
3444 if (types_image)
3446 if (pdb_init_type_parse(msc_dbg, pdb_file, &ctp, types_image))
3448 /* Read type table */
3449 codeview_parse_type_table(&ctp);
3450 pdb_dispose_type_parse(&ctp);
3452 pdb_free(types_image);
3456 static const char PDB_JG_IDENT[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0";
3457 static const char PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
3459 /******************************************************************
3460 * pdb_init
3462 * Tries to load a pdb file
3463 * 'matched' is filled with the number of correct matches for this file:
3464 * - age counts for one
3465 * - timestamp or guid depending on kind counts for one
3466 * a wrong kind of file returns FALSE (FIXME ?)
3468 static BOOL pdb_init(const struct pdb_lookup* pdb_lookup, struct pdb_file_info* pdb_file,
3469 const char* image, unsigned* matched)
3471 BOOL ret = TRUE;
3473 /* check the file header, and if ok, load the TOC */
3474 TRACE("PDB(%s): %.40s\n", pdb_lookup->filename, debugstr_an(image, 40));
3476 *matched = 0;
3477 if (!memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT)))
3479 const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image;
3480 struct PDB_JG_ROOT* root;
3482 pdb_file->u.jg.toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size);
3483 root = pdb_read_jg_file(pdb, pdb_file->u.jg.toc, 1);
3484 if (!root)
3486 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
3487 return FALSE;
3489 switch (root->Version)
3491 case 19950623: /* VC 4.0 */
3492 case 19950814:
3493 case 19960307: /* VC 5.0 */
3494 case 19970604: /* VC 6.0 */
3495 break;
3496 default:
3497 ERR("-Unknown root block version %d\n", root->Version);
3499 if (pdb_lookup->kind != PDB_JG)
3501 WARN("Found %s, but wrong PDB kind\n", pdb_lookup->filename);
3502 pdb_free(root);
3503 return FALSE;
3505 pdb_file->kind = PDB_JG;
3506 pdb_file->u.jg.timestamp = root->TimeDateStamp;
3507 pdb_file->age = root->Age;
3508 if (root->TimeDateStamp == pdb_lookup->timestamp) (*matched)++;
3509 else WARN("Found %s, but wrong signature: %08x %08x\n",
3510 pdb_lookup->filename, root->TimeDateStamp, pdb_lookup->timestamp);
3511 if (root->Age == pdb_lookup->age) (*matched)++;
3512 else WARN("Found %s, but wrong age: %08x %08x\n",
3513 pdb_lookup->filename, root->Age, pdb_lookup->age);
3514 TRACE("found JG for %s: age=%x timestamp=%x\n",
3515 pdb_lookup->filename, root->Age, root->TimeDateStamp);
3516 ret = pdb_load_stream_name_table(pdb_file, &root->names[0], root->cbNames);
3517 pdb_free(root);
3519 else if (!memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT)))
3521 const struct PDB_DS_HEADER* pdb = (const struct PDB_DS_HEADER*)image;
3522 struct PDB_DS_ROOT* root;
3524 pdb_file->u.ds.toc =
3525 pdb_ds_read(pdb, (const UINT*)((const char*)pdb + pdb->toc_page * pdb->block_size),
3526 pdb->toc_size);
3527 root = pdb_read_ds_file(pdb, pdb_file->u.ds.toc, 1);
3528 if (!root)
3530 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
3531 return FALSE;
3533 switch (root->Version)
3535 case 20000404:
3536 break;
3537 default:
3538 ERR("-Unknown root block version %u\n", root->Version);
3540 pdb_file->kind = PDB_DS;
3541 pdb_file->u.ds.guid = root->guid;
3542 pdb_file->age = root->Age;
3543 if (!memcmp(&root->guid, &pdb_lookup->guid, sizeof(GUID))) (*matched)++;
3544 else WARN("Found %s, but wrong GUID: %s %s\n",
3545 pdb_lookup->filename, debugstr_guid(&root->guid),
3546 debugstr_guid(&pdb_lookup->guid));
3547 if (root->Age == pdb_lookup->age) (*matched)++;
3548 else WARN("Found %s, but wrong age: %08x %08x\n",
3549 pdb_lookup->filename, root->Age, pdb_lookup->age);
3550 TRACE("found DS for %s: age=%x guid=%s\n",
3551 pdb_lookup->filename, root->Age, debugstr_guid(&root->guid));
3552 ret = pdb_load_stream_name_table(pdb_file, &root->names[0], root->cbNames);
3554 pdb_free(root);
3557 if (0) /* some tool to dump the internal files from a PDB file */
3559 int i, num_files;
3561 switch (pdb_file->kind)
3563 case PDB_JG: num_files = pdb_file->u.jg.toc->num_files; break;
3564 case PDB_DS: num_files = pdb_file->u.ds.toc->num_files; break;
3567 for (i = 1; i < num_files; i++)
3569 unsigned char* x = pdb_read_file(pdb_file, i);
3570 FIXME("********************** [%u]: size=%08x\n",
3571 i, pdb_get_file_size(pdb_file, i));
3572 dump(x, pdb_get_file_size(pdb_file, i));
3573 pdb_free(x);
3576 return ret;
3579 static BOOL pdb_process_internal(const struct process* pcs,
3580 const struct msc_debug_info* msc_dbg,
3581 const struct pdb_lookup* pdb_lookup,
3582 struct pdb_module_info* pdb_module_info,
3583 unsigned module_index);
3585 static void pdb_process_symbol_imports(const struct process* pcs,
3586 const struct msc_debug_info* msc_dbg,
3587 const PDB_SYMBOLS* symbols,
3588 const void* symbols_image,
3589 const char* image,
3590 const struct pdb_lookup* pdb_lookup,
3591 struct pdb_module_info* pdb_module_info,
3592 unsigned module_index)
3594 if (module_index == -1 && symbols && symbols->pdbimport_size)
3596 const PDB_SYMBOL_IMPORT*imp;
3597 const void* first;
3598 const void* last;
3599 const char* ptr;
3600 int i = 0;
3601 struct pdb_file_info sf0 = pdb_module_info->pdb_files[0];
3603 imp = (const PDB_SYMBOL_IMPORT*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) +
3604 symbols->module_size + symbols->offset_size +
3605 symbols->hash_size + symbols->srcmodule_size);
3606 first = imp;
3607 last = (const char*)imp + symbols->pdbimport_size;
3608 while (imp < (const PDB_SYMBOL_IMPORT*)last)
3610 ptr = (const char*)imp + sizeof(*imp) + strlen(imp->filename);
3611 if (i >= CV_MAX_MODULES) FIXME("Out of bounds!!!\n");
3612 if (!stricmp(pdb_lookup->filename, imp->filename))
3614 if (module_index != -1) FIXME("Twice the entry\n");
3615 else module_index = i;
3616 pdb_module_info->pdb_files[i] = sf0;
3618 else
3620 struct pdb_lookup imp_pdb_lookup;
3622 /* FIXME: this is an import of a JG PDB file
3623 * how's a DS PDB handled ?
3625 imp_pdb_lookup.filename = imp->filename;
3626 imp_pdb_lookup.kind = PDB_JG;
3627 imp_pdb_lookup.timestamp = imp->TimeDateStamp;
3628 imp_pdb_lookup.age = imp->Age;
3629 TRACE("got for %s: age=%u ts=%x\n",
3630 imp->filename, imp->Age, imp->TimeDateStamp);
3631 pdb_process_internal(pcs, msc_dbg, &imp_pdb_lookup, pdb_module_info, i);
3633 i++;
3634 imp = (const PDB_SYMBOL_IMPORT*)((const char*)first + ((ptr - (const char*)first + strlen(ptr) + 1 + 3) & ~3));
3636 pdb_module_info->used_subfiles = i;
3638 if (module_index == -1)
3640 module_index = 0;
3641 pdb_module_info->used_subfiles = 1;
3643 cv_current_module = &cv_zmodules[module_index];
3644 if (cv_current_module->allowed) FIXME("Already allowed??\n");
3645 cv_current_module->allowed = TRUE;
3648 static BOOL pdb_process_internal(const struct process* pcs,
3649 const struct msc_debug_info* msc_dbg,
3650 const struct pdb_lookup* pdb_lookup,
3651 struct pdb_module_info* pdb_module_info,
3652 unsigned module_index)
3654 HANDLE hMap = NULL;
3655 char* image = NULL;
3656 BYTE* symbols_image = NULL;
3657 PDB_STRING_TABLE* files_image = NULL;
3658 unsigned matched;
3659 struct pdb_file_info* pdb_file;
3661 TRACE("Processing PDB file %s\n", pdb_lookup->filename);
3663 pdb_file = &pdb_module_info->pdb_files[module_index == -1 ? 0 : module_index];
3664 /* Open and map() .PDB file */
3665 if ((hMap = map_pdb_file(pcs, pdb_lookup, msc_dbg->module)) == NULL ||
3666 ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL))
3668 WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename);
3669 CloseHandle(hMap);
3670 return FALSE;
3672 if (!pdb_init(pdb_lookup, pdb_file, image, &matched) || matched != 2)
3674 CloseHandle(hMap);
3675 UnmapViewOfFile(image);
3676 return FALSE;
3679 pdb_file->hMap = hMap;
3680 pdb_file->image = image;
3681 symbols_image = pdb_read_file(pdb_file, 3);
3682 if (symbols_image)
3684 PDB_SYMBOLS symbols;
3685 BYTE* globalimage;
3686 BYTE* modimage;
3687 BYTE* ipi_image;
3688 struct codeview_type_parse ipi_ctp;
3689 BYTE* file;
3690 int header_size = 0;
3691 PDB_STREAM_INDEXES* psi;
3692 BOOL ipi_ok;
3694 pdb_convert_symbols_header(&symbols, &header_size, symbols_image);
3695 switch (symbols.version)
3697 case 0: /* VC 4.0 */
3698 case 19960307: /* VC 5.0 */
3699 case 19970606: /* VC 6.0 */
3700 case 19990903:
3701 break;
3702 default:
3703 ERR("-Unknown symbol info version %u %08x\n",
3704 symbols.version, symbols.version);
3707 switch (symbols.stream_index_size)
3709 case 0:
3710 case sizeof(PDB_STREAM_INDEXES_OLD):
3711 /* no fpo ext stream in this case */
3712 break;
3713 case sizeof(PDB_STREAM_INDEXES):
3714 psi = (PDB_STREAM_INDEXES*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) +
3715 symbols.module_size + symbols.offset_size +
3716 symbols.hash_size + symbols.srcmodule_size +
3717 symbols.pdbimport_size + symbols.unknown2_size);
3718 pdb_file->fpoext_stream = psi->FPO_EXT;
3719 break;
3720 default:
3721 FIXME("Unknown PDB_STREAM_INDEXES size (%u)\n", symbols.stream_index_size);
3722 pdb_free(symbols_image);
3723 return FALSE;
3725 files_image = pdb_read_strings(pdb_file);
3727 pdb_process_symbol_imports(pcs, msc_dbg, &symbols, symbols_image, image,
3728 pdb_lookup, pdb_module_info, module_index);
3729 pdb_process_types(msc_dbg, pdb_file);
3731 ipi_image = pdb_read_file(pdb_file, 4);
3732 ipi_ok = pdb_init_type_parse(msc_dbg, pdb_file, &ipi_ctp, ipi_image);
3734 /* Read global types first, so that lookup by name in module (=compilation unit)
3735 * streams' loading can succeed them.
3737 globalimage = pdb_read_file(pdb_file, symbols.gsym_file);
3738 if (globalimage)
3740 const BYTE* data;
3741 unsigned global_size = pdb_get_file_size(pdb_file, symbols.gsym_file);
3743 data = pdb_read_file(pdb_file, symbols.global_hash_file);
3744 if (data)
3746 codeview_snarf_sym_hashtable(msc_dbg, globalimage, global_size,
3747 data, pdb_get_file_size(pdb_file, symbols.global_hash_file),
3748 pdb_global_feed_types);
3749 pdb_free((void*)data);
3753 /* Read per-module symbols' tables */
3754 file = symbols_image + header_size;
3755 while (file - symbols_image < header_size + symbols.module_size)
3757 PDB_SYMBOL_FILE_EX sfile;
3758 const char* file_name;
3759 unsigned size;
3761 HeapValidate(GetProcessHeap(), 0, NULL);
3762 pdb_convert_symbol_file(&symbols, &sfile, &size, file);
3764 modimage = pdb_read_file(pdb_file, sfile.file);
3765 if (modimage)
3767 struct cv_module_snarf cvmod = {ipi_ok ? &ipi_ctp : NULL, (const void*)(modimage + sfile.symbol_size), sfile.lineno2_size,
3768 files_image};
3769 codeview_snarf(msc_dbg, modimage, sizeof(DWORD), sfile.symbol_size, &cvmod);
3771 if (sfile.lineno_size && sfile.lineno2_size)
3772 FIXME("Both line info present... only supporting second\n");
3773 else if (sfile.lineno_size)
3774 codeview_snarf_linetab(msc_dbg,
3775 modimage + sfile.symbol_size,
3776 sfile.lineno_size,
3777 pdb_file->kind == PDB_JG);
3779 pdb_free(modimage);
3781 file_name = (const char*)file + size;
3782 file_name += strlen(file_name) + 1;
3783 file = (BYTE*)((DWORD_PTR)(file_name + strlen(file_name) + 1 + 3) & ~3);
3785 /* Load the global variables and constants (if not yet loaded) and public information */
3786 if (globalimage)
3788 const BYTE* data;
3789 unsigned global_size = pdb_get_file_size(pdb_file, symbols.gsym_file);
3791 data = pdb_read_file(pdb_file, symbols.global_hash_file);
3792 if (data)
3794 codeview_snarf_sym_hashtable(msc_dbg, globalimage, global_size,
3795 data, pdb_get_file_size(pdb_file, symbols.global_hash_file),
3796 pdb_global_feed_variables);
3797 pdb_free((void*)data);
3799 if (!(dbghelp_options & SYMOPT_NO_PUBLICS) && (data = pdb_read_file(pdb_file, symbols.public_file)))
3801 const DBI_PUBLIC_HEADER* pubhdr = (const DBI_PUBLIC_HEADER*)data;
3802 codeview_snarf_sym_hashtable(msc_dbg, globalimage, pdb_get_file_size(pdb_file, symbols.gsym_file),
3803 (const BYTE*)(pubhdr + 1), pubhdr->hash_size, pdb_global_feed_public);
3804 pdb_free((void*)data);
3806 pdb_free(globalimage);
3808 HeapFree(GetProcessHeap(), 0, (DWORD*)ipi_ctp.offset);
3809 pdb_free(ipi_image);
3811 else
3812 pdb_process_symbol_imports(pcs, msc_dbg, NULL, NULL, image,
3813 pdb_lookup, pdb_module_info, module_index);
3815 pdb_free(symbols_image);
3816 pdb_free(files_image);
3818 return TRUE;
3821 static BOOL pdb_process_file(const struct process* pcs,
3822 const struct msc_debug_info* msc_dbg,
3823 struct pdb_lookup* pdb_lookup)
3825 BOOL ret;
3826 struct module_format* modfmt;
3827 struct pdb_module_info* pdb_module_info;
3829 modfmt = HeapAlloc(GetProcessHeap(), 0,
3830 sizeof(struct module_format) + sizeof(struct pdb_module_info));
3831 if (!modfmt) return FALSE;
3833 pdb_module_info = (void*)(modfmt + 1);
3834 msc_dbg->module->format_info[DFI_PDB] = modfmt;
3835 modfmt->module = msc_dbg->module;
3836 modfmt->remove = pdb_module_remove;
3837 modfmt->loc_compute = pdb_location_compute;
3838 modfmt->u.pdb_info = pdb_module_info;
3840 memset(cv_zmodules, 0, sizeof(cv_zmodules));
3841 codeview_init_basic_types(msc_dbg->module);
3842 ret = pdb_process_internal(pcs, msc_dbg, pdb_lookup,
3843 msc_dbg->module->format_info[DFI_PDB]->u.pdb_info, -1);
3844 codeview_clear_type_table();
3845 if (ret)
3847 struct pdb_module_info* pdb_info = msc_dbg->module->format_info[DFI_PDB]->u.pdb_info;
3848 msc_dbg->module->module.SymType = SymPdb;
3849 if (pdb_info->pdb_files[0].kind == PDB_JG)
3850 msc_dbg->module->module.PdbSig = pdb_info->pdb_files[0].u.jg.timestamp;
3851 else
3852 msc_dbg->module->module.PdbSig70 = pdb_info->pdb_files[0].u.ds.guid;
3853 msc_dbg->module->module.PdbAge = pdb_info->pdb_files[0].age;
3854 MultiByteToWideChar(CP_ACP, 0, pdb_lookup->filename, -1,
3855 msc_dbg->module->module.LoadedPdbName,
3856 ARRAY_SIZE(msc_dbg->module->module.LoadedPdbName));
3857 /* FIXME: we could have a finer grain here */
3858 msc_dbg->module->module.LineNumbers = TRUE;
3859 msc_dbg->module->module.GlobalSymbols = TRUE;
3860 msc_dbg->module->module.TypeInfo = TRUE;
3861 msc_dbg->module->module.SourceIndexed = TRUE;
3862 msc_dbg->module->module.Publics = TRUE;
3864 else
3866 msc_dbg->module->format_info[DFI_PDB] = NULL;
3867 HeapFree(GetProcessHeap(), 0, modfmt);
3869 return ret;
3872 BOOL pdb_fetch_file_info(const struct pdb_lookup* pdb_lookup, unsigned* matched)
3874 HANDLE hFile, hMap = NULL;
3875 char* image = NULL;
3876 BOOL ret;
3877 struct pdb_file_info pdb_file;
3879 if ((hFile = CreateFileA(pdb_lookup->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
3880 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ||
3881 ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) ||
3882 ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL))
3884 WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename);
3885 ret = FALSE;
3887 else
3889 ret = pdb_init(pdb_lookup, &pdb_file, image, matched);
3890 pdb_free_file(&pdb_file);
3893 if (image) UnmapViewOfFile(image);
3894 if (hMap) CloseHandle(hMap);
3895 if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
3897 return ret;
3900 /*========================================================================
3901 * FPO unwinding code
3904 /* Stack unwinding is based on postfixed operations.
3905 * Let's define our Postfix EValuator
3907 #define PEV_MAX_LEN 32
3908 struct pevaluator
3910 struct cpu_stack_walk* csw;
3911 struct pool pool;
3912 struct vector stack;
3913 unsigned stk_index;
3914 struct hash_table values;
3915 char error[64];
3918 struct zvalue
3920 DWORD_PTR value;
3921 struct hash_table_elt elt;
3924 #define PEV_ERROR(pev, msg) snprintf((pev)->error, sizeof((pev)->error), "%s", (msg))
3925 #define PEV_ERROR1(pev, msg, pmt) snprintf((pev)->error, sizeof((pev)->error), (msg), (pmt))
3927 #if 0
3928 static void pev_dump_stack(struct pevaluator* pev)
3930 unsigned i;
3931 FIXME("stack #%d\n", pev->stk_index);
3932 for (i = 0; i < pev->stk_index; i++)
3934 FIXME("\t%d) %s\n", i, *(char**)vector_at(&pev->stack, i));
3937 #endif
3939 /* get the value out of an operand (variable or literal) */
3940 static BOOL pev_get_val(struct pevaluator* pev, const char* str, DWORD_PTR* val)
3942 char* n;
3943 struct hash_table_iter hti;
3944 void* ptr;
3946 switch (str[0])
3948 case '$':
3949 case '.':
3950 hash_table_iter_init(&pev->values, &hti, str);
3951 while ((ptr = hash_table_iter_up(&hti)))
3953 if (!strcmp(CONTAINING_RECORD(ptr, struct zvalue, elt)->elt.name, str))
3955 *val = CONTAINING_RECORD(ptr, struct zvalue, elt)->value;
3956 return TRUE;
3959 return PEV_ERROR1(pev, "get_zvalue: no value found (%s)", str);
3960 default:
3961 *val = strtol(str, &n, 10);
3962 if (n == str || *n != '\0')
3963 return PEV_ERROR1(pev, "get_val: not a literal (%s)", str);
3964 return TRUE;
3968 /* push an operand onto the stack */
3969 static BOOL pev_push(struct pevaluator* pev, const char* elt)
3971 char** at;
3972 if (pev->stk_index < vector_length(&pev->stack))
3973 at = vector_at(&pev->stack, pev->stk_index);
3974 else
3975 at = vector_add(&pev->stack, &pev->pool);
3976 if (!at) return PEV_ERROR(pev, "push: out of memory");
3977 *at = pool_strdup(&pev->pool, elt);
3978 pev->stk_index++;
3979 return TRUE;
3982 /* pop an operand from the stack */
3983 static BOOL pev_pop(struct pevaluator* pev, char* elt)
3985 char** at = vector_at(&pev->stack, --pev->stk_index);
3986 if (!at) return PEV_ERROR(pev, "pop: stack empty");
3987 strcpy(elt, *at);
3988 return TRUE;
3991 /* pop an operand from the stack, and gets its value */
3992 static BOOL pev_pop_val(struct pevaluator* pev, DWORD_PTR* val)
3994 char p[PEV_MAX_LEN];
3996 return pev_pop(pev, p) && pev_get_val(pev, p, val);
3999 /* set var 'name' a new value (creates the var if it doesn't exist) */
4000 static BOOL pev_set_value(struct pevaluator* pev, const char* name, DWORD_PTR val)
4002 struct hash_table_iter hti;
4003 void* ptr;
4005 hash_table_iter_init(&pev->values, &hti, name);
4006 while ((ptr = hash_table_iter_up(&hti)))
4008 if (!strcmp(CONTAINING_RECORD(ptr, struct zvalue, elt)->elt.name, name))
4010 CONTAINING_RECORD(ptr, struct zvalue, elt)->value = val;
4011 break;
4014 if (!ptr)
4016 struct zvalue* zv = pool_alloc(&pev->pool, sizeof(*zv));
4017 if (!zv) return PEV_ERROR(pev, "set_value: out of memory");
4018 zv->value = val;
4020 zv->elt.name = pool_strdup(&pev->pool, name);
4021 hash_table_add(&pev->values, &zv->elt);
4023 return TRUE;
4026 /* execute a binary operand from the two top most values on the stack.
4027 * puts result on top of the stack */
4028 static BOOL pev_binop(struct pevaluator* pev, char op)
4030 char res[PEV_MAX_LEN];
4031 DWORD_PTR v1, v2, c;
4033 if (!pev_pop_val(pev, &v1) || !pev_pop_val(pev, &v2)) return FALSE;
4034 switch (op)
4036 case '+': c = v1 + v2; break;
4037 case '-': c = v1 - v2; break;
4038 case '*': c = v1 * v2; break;
4039 case '/': c = v1 / v2; break;
4040 case '%': c = v1 % v2; break;
4041 default: return PEV_ERROR1(pev, "binop: unknown op (%c)", op);
4043 snprintf(res, sizeof(res), "%Id", c);
4044 pev_push(pev, res);
4045 return TRUE;
4048 /* pops top most operand, dereference it, on pushes the result on top of the stack */
4049 static BOOL pev_deref(struct pevaluator* pev)
4051 char res[PEV_MAX_LEN];
4052 DWORD_PTR v1, v2 = 0;
4054 if (!pev_pop_val(pev, &v1)) return FALSE;
4055 if (!sw_read_mem(pev->csw, v1, &v2, pev->csw->cpu->word_size))
4056 return PEV_ERROR1(pev, "deref: cannot read mem at %Ix\n", v1);
4057 snprintf(res, sizeof(res), "%Id", v2);
4058 pev_push(pev, res);
4059 return TRUE;
4062 /* assign value to variable (from two top most operands) */
4063 static BOOL pev_assign(struct pevaluator* pev)
4065 char p2[PEV_MAX_LEN];
4066 DWORD_PTR v1;
4068 if (!pev_pop_val(pev, &v1) || !pev_pop(pev, p2)) return FALSE;
4069 if (p2[0] != '$') return PEV_ERROR1(pev, "assign: %s isn't a variable", p2);
4070 pev_set_value(pev, p2, v1);
4072 return TRUE;
4075 /* initializes the postfix evaluator */
4076 static void pev_init(struct pevaluator* pev, struct cpu_stack_walk* csw,
4077 PDB_FPO_DATA* fpoext, struct pdb_cmd_pair* cpair)
4079 pev->csw = csw;
4080 pool_init(&pev->pool, 512);
4081 vector_init(&pev->stack, sizeof(char*), 8);
4082 pev->stk_index = 0;
4083 hash_table_init(&pev->pool, &pev->values, 8);
4084 pev->error[0] = '\0';
4085 for (; cpair->name; cpair++)
4086 pev_set_value(pev, cpair->name, *cpair->pvalue);
4087 pev_set_value(pev, ".raSearchStart", fpoext->start);
4088 pev_set_value(pev, ".cbLocals", fpoext->locals_size);
4089 pev_set_value(pev, ".cbParams", fpoext->params_size);
4090 pev_set_value(pev, ".cbSavedRegs", fpoext->savedregs_size);
4093 static BOOL pev_free(struct pevaluator* pev, struct pdb_cmd_pair* cpair)
4095 DWORD_PTR val;
4097 if (cpair) for (; cpair->name; cpair++)
4099 if (pev_get_val(pev, cpair->name, &val))
4100 *cpair->pvalue = val;
4102 pool_destroy(&pev->pool);
4103 return TRUE;
4106 static BOOL pdb_parse_cmd_string(struct cpu_stack_walk* csw, PDB_FPO_DATA* fpoext,
4107 const char* cmd, struct pdb_cmd_pair* cpair)
4109 char token[PEV_MAX_LEN];
4110 char* ptok = token;
4111 const char* ptr;
4112 BOOL over = FALSE;
4113 struct pevaluator pev;
4115 if (!cmd) return FALSE;
4116 pev_init(&pev, csw, fpoext, cpair);
4117 for (ptr = cmd; !over; ptr++)
4119 if (*ptr == ' ' || (over = *ptr == '\0'))
4121 *ptok = '\0';
4123 if (!strcmp(token, "+") || !strcmp(token, "-") || !strcmp(token, "*") ||
4124 !strcmp(token, "/") || !strcmp(token, "%"))
4126 if (!pev_binop(&pev, token[0])) goto done;
4128 else if (!strcmp(token, "^"))
4130 if (!pev_deref(&pev)) goto done;
4132 else if (!strcmp(token, "="))
4134 if (!pev_assign(&pev)) goto done;
4136 else
4138 if (!pev_push(&pev, token)) goto done;
4140 ptok = token;
4142 else
4144 if (ptok - token >= PEV_MAX_LEN - 1)
4146 PEV_ERROR1(&pev, "parse: token too long (%s)", ptr - (ptok - token));
4147 goto done;
4149 *ptok++ = *ptr;
4152 pev_free(&pev, cpair);
4153 return TRUE;
4154 done:
4155 FIXME("Couldn't evaluate %s => %s\n", wine_dbgstr_a(cmd), pev.error);
4156 pev_free(&pev, NULL);
4157 return FALSE;
4160 BOOL pdb_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip,
4161 union ctx *context, struct pdb_cmd_pair *cpair)
4163 struct module_pair pair;
4164 struct pdb_module_info* pdb_info;
4165 PDB_FPO_DATA* fpoext;
4166 unsigned i, size;
4167 PDB_STRING_TABLE* strbase;
4168 BOOL ret = TRUE;
4170 if (!module_init_pair(&pair, csw->hProcess, ip)) return FALSE;
4171 if (!pair.effective->format_info[DFI_PDB]) return FALSE;
4172 pdb_info = pair.effective->format_info[DFI_PDB]->u.pdb_info;
4173 TRACE("searching %Ix => %Ix\n", ip, ip - (DWORD_PTR)pair.effective->module.BaseOfImage);
4174 ip -= (DWORD_PTR)pair.effective->module.BaseOfImage;
4176 strbase = pdb_read_strings(&pdb_info->pdb_files[0]);
4177 if (!strbase) return FALSE;
4178 fpoext = pdb_read_file(&pdb_info->pdb_files[0], pdb_info->pdb_files[0].fpoext_stream);
4179 size = pdb_get_file_size(&pdb_info->pdb_files[0], pdb_info->pdb_files[0].fpoext_stream);
4180 if (fpoext && (size % sizeof(*fpoext)) == 0)
4182 size /= sizeof(*fpoext);
4183 for (i = 0; i < size; i++)
4185 if (fpoext[i].start <= ip && ip < fpoext[i].start + fpoext[i].func_size)
4187 TRACE("\t%08x %08x %8x %8x %4x %4x %4x %08x %s\n",
4188 fpoext[i].start, fpoext[i].func_size, fpoext[i].locals_size,
4189 fpoext[i].params_size, fpoext[i].maxstack_size, fpoext[i].prolog_size,
4190 fpoext[i].savedregs_size, fpoext[i].flags,
4191 wine_dbgstr_a(pdb_get_string_table_entry(strbase, fpoext[i].str_offset)));
4192 ret = pdb_parse_cmd_string(csw, &fpoext[i],
4193 pdb_get_string_table_entry(strbase, fpoext[i].str_offset),
4194 cpair);
4195 break;
4199 else ret = FALSE;
4200 pdb_free(fpoext);
4201 pdb_free(strbase);
4203 return ret;
4206 /*========================================================================
4207 * Process CodeView debug information.
4210 #define MAKESIG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
4211 #define CODEVIEW_NB09_SIG MAKESIG('N','B','0','9')
4212 #define CODEVIEW_NB10_SIG MAKESIG('N','B','1','0')
4213 #define CODEVIEW_NB11_SIG MAKESIG('N','B','1','1')
4214 #define CODEVIEW_RSDS_SIG MAKESIG('R','S','D','S')
4216 static BOOL codeview_process_info(const struct process* pcs,
4217 const struct msc_debug_info* msc_dbg)
4219 const DWORD* signature = (const DWORD*)msc_dbg->root;
4220 BOOL ret = FALSE;
4221 struct pdb_lookup pdb_lookup;
4223 TRACE("Processing signature %.4s\n", (const char*)signature);
4225 switch (*signature)
4227 case CODEVIEW_NB09_SIG:
4228 case CODEVIEW_NB11_SIG:
4230 const OMFSignature* cv = (const OMFSignature*)msc_dbg->root;
4231 const OMFDirHeader* hdr = (const OMFDirHeader*)(msc_dbg->root + cv->filepos);
4232 const OMFDirEntry* ent;
4233 const OMFDirEntry* prev;
4234 const OMFDirEntry* next;
4235 unsigned int i;
4237 codeview_init_basic_types(msc_dbg->module);
4239 for (i = 0; i < hdr->cDir; i++)
4241 ent = (const OMFDirEntry*)((const BYTE*)hdr + hdr->cbDirHeader + i * hdr->cbDirEntry);
4242 if (ent->SubSection == sstGlobalTypes)
4244 const OMFGlobalTypes* types;
4245 struct codeview_type_parse ctp;
4247 types = (const OMFGlobalTypes*)(msc_dbg->root + ent->lfo);
4248 ctp.module = msc_dbg->module;
4249 ctp.offset = (const DWORD*)(types + 1);
4250 memset(&ctp.header, 0, sizeof(ctp.header));
4251 ctp.header.first_index = T_FIRSTDEFINABLETYPE;
4252 ctp.header.last_index = ctp.header.first_index + types->cTypes;
4253 ctp.table = (const BYTE*)(ctp.offset + types->cTypes);
4255 cv_current_module = &cv_zmodules[0];
4256 if (cv_current_module->allowed) FIXME("Already allowed??\n");
4257 cv_current_module->allowed = TRUE;
4259 codeview_parse_type_table(&ctp);
4260 break;
4264 ent = (const OMFDirEntry*)((const BYTE*)hdr + hdr->cbDirHeader);
4265 for (i = 0; i < hdr->cDir; i++, ent = next)
4267 next = (i == hdr->cDir-1) ? NULL :
4268 (const OMFDirEntry*)((const BYTE*)ent + hdr->cbDirEntry);
4269 prev = (i == 0) ? NULL :
4270 (const OMFDirEntry*)((const BYTE*)ent - hdr->cbDirEntry);
4272 if (ent->SubSection == sstAlignSym)
4274 codeview_snarf(msc_dbg, msc_dbg->root + ent->lfo, sizeof(DWORD), ent->cb, NULL);
4277 * Check the next and previous entry. If either is a
4278 * sstSrcModule, it contains the line number info for
4279 * this file.
4281 * FIXME: This is not a general solution!
4283 if (next && next->iMod == ent->iMod && next->SubSection == sstSrcModule)
4284 codeview_snarf_linetab(msc_dbg, msc_dbg->root + next->lfo,
4285 next->cb, TRUE);
4287 if (prev && prev->iMod == ent->iMod && prev->SubSection == sstSrcModule)
4288 codeview_snarf_linetab(msc_dbg, msc_dbg->root + prev->lfo,
4289 prev->cb, TRUE);
4294 msc_dbg->module->module.SymType = SymCv;
4295 /* FIXME: we could have a finer grain here */
4296 msc_dbg->module->module.LineNumbers = TRUE;
4297 msc_dbg->module->module.GlobalSymbols = TRUE;
4298 msc_dbg->module->module.TypeInfo = TRUE;
4299 msc_dbg->module->module.SourceIndexed = TRUE;
4300 msc_dbg->module->module.Publics = TRUE;
4301 codeview_clear_type_table();
4302 ret = TRUE;
4303 break;
4306 case CODEVIEW_NB10_SIG:
4308 const CODEVIEW_PDB_DATA* pdb = (const CODEVIEW_PDB_DATA*)msc_dbg->root;
4309 pdb_lookup.filename = pdb->name;
4310 pdb_lookup.kind = PDB_JG;
4311 pdb_lookup.timestamp = pdb->timestamp;
4312 pdb_lookup.age = pdb->age;
4313 ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup);
4314 break;
4316 case CODEVIEW_RSDS_SIG:
4318 const OMFSignatureRSDS* rsds = (const OMFSignatureRSDS*)msc_dbg->root;
4320 TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
4321 wine_dbgstr_guid(&rsds->guid), rsds->age, rsds->name);
4322 pdb_lookup.filename = rsds->name;
4323 pdb_lookup.kind = PDB_DS;
4324 pdb_lookup.guid = rsds->guid;
4325 pdb_lookup.age = rsds->age;
4326 ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup);
4327 break;
4329 default:
4330 ERR("Unknown CODEVIEW signature %08lx in module %s\n",
4331 *signature, debugstr_w(msc_dbg->module->modulename));
4332 break;
4334 if (ret)
4336 msc_dbg->module->module.CVSig = *signature;
4337 memcpy(msc_dbg->module->module.CVData, msc_dbg->root,
4338 sizeof(msc_dbg->module->module.CVData));
4340 return ret;
4343 /*========================================================================
4344 * Process debug directory.
4346 BOOL pe_load_debug_directory(const struct process* pcs, struct module* module,
4347 const BYTE* mapping,
4348 const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
4349 const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg)
4351 BOOL ret;
4352 int i;
4353 struct msc_debug_info msc_dbg;
4355 msc_dbg.module = module;
4356 msc_dbg.nsect = nsect;
4357 msc_dbg.sectp = sectp;
4358 msc_dbg.nomap = 0;
4359 msc_dbg.omapp = NULL;
4361 __TRY
4363 ret = FALSE;
4365 /* First, watch out for OMAP data */
4366 for (i = 0; i < nDbg; i++)
4368 if (dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC)
4370 msc_dbg.nomap = dbg[i].SizeOfData / sizeof(OMAP);
4371 msc_dbg.omapp = (const OMAP*)(mapping + dbg[i].PointerToRawData);
4372 break;
4376 /* Now, try to parse CodeView debug info */
4377 for (i = 0; i < nDbg; i++)
4379 if (dbg[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW)
4381 msc_dbg.root = mapping + dbg[i].PointerToRawData;
4382 if ((ret = codeview_process_info(pcs, &msc_dbg))) goto done;
4386 /* If not found, try to parse COFF debug info */
4387 for (i = 0; i < nDbg; i++)
4389 if (dbg[i].Type == IMAGE_DEBUG_TYPE_COFF)
4391 msc_dbg.root = mapping + dbg[i].PointerToRawData;
4392 if ((ret = coff_process_info(&msc_dbg))) goto done;
4395 done:
4396 /* FIXME: this should be supported... this is the debug information for
4397 * functions compiled without a frame pointer (FPO = frame pointer omission)
4398 * the associated data helps finding out the relevant information
4400 for (i = 0; i < nDbg; i++)
4401 if (dbg[i].Type == IMAGE_DEBUG_TYPE_FPO)
4402 FIXME("This guy has FPO information\n");
4403 #if 0
4405 #define FRAME_FPO 0
4406 #define FRAME_TRAP 1
4407 #define FRAME_TSS 2
4409 typedef struct _FPO_DATA
4411 DWORD ulOffStart; /* offset 1st byte of function code */
4412 DWORD cbProcSize; /* # bytes in function */
4413 DWORD cdwLocals; /* # bytes in locals/4 */
4414 WORD cdwParams; /* # bytes in params/4 */
4416 WORD cbProlog : 8; /* # bytes in prolog */
4417 WORD cbRegs : 3; /* # regs saved */
4418 WORD fHasSEH : 1; /* TRUE if SEH in func */
4419 WORD fUseBP : 1; /* TRUE if EBP has been allocated */
4420 WORD reserved : 1; /* reserved for future use */
4421 WORD cbFrame : 2; /* frame type */
4422 } FPO_DATA;
4423 #endif
4426 __EXCEPT_PAGE_FAULT
4428 ERR("Got a page fault while loading symbols\n");
4429 ret = FALSE;
4431 __ENDTRY
4432 return ret;