2 * File msc.c - read VC++ debug information from COFF and eventually
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.
31 * Get 16 bit CV stuff working.
32 * Add symbol size to internal symbol table.
35 #define NONAMELESSUNION
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
66 struct pdb_stream_name
* stream_dict
;
67 unsigned fpoext_stream
;
73 struct PDB_JG_TOC
* toc
;
78 struct PDB_DS_TOC
* toc
;
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
)
109 const char* hexof
= "0123456789abcdef";
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) ?
124 msg
[10 + 3 * 16] = ' ';
125 msg
[10 + 3 * 16 + 1 + 16] = '\0';
130 /*========================================================================
131 * Process CodeView type information.
134 static struct symt
* cv_basic_types
[T_MAXPREDEFINEDTYPE
];
136 struct cv_defined_module
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
++;
278 if (type
< LF_NUMERIC
)
290 V_I1(v
) = *(const char*)leaf
;
296 V_I2(v
) = *(const short*)leaf
;
308 V_I4(v
) = *(const int*)leaf
;
314 V_UI4(v
) = *(const unsigned int*)leaf
;
320 V_I8(v
) = *(const long long int*)leaf
;
326 V_UI8(v
) = *(const long long unsigned int*)leaf
;
332 V_R4(v
) = *(const float*)leaf
;
336 FIXME("Unsupported numeric leaf type %04x\n", type
);
338 V_VT(v
) = VT_EMPTY
; /* FIXME */
344 V_R8(v
) = *(const double*)leaf
;
348 FIXME("Unsupported numeric leaf type %04x\n", type
);
350 V_VT(v
) = VT_EMPTY
; /* FIXME */
354 FIXME("Unsupported numeric leaf type %04x\n", type
);
356 V_VT(v
) = VT_EMPTY
; /* FIXME */
360 FIXME("Unsupported numeric leaf type %04x\n", type
);
362 V_VT(v
) = VT_EMPTY
; /* FIXME */
366 FIXME("Unsupported numeric leaf type %04x\n", type
);
368 V_VT(v
) = VT_EMPTY
; /* FIXME */
372 FIXME("Unsupported numeric leaf type %04x\n", type
);
377 FIXME("Unsupported numeric leaf type %04x\n", type
);
379 V_VT(v
) = VT_EMPTY
; /* FIXME */
383 FIXME("Unsupported numeric leaf type %04x\n", type
);
385 V_VT(v
) = VT_EMPTY
; /* FIXME */
389 FIXME("Unknown numeric leaf type %04x\n", type
);
390 V_VT(v
) = VT_EMPTY
; /* FIXME */
398 static int numeric_leaf(int* value
, const unsigned short int* leaf
)
400 unsigned short int type
= *leaf
++;
403 if (type
< LF_NUMERIC
)
413 *value
= *(const char*)leaf
;
418 *value
= *(const short*)leaf
;
428 *value
= *(const int*)leaf
;
433 *value
= *(const unsigned int*)leaf
;
438 FIXME("Unsupported numeric leaf type %04x\n", type
);
440 *value
= 0; /* FIXME */
444 FIXME("Unsupported numeric leaf type %04x\n", type
);
446 *value
= 0; /* FIXME */
450 FIXME("Unsupported numeric leaf type %04x\n", type
);
452 *value
= 0; /* FIXME */
456 FIXME("Unsupported numeric leaf type %04x\n", type
);
458 *value
= 0; /* FIXME */
462 FIXME("Unsupported numeric leaf type %04x\n", type
);
464 *value
= 0; /* FIXME */
468 FIXME("Unsupported numeric leaf type %04x\n", type
);
470 *value
= 0; /* FIXME */
474 FIXME("Unsupported numeric leaf type %04x\n", type
);
476 *value
= 0; /* FIXME */
480 FIXME("Unsupported numeric leaf type %04x\n", type
);
482 *value
= 0; /* FIXME */
486 FIXME("Unsupported numeric leaf type %04x\n", type
);
488 *value
= 0; /* FIXME */
492 FIXME("Unsupported numeric leaf type %04x\n", type
);
494 *value
= 0; /* FIXME */
498 FIXME("Unsupported numeric leaf type %04x\n", type
);
500 *value
= 0; /* FIXME */
504 FIXME("Unknown numeric leaf type %04x\n", type
);
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
);
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
);
560 struct hash_link
* next
;
563 struct codeview_type_parse
565 struct module
* module
;
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
)
583 if (!cv_current_module
)
585 FIXME("Adding %x to non allowed module\n", typeno
);
588 if ((typeno
>> 24) != 0)
589 FIXME("No module index while inserting type-id assumption is wrong %x\n",
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
);
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
;
607 static void codeview_clear_type_table(void)
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
,
625 const union codeview_type
* type
);
627 static struct symt
* codeview_fetch_type(struct codeview_type_parse
* ctp
,
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
);
642 static UINT32
codeview_compute_hash(const char* ptr
, unsigned len
)
644 const char* last
= ptr
+ len
;
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
)
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
)
678 case LF_STRUCTURE_V1
:
679 case LF_STRUCTURE_V2
:
680 case LF_STRUCTURE_V3
:
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;
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
)
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
:
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
);
729 case LF_STRUCTURE_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
);
734 case LF_STRUCTURE_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
;
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
);
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
);
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
;
754 p_name
= &cvtype
->enumeration_v1
.p_name
;
757 p_name
= &cvtype
->enumeration_v2
.p_name
;
760 c_name
= cvtype
->enumeration_v3
.name
;
761 decorated
= cvtype
->union_v3
.property
.has_decorated_name
;
768 *name
= p_name
->name
;
769 *len
= p_name
->namelen
;
770 *decorated_name
= NULL
;
776 *len
= strlen(c_name
);
777 *decorated_name
= decorated
? (c_name
+ *len
+ 1) : NULL
;
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
;
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
;
800 const char* decoratedref
;
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
;
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
);
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
,
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
);
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
,
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;
880 if (*ptr
>= 0xf0) /* LF_PAD... */
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
);
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
));
910 if (!codeview_add_type_enum_field_list(ctp
, symt
, type
->index_v1
.ref
))
916 if (!codeview_add_type_enum_field_list(ctp
, symt
, type
->index_v2
.ref
))
922 FIXME("Unsupported type %04x in ENUM field list\n", type
->generic
.id
);
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
)
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
);
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
);
954 subtype
= codeview_fetch_type(ctp
, type
);
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
;
971 const struct p_string
* p_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;
983 if (*ptr
>= 0xf0) /* LF_PAD... */
989 type
= (const union codeview_fieldtype
*)ptr
;
991 switch (type
->generic
.id
)
994 leaf_len
= numeric_leaf(&value
, &type
->bclass_v1
.offset
);
996 /* FIXME: ignored for now */
998 ptr
+= 2 + 2 + 2 + leaf_len
;
1002 leaf_len
= numeric_leaf(&value
, &type
->bclass_v2
.offset
);
1004 /* FIXME: ignored for now */
1006 ptr
+= 2 + 2 + 4 + leaf_len
;
1010 case LF_IVBCLASS_V1
:
1012 const unsigned short int* p_vboff
;
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
;
1025 case LF_IVBCLASS_V2
:
1027 const unsigned short int* p_vboff
;
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
;
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
);
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
);
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);
1068 case LF_STMEMBER_V1
:
1069 /* FIXME: ignored for now */
1070 ptr
+= 2 + 2 + 2 + (1 + type
->stmember_v1
.p_name
.namelen
);
1073 case LF_STMEMBER_V2
:
1074 /* FIXME: ignored for now */
1075 ptr
+= 2 + 4 + 2 + (1 + type
->stmember_v2
.p_name
.namelen
);
1078 case LF_STMEMBER_V3
:
1079 /* FIXME: ignored for now */
1080 ptr
+= 2 + 4 + 2 + (strlen(type
->stmember_v3
.name
) + 1);
1084 /* FIXME: ignored for now */
1085 ptr
+= 2 + 2 + 2 + (1 + type
->method_v1
.p_name
.namelen
);
1089 /* FIXME: ignored for now */
1090 ptr
+= 2 + 2 + 4 + (1 + type
->method_v2
.p_name
.namelen
);
1094 /* FIXME: ignored for now */
1095 ptr
+= 2 + 2 + 4 + (strlen(type
->method_v3
.name
) + 1);
1098 case LF_NESTTYPE_V1
:
1099 /* FIXME: ignored for now */
1100 ptr
+= 2 + 2 + (1 + type
->nesttype_v1
.p_name
.namelen
);
1103 case LF_NESTTYPE_V2
:
1104 /* FIXME: ignored for now */
1105 ptr
+= 2 + 2 + 4 + (1 + type
->nesttype_v2
.p_name
.namelen
);
1108 case LF_NESTTYPE_V3
:
1109 /* FIXME: ignored for now */
1110 ptr
+= 2 + 2 + 4 + (strlen(type
->nesttype_v3
.name
) + 1);
1113 case LF_VFUNCTAB_V1
:
1114 /* FIXME: ignored for now */
1118 case LF_VFUNCTAB_V2
:
1119 /* FIXME: ignored for now */
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
);
1132 ptr
+= 2 + 2 + 2 + (1 + type
->onemethod_v1
.p_name
.namelen
);
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
);
1146 ptr
+= 2 + 2 + 4 + (1 + type
->onemethod_v2
.p_name
.namelen
);
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);
1160 ptr
+= 2 + 2 + 4 + (strlen(type
->onemethod_v3
.name
) + 1);
1166 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v1
.ref
))
1172 if (!codeview_add_type_struct_field_list(ctp
, symt
, type
->index_v2
.ref
))
1178 FIXME("Unsupported type %04x in STRUCT field list\n", type
->generic
.id
);
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
);
1195 static void codeview_add_func_signature_args(struct codeview_type_parse
* ctp
,
1196 struct symt_function_signature
* sym
,
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
)))
1206 switch (reftype
->generic
.id
)
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
]));
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
]));
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
,
1226 const union codeview_type
* type
)
1228 struct symt
* symt
= NULL
;
1229 int value
, leaf_len
;
1230 const struct p_string
* p_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
);
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
);
1259 symt
= codeview_add_type_pointer(ctp
, type
->pointer_v1
.datatype
);
1262 symt
= codeview_add_type_pointer(ctp
, type
->pointer_v2
.datatype
);
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
);
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
);
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
);
1289 case LF_STRUCTURE_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
);
1296 case LF_STRUCTURE_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
);
1303 case LF_STRUCTURE_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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1389 /* this is an ugly hack... FIXME when we have C++ support */
1392 snprintf(buf
, sizeof(buf
), "__internal_vt_shape_%x\n", curr_type
);
1393 symt
= &symt_new_udt(ctp
->module
, buf
, 0, UdtStruct
)->symt
;
1397 FIXME("Unsupported type-id leaf %x\n", type
->generic
.id
);
1398 dump(type
, 2 + type
->generic
.len
);
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
)
1408 int value
, leaf_len
;
1409 const struct p_string
* p_name
;
1412 switch (type
->generic
.id
)
1414 case LF_STRUCTURE_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
;
1422 case LF_STRUCTURE_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
;
1430 case LF_STRUCTURE_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
;
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
;
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
;
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
;
1457 symt
= &symt_new_enum(ctp
->module
, terminate_string(&type
->enumeration_v1
.p_name
), NULL
)->symt
;
1461 symt
= &symt_new_enum(ctp
->module
, terminate_string(&type
->enumeration_v2
.p_name
), NULL
)->symt
;
1465 symt
= &symt_new_enum(ctp
->module
, type
->enumeration_v3
.name
, NULL
)->symt
;
1468 default: symt
= NULL
;
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
)
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
))
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
)))
1530 if ((symt
= codeview_load_forwardable_type(ctp
, codeview_jump_to_type(ctp
, impl_type
))))
1531 codeview_add_type(impl_type
, symt
);
1533 FIXME("forward def of %x => %x, unable to load impl\n", hl
->id
, impl_type
);
1537 /* forward type definition without implementation, create empty type */
1538 symt
= codeview_load_forwardable_type(ctp
, type
);
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
);
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
;
1577 const unsigned int* filetab
;
1578 const unsigned int* lt_ptr
;
1579 const unsigned short* linenos
;
1580 const struct startend
* start
;
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.
1600 source
= source_new(msc_dbg
->module
, NULL
, terminate_string((const struct p_string
*)(start
+ nseg
)));
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*)<b
->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);
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
)
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
;
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
)
1662 TRACE("No DEBUG_S_FILECHKSMS found\n");
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 */
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");
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);
1701 symt_add_func_line(msc_dbg
->module
, func
, source
,
1702 lines
[i
].linenumStart
, lineblk_base
+ lines
[i
].offset
);
1705 case DEBUG_S_FILECHKSMS
: /* skip */
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
;
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
);
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
)
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
))
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
,
1770 unsigned segment
, unsigned offset
,
1771 unsigned symtype
, BOOL is_local
, BOOL in_tls
, BOOL dontcheck
)
1775 struct location loc
;
1777 loc
.kind
= in_tls
? loc_tlsrel
: loc_absolute
;
1779 loc
.offset
= in_tls
? offset
: codeview_get_address(msc_dbg
, segment
, offset
);
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
);
1787 if (!dontcheck
&& !in_tls
)
1789 /* Check that we don't add twice the same variable */
1790 struct hash_table_iter hti
;
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')
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 */
1826 unsigned short rangelen
; /* after 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 */
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
);
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
)
1908 codeview_xform_range(msc_dbg
, locinfo
, &symrange
->defrange_v3
.range
);
1909 /* FIXME: transformation unsupported; let loc_compute bark if actually needed */
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 */
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
);
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
);
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
);
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
;
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
);
1941 gap
= codeview_get_gaps(symrange
);
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
);
1955 *(DWORD
*)locinfo
= 0; /* store terminating kind == 0 */
1959 loc
->kind
= loc_error
;
1960 loc
->reg
= loc_err_internal
;
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);
1977 else if ((*ptr
& 0xE0) == 0xC0)
1979 res
= (*ptr
++ & 0x1f) << 24;
1980 res
|= *ptr
++ << 16;
1984 else res
= (unsigned)(-1);
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;
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;
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
,
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
;
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
;
2069 inlsrcex
= CV_RECORD_GAP(inlsrcex
, inlsrcex
->countOfExtraFiles
* sizeof(inlsrcex
->extraFileId
[0]));
2073 FIXME("Unknown signature %lx in INLINEELINES subsection\n", *(DWORD
*)CV_RECORD_AFTER(hdr
));
2080 static inline void inline_site_update_last_range(struct symt_inlinesite
* inlined
, ULONG_PTR hi
)
2082 unsigned num
= inlined
->vranges
.num_elts
;
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
)
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
);
2114 /* grasp first code offset in binary annotation to compute inline site start address */
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
)
2126 else if (cvba
.opcode
== BA_OP_ChangeCodeLengthAndCodeOffset
)
2135 WARN("Couldn't find start address of inlined\n");
2139 switch (cvt
->generic
.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
));
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
));
2153 FIXME("unsupported inlinee kind %x\n", cvt
->generic
.id
);
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
)
2164 if (!hdr_files
) return FALSE
;
2165 srcok
= cv_dbgsubsect_find_inlinee(msc_dbg
, inlinee
, cvmod
, hdr_files
, &srcfile
, &line
);
2170 /* rescan all annotations and store ranges & line information */
2173 cvba
.last_annot
= last_annot
;
2175 while (codeview_advance_binannot(&cvba
))
2177 switch (cvba
.opcode
)
2179 case BA_OP_CodeOffset
:
2182 case BA_OP_ChangeCodeOffset
:
2183 offset
+= cvba
.arg1
;
2184 inline_site_update_last_range(inlined
, top_func
->address
+ offset
);
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
);
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
);
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
));
2202 case BA_OP_ChangeLineOffset
:
2203 line
+= binannot_getsigned(cvba
.arg1
);
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
);
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
);
2213 case BA_OP_ChangeCodeLengthAndCodeOffset
:
2214 offset
+= cvba
.arg2
;
2215 inline_site_update_last_range(inlined
, top_func
->address
+ offset
);
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
);
2221 WARN("Unsupported op %d\n", cvba
.opcode
);
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
);
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
;
2242 struct symt_block
* block
= NULL
;
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.
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
);
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
);
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
);
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
);
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
);
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
);
2304 /* Public symbols */
2310 /* will be handled later on in codeview_snarf_public */
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.
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
);
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
);
2332 * Global and static functions.
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
);
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
);
2366 if (top_func
) FIXME("nested function\n");
2367 top_func
= symt_new_function(msc_dbg
->module
, compiland
,
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
);
2380 * Function parameters and stack variables.
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
,
2390 codeview_get_type(sym
->stack_v1
.symtype
, FALSE
),
2391 terminate_string(&sym
->stack_v1
.p_name
));
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
,
2401 codeview_get_type(sym
->stack_v2
.symtype
, FALSE
),
2402 terminate_string(&sym
->stack_v2
.p_name
));
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
,
2414 codeview_get_type(sym
->stack_v3
.symtype
, FALSE
),
2415 sym
->stack_v3
.name
);
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
,
2427 codeview_get_type(sym
->regrel_v3
.symtype
, FALSE
),
2428 sym
->regrel_v3
.name
);
2431 case S_REGISTER_16t
:
2432 loc
.kind
= loc_register
;
2433 loc
.reg
= sym
->register_v1
.reg
;
2435 symt_add_func_local(msc_dbg
->module
, curr_func
,
2437 block
, codeview_get_type(sym
->register_v1
.type
, FALSE
),
2438 terminate_string(&sym
->register_v1
.p_name
));
2441 loc
.kind
= loc_register
;
2442 loc
.reg
= sym
->register_v2
.reg
;
2444 symt_add_func_local(msc_dbg
->module
, curr_func
,
2446 block
, codeview_get_type(sym
->register_v2
.type
, FALSE
),
2447 terminate_string(&sym
->register_v2
.p_name
));
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
;
2455 symt_add_func_local(msc_dbg
->module
, curr_func
,
2457 block
, codeview_get_type(sym
->register_v3
.type
, FALSE
),
2458 sym
->register_v3
.name
);
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
;
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
;
2475 block
= symt_close_func_block(msc_dbg
->module
, curr_func
, block
);
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
;
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
));
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
));
2495 TRACE("S-Compile-V3 machine:%x language:%x %s\n", sym
->compile2_v3
.machine
, sym
->compile2_v3
.flags
.iLanguage
, sym
->compile2_v3
.name
);
2499 TRACE("S-Compile3-V3 machine:%x language:%x %s\n", sym
->compile3_v3
.machine
, sym
->compile3_v3
.flags
.iLanguage
, sym
->compile3_v3
.name
);
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
));
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
)));
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
));
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
));
2543 case S_CONSTANT_16t
:
2546 const struct p_string
* name
;
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
),
2563 const struct p_string
* name
;
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
),
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
);
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
));
2602 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2603 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
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
));
2613 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2614 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
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
);
2623 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2624 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
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
,
2638 codeview_get_type(sym
->local_v3
.symtype
, FALSE
),
2639 sym
->local_v3
.name
);
2642 length
+= codeview_defrange_length(sym
);
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
);
2653 curr_func
= (struct symt_function
*)inlined
;
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
;
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
);
2674 curr_func
= (struct symt_function
*)inlined
;
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
;
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
);
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.
2704 name
= (const char*)sym
+ length
;
2705 length
+= (*name
+ 1 + 3) & ~3;
2710 TRACE("Start search: seg=0x%x at offset 0x%08x\n",
2711 sym
->ssearch_v1
.segment
, sym
->ssearch_v1
.offset
);
2715 TRACE("S-Align V1\n");
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
);
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
;
2737 WARN("Couldn't find function referenced by S_SEPCODE at %04x:%08x\n",
2738 sym
->sepcode_v3
.sectParent
, sym
->sepcode_v3
.offParent
);
2741 FIXME("S_SEPCODE inside top-level function %s\n", top_func
->hash_elt
.name
);
2744 /* the symbols we can safely ignore for now */
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
:
2768 TRACE("Unsupported symbol id %x\n", sym
->generic
.id
);
2772 FIXME("Unsupported symbol id %x\n", sym
->generic
.id
);
2773 dump(sym
, 2 + sym
->generic
.len
);
2777 if (cvmod
) codeview_snarf_linetab2(msc_dbg
, cvmod
);
2781 static BOOL
codeview_is_inside(const struct cv_local_info
* locinfo
, const struct symt_function
* func
, DWORD_PTR ip
)
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
)
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
;
2802 case loc_cv_local_range
:
2803 for (locinfo
= (const struct cv_local_info
*)loc
->offset
;
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
)
2811 case S_DEFRANGE_SUBFIELD
:
2813 FIXME("Unsupported defrange %d\n", locinfo
->kind
);
2814 loc
->kind
= loc_error
;
2815 loc
->reg
= loc_err_internal
;
2817 case S_DEFRANGE_SUBFIELD_REGISTER
:
2818 FIXME("sub-field part not handled\n");
2820 case S_DEFRANGE_REGISTER
:
2821 loc
->kind
= loc_register
;
2822 loc
->reg
= locinfo
->reg
;
2824 case S_DEFRANGE_REGISTER_REL
:
2825 loc
->kind
= loc_regrel
;
2826 loc
->reg
= locinfo
->reg
;
2827 loc
->offset
= locinfo
->offset
;
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
;
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");
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
);
2884 static BOOL
pdb_global_feed_types(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
2887 switch (sym
->generic
.id
)
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
));
2896 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2897 terminate_string(&sym
->udt_v1
.p_name
), sym
->udt_v1
.type
);
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
));
2907 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2908 terminate_string(&sym
->udt_v2
.p_name
), sym
->udt_v2
.type
);
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
);
2917 FIXME("S-Udt %s: couldn't find type 0x%x\n",
2918 sym
->udt_v3
.name
, sym
->udt_v3
.type
);
2921 default: return FALSE
;
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
)
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
);
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
);
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
);
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
);
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
);
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
);
2965 default: return FALSE
;
2970 static BOOL
pdb_global_feed_public(const struct msc_debug_info
* msc_dbg
, const union codeview_symbol
* sym
)
2972 switch (sym
->generic
.id
)
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);
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);
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);
2992 default: return FALSE
;
2997 /*========================================================================
3001 static void* pdb_jg_read(const struct PDB_JG_HEADER
* pdb
, const WORD
* block_list
,
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
);
3019 static void* pdb_ds_read(const struct PDB_DS_HEADER
* pdb
, const UINT
*block_list
,
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
);
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
;
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
;
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
,
3071 switch (pdb_file
->kind
)
3074 return pdb_read_jg_file((const struct PDB_JG_HEADER
*)pdb_file
->image
,
3075 pdb_file
->u
.jg
.toc
, file_nr
);
3077 return pdb_read_ds_file((const struct PDB_DS_HEADER
*)pdb_file
->image
,
3078 pdb_file
->u
.ds
.toc
, file_nr
);
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
];
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
)
3103 pdb_free(pdb_file
->u
.jg
.toc
);
3104 pdb_file
->u
.jg
.toc
= NULL
;
3107 pdb_free(pdb_file
->u
.ds
.toc
);
3108 pdb_file
->u
.ds
.toc
= NULL
;
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
)
3122 pdw
= (DWORD
*)(str
+ cb
);
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 */
3133 pdw
+= *ok_bits
++ + 1;
3136 FIXME("unexpected value\n");
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
++;
3151 pdb_file
->stream_dict
[numok
].name
= NULL
;
3152 pdb_file
->fpoext_stream
= -1;
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
;
3167 static PDB_STRING_TABLE
* pdb_read_strings(const struct pdb_file_info
* pdb_file
)
3170 PDB_STRING_TABLE
*ret
;
3172 idx
= pdb_get_stream_by_name(pdb_file
, "/names");
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
;
3180 WARN("string table not found\n");
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
)
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
;
3222 /* New version of the types record header */
3223 *types
= *(const PDB_TYPES
*)image
;
3228 static void pdb_convert_symbols_header(PDB_SYMBOLS
* symbols
,
3229 int* header_size
, const BYTE
* image
)
3231 memset(symbols
, 0, sizeof(PDB_SYMBOLS
));
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
);
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;
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
];
3289 switch (lookup
->kind
)
3292 ret
= path_find_symbol_file(pcs
, module
, lookup
->filename
, DMT_PDB
, NULL
, lookup
->timestamp
,
3293 lookup
->age
, dbg_file_path
, &module
->module
.PdbUnmatched
);
3296 ret
= path_find_symbol_file(pcs
, module
, lookup
->filename
, DMT_PDB
, &lookup
->guid
, 0,
3297 lookup
->age
, dbg_file_path
, &module
->module
.PdbUnmatched
);
3302 WARN("\tCouldn't find %s\n", lookup
->filename
);
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
);
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
,
3337 ctp
->hash_stream
= NULL
;
3340 ctp
->alloc_hash
= NULL
;
3341 if (!pdb_convert_types_header(&ctp
->header
, image
))
3344 /* Check for unknown versions */
3345 switch (ctp
->header
.version
)
3347 case 19950410: /* VC 4.0 */
3349 case 19961031: /* VC 5.0 / 6.0 */
3350 case 19990903: /* VC 7.0 */
3351 case 20040203: /* VC 8.0 */
3354 ERR("-Unknown type info version %d\n", ctp
->header
.version
);
3357 if (ctp
->header
.hash_size
!= 2 && ctp
->header
.hash_size
!= 4)
3359 ERR("-Unsupported hash of size %u\n", ctp
->header
.hash_size
);
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");
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 */
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
))
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 */
3424 hl
->next
= ctp
->hash
[hash_i
];
3425 ctp
->hash
[hash_i
] = hl
;
3434 pdb_dispose_type_parse(ctp
);
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);
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 /******************************************************************
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
)
3473 /* check the file header, and if ok, load the TOC */
3474 TRACE("PDB(%s): %.40s\n", pdb_lookup
->filename
, debugstr_an(image
, 40));
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);
3486 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup
->filename
);
3489 switch (root
->Version
)
3491 case 19950623: /* VC 4.0 */
3493 case 19960307: /* VC 5.0 */
3494 case 19970604: /* VC 6.0 */
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
);
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
);
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
),
3527 root
= pdb_read_ds_file(pdb
, pdb_file
->u
.ds
.toc
, 1);
3530 ERR("-Unable to get root from .PDB in %s\n", pdb_lookup
->filename
);
3533 switch (root
->Version
)
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
);
3557 if (0) /* some tool to dump the internal files from a PDB file */
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
));
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
,
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
;
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
);
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
;
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
);
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)
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
)
3656 BYTE
* symbols_image
= NULL
;
3657 PDB_STRING_TABLE
* files_image
= NULL
;
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
);
3672 if (!pdb_init(pdb_lookup
, pdb_file
, image
, &matched
) || matched
!= 2)
3675 UnmapViewOfFile(image
);
3679 pdb_file
->hMap
= hMap
;
3680 pdb_file
->image
= image
;
3681 symbols_image
= pdb_read_file(pdb_file
, 3);
3684 PDB_SYMBOLS symbols
;
3688 struct codeview_type_parse ipi_ctp
;
3690 int header_size
= 0;
3691 PDB_STREAM_INDEXES
* psi
;
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 */
3703 ERR("-Unknown symbol info version %u %08x\n",
3704 symbols
.version
, symbols
.version
);
3707 switch (symbols
.stream_index_size
)
3710 case sizeof(PDB_STREAM_INDEXES_OLD
):
3711 /* no fpo ext stream in this case */
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
;
3721 FIXME("Unknown PDB_STREAM_INDEXES size (%u)\n", symbols
.stream_index_size
);
3722 pdb_free(symbols_image
);
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
);
3741 unsigned global_size
= pdb_get_file_size(pdb_file
, symbols
.gsym_file
);
3743 data
= pdb_read_file(pdb_file
, symbols
.global_hash_file
);
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
;
3761 HeapValidate(GetProcessHeap(), 0, NULL
);
3762 pdb_convert_symbol_file(&symbols
, &sfile
, &size
, file
);
3764 modimage
= pdb_read_file(pdb_file
, sfile
.file
);
3767 struct cv_module_snarf cvmod
= {ipi_ok
? &ipi_ctp
: NULL
, (const void*)(modimage
+ sfile
.symbol_size
), sfile
.lineno2_size
,
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
,
3777 pdb_file
->kind
== PDB_JG
);
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 */
3789 unsigned global_size
= pdb_get_file_size(pdb_file
, symbols
.gsym_file
);
3791 data
= pdb_read_file(pdb_file
, symbols
.global_hash_file
);
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
);
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
);
3821 static BOOL
pdb_process_file(const struct process
* pcs
,
3822 const struct msc_debug_info
* msc_dbg
,
3823 struct pdb_lookup
* pdb_lookup
)
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();
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
;
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
;
3866 msc_dbg
->module
->format_info
[DFI_PDB
] = NULL
;
3867 HeapFree(GetProcessHeap(), 0, modfmt
);
3872 BOOL
pdb_fetch_file_info(const struct pdb_lookup
* pdb_lookup
, unsigned* matched
)
3874 HANDLE hFile
, hMap
= NULL
;
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
);
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
);
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
3910 struct cpu_stack_walk
* csw
;
3912 struct vector stack
;
3914 struct hash_table values
;
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))
3928 static void pev_dump_stack(struct pevaluator
* pev
)
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
));
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
)
3943 struct hash_table_iter hti
;
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
;
3959 return PEV_ERROR1(pev
, "get_zvalue: no value found (%s)", str
);
3961 *val
= strtol(str
, &n
, 10);
3962 if (n
== str
|| *n
!= '\0')
3963 return PEV_ERROR1(pev
, "get_val: not a literal (%s)", str
);
3968 /* push an operand onto the stack */
3969 static BOOL
pev_push(struct pevaluator
* pev
, const char* elt
)
3972 if (pev
->stk_index
< vector_length(&pev
->stack
))
3973 at
= vector_at(&pev
->stack
, pev
->stk_index
);
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
);
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");
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
;
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
;
4016 struct zvalue
* zv
= pool_alloc(&pev
->pool
, sizeof(*zv
));
4017 if (!zv
) return PEV_ERROR(pev
, "set_value: out of memory");
4020 zv
->elt
.name
= pool_strdup(&pev
->pool
, name
);
4021 hash_table_add(&pev
->values
, &zv
->elt
);
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
;
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
);
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
);
4062 /* assign value to variable (from two top most operands) */
4063 static BOOL
pev_assign(struct pevaluator
* pev
)
4065 char p2
[PEV_MAX_LEN
];
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
);
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
)
4080 pool_init(&pev
->pool
, 512);
4081 vector_init(&pev
->stack
, sizeof(char*), 8);
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
)
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
);
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
];
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'))
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
;
4138 if (!pev_push(&pev
, token
)) goto done
;
4144 if (ptok
- token
>= PEV_MAX_LEN
- 1)
4146 PEV_ERROR1(&pev
, "parse: token too long (%s)", ptr
- (ptok
- token
));
4152 pev_free(&pev
, cpair
);
4155 FIXME("Couldn't evaluate %s => %s\n", wine_dbgstr_a(cmd
), pev
.error
);
4156 pev_free(&pev
, NULL
);
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
;
4167 PDB_STRING_TABLE
* strbase
;
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
),
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
;
4221 struct pdb_lookup pdb_lookup
;
4223 TRACE("Processing signature %.4s\n", (const char*)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
;
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
);
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
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
,
4287 if (prev
&& prev
->iMod
== ent
->iMod
&& prev
->SubSection
== sstSrcModule
)
4288 codeview_snarf_linetab(msc_dbg
, msc_dbg
->root
+ prev
->lfo
,
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();
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
);
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
);
4330 ERR("Unknown CODEVIEW signature %08lx in module %s\n",
4331 *signature
, debugstr_w(msc_dbg
->module
->modulename
));
4336 msc_dbg
->module
->module
.CVSig
= *signature
;
4337 memcpy(msc_dbg
->module
->module
.CVData
, msc_dbg
->root
,
4338 sizeof(msc_dbg
->module
->module
.CVData
));
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
)
4353 struct msc_debug_info msc_dbg
;
4355 msc_dbg
.module
= module
;
4356 msc_dbg
.nsect
= nsect
;
4357 msc_dbg
.sectp
= sectp
;
4359 msc_dbg
.omapp
= NULL
;
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
);
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
;
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");
4406 #define FRAME_TRAP 1
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 */
4428 ERR("Got a page fault while loading symbols\n");